summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephen Smalley <sds@tycho.nsa.gov>2015-02-02 23:18:26 +0000
committerAndroid Git Automerger <android-git-automerger@android.com>2015-02-02 23:18:26 +0000
commitc4fd7ffc8bd2b865a093011aeb11ec37fa127b8d (patch)
tree4760e68399f67c4a904389bf8759b2f25e79be1e
parent9d2c287eac72e70c9df9da7772d44f7e8c5b0b51 (diff)
parent2afd4debfa6d58909cf0a6a31194bf2c7c7c55dd (diff)
downloadlibsepol-c4fd7ffc8bd2b865a093011aeb11ec37fa127b8d.tar.gz
am 2afd4deb: Update to libsepol 2.4.
* commit '2afd4debfa6d58909cf0a6a31194bf2c7c7c55dd': Update to libsepol 2.4.
-rw-r--r--.gitignore1
-rw-r--r--ChangeLog26
-rw-r--r--Makefile4
-rw-r--r--VERSION2
-rw-r--r--cil/.gitignore12
-rw-r--r--cil/COPYING32
-rw-r--r--cil/Makefile102
-rw-r--r--cil/README75
-rw-r--r--cil/docs/CIL_Reference_Guide.xml581
-rw-r--r--cil/docs/Makefile50
-rw-r--r--cil/docs/cil_access_vector_rules.xml279
-rw-r--r--cil/docs/cil_call_macro_statements.xml174
-rw-r--r--cil/docs/cil_class_and_permission_statements.xml493
-rw-r--r--cil/docs/cil_conditional_statements.xml269
-rw-r--r--cil/docs/cil_constraint_statements.xml363
-rw-r--r--cil/docs/cil_container_statements.xml398
-rw-r--r--cil/docs/cil_context_statement.xml100
-rw-r--r--cil/docs/cil_default_object_statements.xml215
-rw-r--r--cil/docs/cil_design.diabin0 -> 6784 bytes
-rw-r--r--cil/docs/cil_design.jpegbin0 -> 141777 bytes
-rw-r--r--cil/docs/cil_file_labeling_statements.xml302
-rw-r--r--cil/docs/cil_mls_labeling_statements.xml733
-rw-r--r--cil/docs/cil_network_labeling_statements.xml234
-rw-r--r--cil/docs/cil_policy_config_statements.xml118
-rw-r--r--cil/docs/cil_role_statements.xml374
-rw-r--r--cil/docs/cil_sid_statements.xml142
-rw-r--r--cil/docs/cil_type_statements.xml581
-rw-r--r--cil/docs/cil_user_statements.xml420
-rw-r--r--cil/docs/cil_xen_statements.xml183
-rw-r--r--cil/docs/secilc.8.xml89
-rw-r--r--cil/include/cil/cil.h69
-rw-r--r--cil/secilc.c353
-rw-r--r--cil/src/cil.c2307
-rw-r--r--cil/src/cil_binary.c3751
-rw-r--r--cil/src/cil_binary.h436
-rw-r--r--cil/src/cil_build_ast.c5927
-rw-r--r--cil/src/cil_build_ast.h219
-rw-r--r--cil/src/cil_copy_ast.c1939
-rw-r--r--cil/src/cil_copy_ast.h117
-rw-r--r--cil/src/cil_flavor.h185
-rw-r--r--cil/src/cil_fqn.c221
-rw-r--r--cil/src/cil_fqn.h38
-rw-r--r--cil/src/cil_internal.h960
-rw-r--r--cil/src/cil_lexer.h53
-rw-r--r--cil/src/cil_lexer.l93
-rw-r--r--cil/src/cil_list.c218
-rw-r--r--cil/src/cil_list.h61
-rw-r--r--cil/src/cil_log.c67
-rw-r--r--cil/src/cil_log.h39
-rw-r--r--cil/src/cil_mem.c100
-rw-r--r--cil/src/cil_mem.h41
-rw-r--r--cil/src/cil_parser.c134
-rw-r--r--cil/src/cil_parser.h37
-rw-r--r--cil/src/cil_policy.c1435
-rw-r--r--cil/src/cil_policy.h47
-rw-r--r--cil/src/cil_post.c1726
-rw-r--r--cil/src/cil_post.h51
-rw-r--r--cil/src/cil_reset_ast.c519
-rw-r--r--cil/src/cil_reset_ast.h8
-rw-r--r--cil/src/cil_resolve_ast.c3798
-rw-r--r--cil/src/cil_resolve_ast.h100
-rw-r--r--cil/src/cil_stack.c111
-rw-r--r--cil/src/cil_stack.h62
-rw-r--r--cil/src/cil_strpool.c104
-rw-r--r--cil/src/cil_strpool.h38
-rw-r--r--cil/src/cil_symtab.c273
-rw-r--r--cil/src/cil_symtab.h90
-rw-r--r--cil/src/cil_tree.c1620
-rw-r--r--cil/src/cil_tree.h71
-rw-r--r--cil/src/cil_verify.c1570
-rw-r--r--cil/src/cil_verify.h73
-rw-r--r--cil/test/integration.cil223
-rw-r--r--cil/test/integration_testing/mls_policy.cil115
-rw-r--r--cil/test/integration_testing/nonmls.cil86
-rw-r--r--cil/test/integration_testing/nonmls.conf76
-rw-r--r--cil/test/integration_testing/ordered_lists_bad1.cil42
-rw-r--r--cil/test/integration_testing/ordered_lists_bad2.cil43
-rw-r--r--cil/test/integration_testing/ordered_lists_bad3.cil43
-rw-r--r--cil/test/integration_testing/ordered_lists_easy.cil38
-rw-r--r--cil/test/integration_testing/ordered_lists_hard.cil43
-rw-r--r--cil/test/integration_testing/small.cil5
-rw-r--r--cil/test/policy.cil322
-rw-r--r--cil/test/policy.conf143
-rw-r--r--cil/test/unit/AllTests.c76
-rw-r--r--cil/test/unit/CilTest.c1974
-rw-r--r--cil/test/unit/CilTest.h44
-rw-r--r--cil/test/unit/CuTest.c362
-rw-r--r--cil/test/unit/CuTest.h139
-rw-r--r--cil/test/unit/test_cil.c179
-rw-r--r--cil/test/unit/test_cil.h46
-rw-r--r--cil/test/unit/test_cil_build_ast.c19179
-rw-r--r--cil/test/unit/test_cil_build_ast.h1198
-rw-r--r--cil/test/unit/test_cil_copy_ast.c2571
-rw-r--r--cil/test/unit/test_cil_copy_ast.h176
-rw-r--r--cil/test/unit/test_cil_fqn.c75
-rw-r--r--cil/test/unit/test_cil_fqn.h37
-rw-r--r--cil/test/unit/test_cil_lexer.c100
-rw-r--r--cil/test/unit/test_cil_lexer.h38
-rw-r--r--cil/test/unit/test_cil_list.c345
-rw-r--r--cil/test/unit/test_cil_list.h46
-rw-r--r--cil/test/unit/test_cil_parser.c57
-rw-r--r--cil/test/unit/test_cil_parser.h37
-rw-r--r--cil/test/unit/test_cil_post.c703
-rw-r--r--cil/test/unit/test_cil_post.h79
-rw-r--r--cil/test/unit/test_cil_resolve_ast.c11319
-rw-r--r--cil/test/unit/test_cil_resolve_ast.h578
-rw-r--r--cil/test/unit/test_cil_symtab.c61
-rw-r--r--cil/test/unit/test_cil_symtab.h37
-rw-r--r--cil/test/unit/test_cil_tree.c71
-rw-r--r--cil/test/unit/test_cil_tree.h38
-rw-r--r--cil/test/unit/test_integration.c76
-rw-r--r--cil/test/unit/test_integration.h38
-rw-r--r--include/Makefile3
-rw-r--r--include/sepol/policydb.h6
-rw-r--r--include/sepol/policydb/avtab.h7
-rw-r--r--include/sepol/policydb/policydb.h2
-rw-r--r--include/sepol/policydb/services.h16
-rw-r--r--src/Makefile36
-rw-r--r--src/avtab.c45
-rw-r--r--src/expand.c129
-rw-r--r--src/libsepol.map.in36
-rw-r--r--src/link.c6
-rw-r--r--src/policydb.c2
-rw-r--r--src/policydb_internal.h2
-rw-r--r--src/policydb_public.c17
-rw-r--r--src/services.c106
-rw-r--r--src/write.c2
-rw-r--r--tests/test-linker-roles.c2
128 files changed, 76531 insertions, 157 deletions
diff --git a/.gitignore b/.gitignore
index a74c98b..77bb591 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
utils/chkcon
+libsepol.map
diff --git a/ChangeLog b/ChangeLog
index 2cdcb9c..7a87948 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
+2.4 2015-02-02
+ * Remove assumption that SHLIBDIR is ../../ relative to LIBDIR, from Steve
+ Lawrence
+ * Fix bugs found by hardened gcc flags, from Nicolas Iooss.
+ * Build CIL into libsepol. libsepol can be built without CIL by setting the
+ DISABLE_CIL flag to 'y', from Steve Lawrence
+ * Add an API function to set target_platform, from Steve Lawrence
+ * Report all neverallow violations, from Stephen Smalley
+ * Improve check_assertions performance through hash tweaks from John Brooks.
+ * Allow libsepol C++ static library on device from Daniel Cashman.
+
+2.3 2014-05-06
+ * Improve error message for name-based transition conflicts.
+ * Revert libsepol: filename_trans: use some better sorting to compare and merge.
+ * Report source file and line information for neverallow failures.
+ * Fix valgrind errors in constraint_expr_eval_reason from Richard Haines.
+ * Add sepol_validate_transition_reason_buffer function from Richard Haines.
+
2.2 2013-10-30
* Allow constraint denial cause to be determined from Richard Haines.
- Add kernel policy version 29.
@@ -12,23 +30,23 @@
* implement default type policy syntax
* Fix memory leak issues found by Klocwork
-2.1.8 2011-09-13
+2.1.8 2012-09-13
* fix neverallow checking on attributes
* Move context_copy() after switch block in ocontext_copy_*().
* check for missing initial SID labeling statement.
* Add always_check_network policy capability
* role_fix_callback skips out-of-scope roles during expansion.
-2.1.7 2011-06-28
+2.1.7 2012-06-28
* reserve policycapability for redhat testing of ptrace child
* cosmetic changes to make the source easier to read
* prepend instead of append to filename_trans list
* Android/MacOS X build support
-2.1.6 2011-04-23
+2.1.6 2012-04-23
* allocate enough space to hold filename in trans rules
-2.1.5 2011-03-28
+2.1.5 2012-03-28
* checkpolicy: implement new default labeling behaviors
2.1.4 2011-10-03
diff --git a/Makefile b/Makefile
index d526965..5b5d03e 100644
--- a/Makefile
+++ b/Makefile
@@ -1,3 +1,7 @@
+DISABLE_CIL ?= n
+
+export DISABLE_CIL
+
all:
$(MAKE) -C src
$(MAKE) -C utils
diff --git a/VERSION b/VERSION
index 8bbe6cf..6b4950e 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.2
+2.4
diff --git a/cil/.gitignore b/cil/.gitignore
new file mode 100644
index 0000000..d02d081
--- /dev/null
+++ b/cil/.gitignore
@@ -0,0 +1,12 @@
+*.swp
+*.gcda
+*.gcno
+*.o
+*.a
+src/cil_lexer.c
+unit_tests
+cov
+secilc
+ docs/pdf/
+ docs/html/
+ docs/man8/
diff --git a/cil/COPYING b/cil/COPYING
new file mode 100644
index 0000000..03a9905
--- /dev/null
+++ b/cil/COPYING
@@ -0,0 +1,32 @@
+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.
diff --git a/cil/Makefile b/cil/Makefile
new file mode 100644
index 0000000..9f52ee4
--- /dev/null
+++ b/cil/Makefile
@@ -0,0 +1,102 @@
+PREFIX ?= $(DESTDIR)/usr
+LIBDIR ?= $(PREFIX)/lib
+SHLIBDIR ?= $(DESTDIR)/lib
+INCLUDEDIR ?= $(PREFIX)/include
+SRCDIR ?= ./src
+TESTDIR ?= ./test
+UNITDIR ?= $(TESTDIR)/unit
+LIBCILDIR ?= $(SRCDIR)
+
+LEX = flex
+
+DEBUG = 0
+
+SECILC = secilc
+
+UNIT = unit_tests
+
+SECILC_SRCS := secilc.c
+SECILC_OBJS := $(patsubst %.c,%.o,$(SECILC_SRCS))
+
+TEST_SRCS := $(wildcard $(UNITDIR)/*.c)
+TEST_OBJS := $(patsubst %.c,%.o,$(TEST_SRCS))
+
+LIBCIL_GENERATED := $(LIBCILDIR)/cil_lexer.c
+LIBCIL_SRCS := $(wildcard $(LIBCILDIR)/*.c) $(LIBCIL_GENERATED)
+LIBCIL_OBJS := $(patsubst %.c,%.o,$(LIBCIL_SRCS))
+LIBCIL_INCLUDES := $(wildcard $(LIBCILDIR)/*.h)
+
+LIBCIL_STATIC := $(SRCDIR)/libcil.a
+
+LIBSEPOL_STATIC = /usr/lib/libsepol.a
+
+LIBS =
+LDFLAGS =
+COVCFLAGS = -fprofile-arcs -ftest-coverage -O0
+
+CFLAGS ?= -Wall -Wshadow -Wextra -Wundef -Wmissing-format-attribute -Wcast-align -Wstrict-prototypes -Wpointer-arith -Wunused
+
+ifeq ($(DEBUG),1)
+ override CFLAGS += -g3 -O0 -gdwarf-2 -fno-strict-aliasing -DDEBUG
+ override LDFLAGS += -g
+else
+ override CFLAGS += -O2
+endif
+
+override CFLAGS += -I./include -I$(INCLUDEDIR) -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64
+
+ARCH := $(patsubst i%86,i386,$(shell uname -m))
+ifneq (,$(filter i386,$(ARCH)))
+ TLSFLAGS += -mno-tls-direct-seg-refs
+endif
+ifneq (,$(filter x86_64,$(ARCH)))
+ override LDFLAGS += -I/usr/lib64
+ override LIBSEPOL_STATIC = /usr/lib64/libsepol.a
+endif
+
+all: $(SECILC)
+
+%.o: %.c $(LIBCIL_INCLUDES)
+ $(CC) $(CFLAGS) -c -o $@ $<
+
+$(LIBCIL_STATIC): $(LIBCIL_OBJS)
+ $(AR) rcs $@ $^
+ ranlib $@
+
+$(LIBCIL_GENERATED): $(LIBCILDIR)/cil_lexer.l
+ $(LEX) -t $< > $@
+
+$(UNIT): $(TEST_OBJS) $(LIBCIL_STATIC)
+ $(CC) $(CFLAGS) -o $@ $^ $(LIBCIL_STATIC) $(LIBSEPOL_STATIC) $(LDFLAGS)
+
+$(SECILC): $(SECILC_OBJS) $(LIBCIL_STATIC)
+ $(CC) $(CFLAGS) -o $@ $^ $(LIBCIL_STATIC) $(LIBSEPOL_STATIC) $(LDFLAGS)
+
+unit: $(SECILC) $(UNIT)
+
+# Requires lcov 1.9+ (--ignore-errors)
+coverage: CFLAGS += $(COVCFLAGS)
+coverage: clean unit
+ ./unit_tests
+ test -d cov || mkdir cov
+ lcov --directory src --capture --output-file cov/app.info --ignore-errors source -b src
+ lcov --remove cov/app.info '/usr/include/*' --remove cov/app.info 'sepol/*' --output-file cov/app.info
+ genhtml -o ./cov/html ./cov/app.info
+
+test: $(SECILC)
+ ./$(SECILC) test/policy.cil
+
+clean:
+ rm -f $(SECILC)
+ rm -f $(LIBCIL_STATIC)
+ rm -f $(TEST_OBJS) $(SECILC_OBJS)
+ rm -rf cov src/*.gcda src/*.gcno *.gcda *.gcno
+ rm -f $(LIBCIL_OBJS)
+
+bare: clean
+ rm -f $(LIBCIL_GENERATED)
+ rm -f $(UNIT)
+ rm -f policy.*
+ rm -f file_contexts
+
+.PHONY: all bare clean coverage test unit
diff --git a/cil/README b/cil/README
new file mode 100644
index 0000000..e25f849
--- /dev/null
+++ b/cil/README
@@ -0,0 +1,75 @@
+SELinux Common Intermediate Language (CIL) Compiler
+
+INTRODUCTION
+
+ The SELinux CIL Compiler is a compiler that converts the CIL language as
+ described on the CIL design wiki into a kernel binary policy file.
+ Please see the CIL Design Wiki at:
+ http://github.com/SELinuxProject/cil/wiki/
+ for more information about the goals and features on the CIL language.
+
+DEPENDENCIES
+
+ gcc >= 4.5.1
+ libsepol-static >= 2.1.4
+ lcov >= 1.9
+ flex >= 2.5.35
+
+
+BUILD STEPS
+
+ Open a terminal client and execute the following command to download the source code:
+
+ git clone https://github.com/SELinuxProject/cil.git
+
+ Change directory into the "cil" directory.
+ Run "make" with one of the following targets:
+
+ make
+ Build the CIL compiler (secilc)
+
+ make unit
+ Build the unit_test application to run unit tests
+
+ make coverage
+ Build the unit test binary and create coverage reports
+
+ make clean
+ Remove temporary build files
+
+ make bare
+ Remove temporary build files and compile binaries
+
+
+USAGE
+
+ Execute 'secilc' with any number of CIL files as arguments. A binary policy and
+ file_contexts file will be created.
+
+ Use the '--help' option for more details.
+
+
+DOCUMENTATION
+
+ There is a Docbook CIL Reference Guide in the docs directory, to build
+ this in HTML and PDF format change to the docs directory and run:
+ make html pdf
+
+ There is also an secilc man page that can be built with:
+ make man
+
+ The documents will be located in the docs/html, docs/pdf and docs/man8
+ directories.
+
+ To build the html and manpage the xmlto package is required.
+ To build the pdf document the xmlto and dblatex packages are required.
+
+
+KNOWN ISSUES
+
+ - Blocks inside of macros causes undefined behavior
+
+ - Policy must be well formed. For example, invalid usage of
+ sensitivities/categories/levels may create an unloaded binary
+
+ - Recursive limits are not handled
diff --git a/cil/docs/CIL_Reference_Guide.xml b/cil/docs/CIL_Reference_Guide.xml
new file mode 100644
index 0000000..e905152
--- /dev/null
+++ b/cil/docs/CIL_Reference_Guide.xml
@@ -0,0 +1,581 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
+ [ <!ENTITY policy_config_statements SYSTEM "cil_policy_config_statements.xml">
+ <!ENTITY container_statements SYSTEM "cil_container_statements.xml">
+ <!ENTITY call_macro_statements SYSTEM "cil_call_macro_statements.xml">
+ <!ENTITY default_object_statements SYSTEM "cil_default_object_statements.xml">
+ <!ENTITY user_statements SYSTEM "cil_user_statements.xml">
+ <!ENTITY role_statements SYSTEM "cil_role_statements.xml">
+ <!ENTITY type_statements SYSTEM "cil_type_statements.xml">
+ <!ENTITY class_and_permission_statements SYSTEM "cil_class_and_permission_statements.xml">
+ <!ENTITY access_vector_rules SYSTEM "cil_access_vector_rules.xml">
+ <!ENTITY conditional_statements SYSTEM "cil_conditional_statements.xml">
+ <!ENTITY constraint_statements SYSTEM "cil_constraint_statements.xml">
+ <!ENTITY mls_labeling_statements SYSTEM "cil_mls_labeling_statements.xml">
+ <!ENTITY context_statement SYSTEM "cil_context_statement.xml">
+ <!ENTITY sid_statements SYSTEM "cil_sid_statements.xml">
+ <!ENTITY file_labeling_statements SYSTEM "cil_file_labeling_statements.xml">
+ <!ENTITY network_labeling_statements SYSTEM "cil_network_labeling_statements.xml">
+ <!ENTITY xen_statements SYSTEM "cil_xen_statements.xml">
+
+ <!-- This is to load in the latest example policy.cil file -->
+ <!ENTITY policy_cil SYSTEM "../test/policy.cil">
+
+ ]>
+
+<article lang="en_GB">
+ <articleinfo>
+ <title>Common Interface Language (CIL) Reference Guide</title>
+ <revhistory>
+ <revision>
+ <revnumber>0.2</revnumber>
+ <date>22nd May '14</date>
+ <revremark>Updated classmap/classmapping, added classmap to statements that utilise class_id's (defaultuser, typetransition etc.), update various examples to show anonymous classpermissionset's using expressions.</revremark>
+ </revision>
+ </revhistory>
+ </articleinfo>
+
+ <sect1>
+ <title>CIL Information</title>
+ <orderedlist>
+ <listitem><para>The statement definitions are those found in the source from: <literal>git clone <ulink url="https://bitbucket.org/jwcarter/secilc.git"></ulink></literal> dated 21st May '14.</para></listitem>
+ <listitem><para>Not all possible alternate statement permutations are shown, however there should be enough variation to work out any other valid formats. There is also an example <filename>policy.cil</filename> file shown in the <link linkend="example_policy">Appendix</link>.</para></listitem>
+ <listitem><para>The MLS components on contexts and user statements must be declared even if the policy does not support MCS/MLS. </para></listitem>
+ <listitem><para>The CIL compiler will not build a policy unless it also has as a minimum: one <literal><link linkend="allow">allow</link></literal> rule, one <literal><link linkend="sid">sid</link></literal>, <literal><link linkend="sidorder">sidorder</link></literal> and <literal><link linkend="sidcontext">sidcontext</link></literal> statement. </para></listitem>
+ <listitem><para>The role <literal>object_r</literal> must be explicitly associated to contexts used for labeling objects. The original <emphasis role="bold"><literal>checkpolicy</literal></emphasis><literal>(8)</literal> and <emphasis role="bold"><literal>checkmodule</literal></emphasis><literal>(8)</literal> compilers did this by default - CIL does not.</para></listitem>
+ <listitem><para>Be aware that CIL allows <literal><link linkend="class">class</link></literal> statements to be declared in a namespace, however the policy author needs to note that applications (and the kernel) generally reference a class by its well known class identifier (e.g. <literal>zygote</literal>) however if declared in a namespace (e.g. <literal>(block zygote (class zygote (...)))</literal> or <literal>(block zygote (class class (...)))</literal>) it would be prefixed with that namespace (e.g. <literal>zygote.zygote</literal> or <literal>zygote.class</literal>). Unless the application / kernel code was updated the class would never be resolved, therefore it is recommended that classes are declared in the global namespace.</para></listitem>
+ <listitem><para>Where possible use <literal><link linkend="typeattribute">typeattribute</link></literal>'s when defining source/target <literal><link linkend="allow">allow</link></literal> rules instead of multiple <literal>allow</literal> rules with individual <literal><link linkend="type">type</link></literal>'s. This will lead to the generation of much smaller kernel policy files.</para></listitem>
+ <listitem><para>The <ulink url="http://userspace.selinuxproject.org/trac/wiki/CilDesign"></ulink> site explains the language however some of the statement definitions are dated.</para></listitem>
+ </orderedlist>
+ <sect2>
+ <title>Declarations</title>
+ <para>Declarations may be named or anonymous and have three different forms:</para>
+ <orderedlist>
+ <listitem><para>Named declarations - These create new objects that introduce a name or identifier, for example:</para>
+ <para><literal>(type process)</literal> - creates a <literal>type</literal> with an identifier of <literal>process</literal>.</para>
+ <para><literal>(typeattribute domain)</literal> - creates a <literal>typeattribute</literal> with an identifier of <literal>domain</literal>.</para>
+ <para><literal>(class file (read write))</literal> - creates a <literal>class</literal> with an identifier of <literal>file</literal> that has <literal>read</literal> and <literal>write</literal> permissions associated to it.</para>
+ <para>The list of declaration type statement keywords are:</para>
+ <simplelist type="inline">
+ <member><literal><link linkend="block">block</link></literal></member>
+ <member><literal><link linkend="optional">optional</link></literal></member>
+ <member><literal><link linkend="common">common</link></literal></member>
+ <member><literal><link linkend="class">class</link></literal></member>
+ <member><literal><link linkend="classmap">classmap</link></literal></member>
+ <member><literal><link linkend="classmapping">classmapping</link></literal></member>
+ <member><literal><link linkend="sid">sid</link></literal></member>
+ <member><literal><link linkend="user">user</link></literal></member>
+ <member><literal><link linkend="role">role</link></literal></member>
+ <member><literal><link linkend="roleattribute">roleattribute</link></literal></member>
+ <member><literal><link linkend="type">type</link></literal></member>
+ <member><literal><link linkend="classpermission">classpermission</link></literal></member>
+ <member><literal><link linkend="classpermissionset">classpermissionset</link></literal></member>
+ <member><literal><link linkend="typeattribute">typeattribute</link></literal></member>
+ <member><literal><link linkend="typealias">typealias</link></literal></member>
+ <member><literal><link linkend="tunable">tunable</link></literal></member>
+ <member><literal><link linkend="sensitivity">sensitivity</link></literal></member>
+ <member><literal><link linkend="sensitivityalias">sensitivityalias</link></literal></member>
+ <member><literal><link linkend="category">category</link></literal></member>
+ <member><literal><link linkend="categoryalias">categoryalias</link></literal></member>
+ <member><literal><link linkend="categoryset">categoryset</link></literal></member>
+ <member><literal><link linkend="level">level</link></literal></member>
+ <member><literal><link linkend="levelrange">levelrange</link></literal></member>
+ <member><literal><link linkend="context">context</link></literal></member>
+ <member><literal><link linkend="ipaddr">ipaddr</link></literal></member>
+ <member><literal><link linkend="macro">macro</link></literal></member>
+ <member><literal><link linkend="policycap">policycap</link></literal></member>
+ </simplelist>
+ </listitem>
+ <listitem><para>Explicit anonymous declarations - These are currently restricted to IP addesses where they can be declared directly in statements by enclosing them within parentheses e.g. <literal>(127.0.0.1)</literal> or <literal>(::1)</literal>. See the <link linkend="network_labeling">Network Labeling Statements</link> section for examples.</para></listitem>
+ <listitem><para>Anonymous declarations - These have been previously declared and the object already exists, therefore they may be referenced by their name or identifier within statements. For example the following declare all the components required to specify a context:</para>
+ <programlisting><![CDATA[
+(sensitivity s0)
+(category c0)
+(role object_r)
+
+(block unconfined
+ (user user)
+ (type object)
+)]]>
+ </programlisting>
+ <simpara>now a <literal><link linkend="portcon">portcon</link></literal> statement can be defined that uses these individual components to build a context as follows:</simpara>
+ <programlisting><![CDATA[(portcon udp 12345 (unconfined.user object_r unconfined.object ((s0) (s0(c0)))))]]></programlisting>
+ </listitem>
+ </orderedlist>
+ </sect2>
+
+ <sect2>
+ <title>Definitions</title>
+ <para>Statements that build on the objects, for example:</para>
+ <itemizedlist mark="none">
+ <listitem><para><literal>(typeattributeset domain (process))</literal> - Adds the <literal>type</literal> '<literal>process</literal>' to the <literal>typeattribute</literal> '<literal>domain</literal>'.</para></listitem>
+ <listitem><para><literal>(allow domain process (file (read write))))</literal> - Adds an <literal>allow</literal> rule referencing <literal>domain</literal>, <literal>process</literal> and the <literal>file class</literal>.</para></listitem>
+ </itemizedlist>
+ <para>Definitions may be repeated many times throughout the policy. Duplicates will resolve to a single definition during compilation.</para>
+ </sect2>
+ <sect2>
+ <title>Symbol Character Set</title>
+ <para>Symbols (any string not enclosed in double quotes) must only contain alphanumeric <literal>[a-z A-Z] [0-9]</literal> characters plus the following special characters: <literal>\.@=/-_$%@+!|&amp;^:</literal></para>
+ <para>However symbols are checked for any specific character set limitations, for example:</para>
+ <itemizedlist>
+ <listitem><para>Names or identifiers must start with an alpa character <literal>[a-z A-Z]</literal>, the remainder may be alphanumeric <literal>[a-z A-Z] [0-9]</literal> characters plus underscore <literal>[_]</literal> or hyphen <literal>[-]</literal>.</para></listitem>
+ <listitem><para>IP addresses must conform to IPv4 or IPv6 format.</para></listitem>
+ <listitem><para>Memory, ports, irqs must be numeric <literal>[0-9]</literal>.</para></listitem>
+ </itemizedlist>
+ </sect2>
+ <sect2>
+ <title>String Character Set</title>
+ <para>Strings are enclosed within double quotes (e.g. <literal>"This is a string"</literal>), and may contain any character except the double quote (").</para>
+ </sect2>
+ <sect2>
+ <title>Comments</title>
+ <para>Comments start with a semicolon '<literal>;</literal>' and end when a new line is started.</para>
+ </sect2>
+ <sect2>
+ <title>Namespaces</title>
+ <para>CIL supports namespaces via containers such as the <literal>block</literal> statement. When a block is resolved to form the parent / child relationship a dot '<literal>.</literal>' is used, for example the following <literal>allow</literal> rule:</para>
+ <programlisting><![CDATA[
+(block example_ns
+ (type process)
+ (type object)
+ (class file (open read write getattr))
+
+ (allow process object (file (open read getattr)))
+)]]>
+ </programlisting>
+ <para>will resolve to the following kernel policy language statement:</para>
+ <programlisting><![CDATA[allow example_ns.process example_ns.object : example_ns.file { open read getattr };]]></programlisting>
+ </sect2>
+ <sect2>
+ <title>Global Namespace</title>
+ <para>CIL has a global namespace that is always present. Any symbol that is declared outside a container is in the global namespace. To reference a symbol in global namespace, the symbol should be prefixed with a dot '<literal>.</literal>' as shown in the following example:</para>
+ <programlisting><![CDATA[
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; This example has three namespace 'tmpfs' types declared:
+; 1) Global .tmpfs
+; 2) file.tmpfs
+; 3) other_ns.tmpfs
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+; This type is the global tmpfs:
+(type tmpfs)
+
+(block file
+ ; file namespace tmpfs
+ (type tmpfs)
+ (class file (open read write getattr))
+
+ ; This rule will reference the local namespace for src and tgt:
+ (allow tmpfs tmpfs (file (open)))
+ ; Resulting policy rule:
+ ; allow file.tmpfs file.tmpfs : file.file open;
+
+ ; This rule will reference the local namespace for src and global for tgt:
+ (allow tmpfs .tmpfs (file (read)))
+ ; Resulting policy rule:
+ ; allow file.tmpfs tmpfs : file.file read;
+
+ ; This rule will reference the global namespace for src and tgt:
+ (allow .tmpfs .tmpfs (file (write)))
+ ; Resulting policy rule:
+ ; allow tmpfs tmpfs : file.file write;
+
+ ; This rule will reference the other_ns namespace for src and
+ ; local namespace for tgt:
+ (allow other_ns.tmpfs tmpfs (file (getattr)))
+ ; Resulting policy rule:
+ ; allow other_ns.tmpfs file.tmpfs : file.file getattr;
+)
+
+(block other_ns
+ (type tmpfs)
+)]]>
+ </programlisting>
+ <para>Should the symbol not be prefixed with a dot, the current namespace would be searched first and then the global namespace (provided there is not a symbol of that name in the current namespace).</para>
+ </sect2>
+ <sect2>
+ <title>Expressions</title>
+ <para>Expressions may occur in the following CIL statements:
+ <simplelist type="inline">
+ <member><literal><link linkend="booleanif">booleanif</link></literal></member>
+ <member><literal><link linkend="tunableif">tunableif</link></literal></member>
+ <member><literal><link linkend="classpermissionset">classpermissionset</link></literal></member>
+ <member><literal><link linkend="typeattributeset">typeattributeset</link></literal></member>
+ <member><literal><link linkend="roleattributeset">roleattributeset</link></literal></member>
+ <member><literal><link linkend="categoryset">categoryset</link></literal></member>
+ <member><literal><link linkend="constrain">constrain</link></literal></member>
+ <member><literal><link linkend="mlsconstrain">mlsconstrain</link></literal></member>
+ <member><literal><link linkend="validatetrans">validatetrans</link></literal></member>
+ <member><literal><link linkend="validatetrans">validatetrans</link></literal></member>
+ </simplelist></para>
+ <para>CIL expressions use the <ulink url="http://www.cs.man.ac.uk/~pjj/cs212/fix.html">prefix</ulink> or Polish notation and may be nested (note that the kernel policy language uses postfix or reverse Polish notation). The syntax is as follows, where the parenthesis are part of the syntax:</para>
+ <programlisting><![CDATA[
+expr_set = (name ... | expr ...)
+expr = (expr_key expr_set ...)
+expr_key = and | or | xor | not | all | eq | neq | dom | domby | incomp | range]]>
+ </programlisting>
+ <para>The number of <literal>expr_set</literal>'s in an <literal>expr</literal> is dependent on the statement type (there are four different classes as defined below) that also influence the valid <literal>expr_key</literal> entries (e.g. <literal>dom</literal>, <literal>domby</literal>, <literal>incomp</literal> are only allowed in constraint statements).</para>
+
+ <informaltable frame="all">
+ <tgroup cols="5"><tbody>
+ <row>
+ <entry valign="bottom"><?dbhtml bgcolor="orange" ?><?dbfo bgcolor="orange" ?><?dblatex bgcolor="orange" ?>
+ <para/>
+ <para/>
+ <para/>
+ <para><emphasis role="bold">expr_key</emphasis></para>
+ </entry>
+ <entry valign="top" align="center"><?dbhtml bgcolor="lightgreen" ?><?dbfo bgcolor="lightgreen" ?><?dblatex bgcolor="green" ?>
+ <para><emphasis role="bold">classpermissionset</emphasis></para>
+ <para><emphasis role="bold">roleattributeset</emphasis></para>
+ <para><emphasis role="bold">typeattributeset</emphasis></para>
+ </entry>
+ <entry valign="top" align="center"><?dbhtml bgcolor="lightgreen" ?><?dbfo bgcolor="lightgreen" ?><?dblatex bgcolor="green" ?>
+ <para><emphasis role="bold">categoryset</emphasis></para>
+ </entry>
+ <entry valign="top" align="center"><?dbhtml bgcolor="lightgreen" ?><?dbfo bgcolor="lightgreen" ?><?dblatex bgcolor="green" ?>
+ <para><emphasis role="bold">booleanif</emphasis></para>
+ <para><emphasis role="bold">tunableif</emphasis></para>
+ </entry>
+ <entry valign="top" align="center"><?dbhtml bgcolor="lightgreen" ?><?dbfo bgcolor="lightgreen" ?><?dblatex bgcolor="green" ?>
+ <para><emphasis role="bold">constrain</emphasis></para>
+ <para><emphasis role="bold">mlsconstrain</emphasis></para>
+ <para><emphasis role="bold">validatetrans</emphasis></para>
+ <para><emphasis role="bold">mlsvalidatetrans</emphasis></para>
+ </entry>
+ </row>
+ <row>
+ <entry><?dbhtml bgcolor="orange" ?><?dbfo bgcolor="orange" ?><?dblatex bgcolor="orange" ?>
+ <para><emphasis role="bold"><literal>dom</literal></emphasis></para>
+ </entry>
+ <entry>
+ <para/>
+ </entry>
+ <entry>
+ <para/>
+ </entry>
+ <entry>
+ <para/>
+ </entry>
+ <entry align="center"><?dbhtml bgcolor="lightgray" ?><?dbfo bgcolor="lightgray" ?><?dblatex bgcolor="lightgray" ?>
+ <para><emphasis role="bold">X</emphasis></para>
+ </entry>
+ </row>
+ <row>
+ <entry><?dbhtml bgcolor="orange" ?><?dbfo bgcolor="orange" ?><?dblatex bgcolor="orange" ?>
+ <para><emphasis role="bold"><literal>domby</literal></emphasis></para>
+ </entry>
+ <entry>
+ <para/>
+ </entry>
+ <entry>
+ <para/>
+ </entry>
+ <entry>
+ <para/>
+ </entry>
+ <entry align="center"><?dbhtml bgcolor="lightgray" ?><?dbfo bgcolor="lightgray" ?><?dblatex bgcolor="lightgray" ?>
+ <para><emphasis role="bold">X</emphasis></para>
+ </entry>
+ </row>
+ <row>
+ <entry><?dbhtml bgcolor="orange" ?><?dbfo bgcolor="orange" ?><?dblatex bgcolor="orange" ?>
+ <para><emphasis role="bold"><literal>incomp</literal></emphasis></para>
+ </entry>
+ <entry>
+ <para/>
+ </entry>
+ <entry>
+ <para/>
+ </entry>
+ <entry>
+ <para/>
+ </entry>
+ <entry align="center"><?dbhtml bgcolor="lightgray" ?><?dbfo bgcolor="lightgray" ?><?dblatex bgcolor="lightgray" ?>
+ <para><emphasis role="bold">X</emphasis></para>
+ </entry>
+ </row>
+ <row>
+ <entry><?dbhtml bgcolor="orange" ?><?dbfo bgcolor="orange" ?><?dblatex bgcolor="orange" ?>
+ <para><emphasis role="bold"><literal>eq</literal></emphasis></para>
+ </entry>
+ <entry>
+ <para/>
+ </entry>
+ <entry>
+ <para/>
+ </entry>
+ <entry align="center"><?dbhtml bgcolor="lightgray" ?><?dbfo bgcolor="lightgray" ?><?dblatex bgcolor="lightgray" ?>
+ <para><emphasis role="bold">X</emphasis></para>
+ </entry>
+ <entry align="center"><?dbhtml bgcolor="lightgray" ?><?dbfo bgcolor="lightgray" ?><?dblatex bgcolor="lightgray" ?>
+ <para><emphasis role="bold">X</emphasis></para>
+ </entry>
+ </row>
+ <row>
+ <entry><?dbhtml bgcolor="orange" ?><?dbfo bgcolor="orange" ?><?dblatex bgcolor="orange" ?>
+ <para><emphasis role="bold"><literal>ne</literal></emphasis></para>
+ </entry>
+ <entry>
+ <para/>
+ </entry>
+ <entry>
+ <para/>
+ </entry>
+ <entry align="center"><?dbhtml bgcolor="lightgray" ?><?dbfo bgcolor="lightgray" ?><?dblatex bgcolor="lightgray" ?>
+ <para><emphasis role="bold">X</emphasis></para>
+ </entry>
+ <entry align="center"><?dbhtml bgcolor="lightgray" ?><?dbfo bgcolor="lightgray" ?><?dblatex bgcolor="lightgray" ?>
+ <para><emphasis role="bold">X</emphasis></para>
+ </entry>
+ </row>
+ <row>
+ <entry><?dbhtml bgcolor="orange" ?><?dbfo bgcolor="orange" ?><?dblatex bgcolor="orange" ?>
+ <para><emphasis role="bold"><literal>and</literal></emphasis></para>
+ </entry>
+ <entry align="center"><?dbhtml bgcolor="lightgray" ?><?dbfo bgcolor="lightgray" ?><?dblatex bgcolor="lightgray" ?>
+ <para><emphasis role="bold">X</emphasis></para>
+ </entry>
+ <entry align="center"><?dbhtml bgcolor="lightgray" ?><?dbfo bgcolor="lightgray" ?><?dblatex bgcolor="lightgray" ?>
+ <para><emphasis role="bold">X</emphasis></para>
+ </entry>
+ <entry align="center"><?dbhtml bgcolor="lightgray" ?><?dbfo bgcolor="lightgray" ?><?dblatex bgcolor="lightgray" ?>
+ <para><emphasis role="bold">X</emphasis></para>
+ </entry>
+ <entry align="center"><?dbhtml bgcolor="lightgray" ?><?dbfo bgcolor="lightgray" ?><?dblatex bgcolor="lightgray" ?>
+ <para><emphasis role="bold">X</emphasis></para>
+ </entry>
+ </row>
+ <row>
+ <entry><?dbhtml bgcolor="orange" ?><?dbfo bgcolor="orange" ?><?dblatex bgcolor="orange" ?>
+ <para><emphasis role="bold"><literal>or</literal></emphasis></para>
+ </entry>
+ <entry align="center"><?dbhtml bgcolor="lightgray" ?><?dbfo bgcolor="lightgray" ?><?dblatex bgcolor="lightgray" ?>
+ <para><emphasis role="bold">X</emphasis></para>
+ </entry>
+ <entry align="center"><?dbhtml bgcolor="lightgray" ?><?dbfo bgcolor="lightgray" ?><?dblatex bgcolor="lightgray" ?>
+ <para><emphasis role="bold">X</emphasis></para>
+ </entry>
+ <entry align="center"><?dbhtml bgcolor="lightgray" ?><?dbfo bgcolor="lightgray" ?><?dblatex bgcolor="lightgray" ?>
+ <para><emphasis role="bold">X</emphasis></para>
+ </entry>
+ <entry align="center"><?dbhtml bgcolor="lightgray" ?><?dbfo bgcolor="lightgray" ?><?dblatex bgcolor="lightgray" ?>
+ <para><emphasis role="bold">X</emphasis></para>
+ </entry>
+ </row>
+ <row>
+ <entry><?dbhtml bgcolor="orange" ?><?dbfo bgcolor="orange" ?><?dblatex bgcolor="orange" ?>
+ <para><emphasis role="bold"><literal>not</literal></emphasis></para>
+ </entry>
+ <entry align="center"><?dbhtml bgcolor="lightgray" ?><?dbfo bgcolor="lightgray" ?><?dblatex bgcolor="lightgray" ?>
+ <para><emphasis role="bold">X</emphasis></para>
+ </entry>
+ <entry align="center"><?dbhtml bgcolor="lightgray" ?><?dbfo bgcolor="lightgray" ?><?dblatex bgcolor="lightgray" ?>
+ <para><emphasis role="bold">X</emphasis></para>
+ </entry>
+ <entry align="center"><?dbhtml bgcolor="lightgray" ?><?dbfo bgcolor="lightgray" ?><?dblatex bgcolor="lightgray" ?>
+ <para><emphasis role="bold">X</emphasis></para>
+ </entry>
+ <entry align="center"><?dbhtml bgcolor="lightgray" ?><?dbfo bgcolor="lightgray" ?><?dblatex bgcolor="lightgray" ?>
+ <para><emphasis role="bold">X</emphasis></para>
+ </entry>
+ </row>
+ <row>
+ <entry><?dbhtml bgcolor="orange" ?><?dbfo bgcolor="orange" ?><?dblatex bgcolor="orange" ?>
+ <para><emphasis role="bold"><literal>xor</literal></emphasis></para>
+ </entry>
+ <entry align="center"><?dbhtml bgcolor="lightgray" ?><?dbfo bgcolor="lightgray" ?><?dblatex bgcolor="lightgray" ?>
+ <para><emphasis role="bold">X</emphasis></para>
+ </entry>
+ <entry align="center"><?dbhtml bgcolor="lightgray" ?><?dbfo bgcolor="lightgray" ?><?dblatex bgcolor="lightgray" ?>
+ <para><emphasis role="bold">X</emphasis></para>
+ </entry>
+ <entry align="center"><?dbhtml bgcolor="lightgray" ?><?dbfo bgcolor="lightgray" ?><?dblatex bgcolor="lightgray" ?>
+ <para><emphasis role="bold">X</emphasis></para>
+ </entry>
+ <entry>
+ <para/>
+ </entry>
+ </row>
+ <row>
+ <entry><?dbhtml bgcolor="orange" ?><?dbfo bgcolor="orange" ?><?dblatex bgcolor="orange" ?>
+ <para><emphasis role="bold"><literal>all</literal></emphasis></para>
+ </entry>
+ <entry align="center"><?dbhtml bgcolor="lightgray" ?><?dbfo bgcolor="lightgray" ?><?dblatex bgcolor="lightgray" ?>
+ <para><emphasis role="bold">X</emphasis></para>
+ </entry>
+ <entry align="center"><?dbhtml bgcolor="lightgray" ?><?dbfo bgcolor="lightgray" ?><?dblatex bgcolor="lightgray" ?>
+ <para><emphasis role="bold">X</emphasis></para>
+ </entry>
+ <entry>
+ <para/>
+ </entry>
+ <entry>
+ <para/>
+ </entry>
+ </row>
+ <row>
+ <entry><?dbhtml bgcolor="orange" ?><?dbfo bgcolor="orange" ?><?dblatex bgcolor="orange" ?>
+ <para><emphasis role="bold"><literal>range</literal></emphasis></para>
+ </entry>
+ <entry>
+ <para/>
+ </entry>
+ <entry align="center"><?dbhtml bgcolor="lightgray" ?><?dbfo bgcolor="lightgray" ?><?dblatex bgcolor="lightgray" ?>
+ <para><emphasis role="bold">X</emphasis></para>
+ </entry>
+ <entry>
+ <para/>
+ </entry>
+ <entry>
+ <para/>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+
+ <orderedlist>
+ <listitem>
+ <para>The <literal><link linkend="classpermissionset">classpermissionset</link></literal>,
+<literal><link linkend="roleattributeset">roleattributeset</link></literal> and <literal><link linkend="typeattributeset">typeattributeset</link></literal> statements allow <literal>expr_set</literal> to mix names and <literal>expr</literal>s with <literal>expr_key</literal> values of: <literal>and</literal>, <literal>or</literal>, <literal>xor</literal>, <literal>not</literal>, <literal>all</literal> as shown in the examples:</para>
+ <para>This example includes all <literal>fs_type type</literal> entries except <literal>file.usermodehelper</literal> and <literal>file.proc_security</literal> in the associated <literal>typeattribute</literal> identifier <literal>all_fs_type_except_usermodehelper_and_proc_security</literal>:</para>
+ <programlisting><![CDATA[
+(typeattribute all_fs_type_except_usermodehelper_and_proc_security)
+
+(typeattributeset all_fs_type_except_usermodehelper_and_proc_security
+ (and
+ (and
+ fs_type
+ (not file.usermodehelper)
+ )
+ (not file.proc_security)
+ )
+)]]>
+ </programlisting>
+ <para>The <literal>cps_1 classpermissionset</literal> identifier includes all permissions except <literal>load_policy</literal> and <literal>setenforce</literal>:</para>
+ <programlisting><![CDATA[
+(class security (compute_av compute_create compute_member check_context load_policy compute_relabel compute_user setenforce setbool setsecparam setcheckreqprot read_policy))
+
+(classpermission cps_1)
+
+(classpermissionset cps_1 (security (not (load_policy setenforce))))]]>
+ </programlisting>
+
+ <para>This example includes all permissions in the associated <literal>classpermissionset</literal> identifer <literal>security_all_perms</literal>:</para>
+ <programlisting><![CDATA[
+(class security (compute_av compute_create compute_member check_context load_policy
+ compute_relabel compute_user setenforce setbool setsecparam setcheckreqprot
+ read_policy)
+)
+
+(classpermission security_all_perms)
+
+(classpermissionset security_all_perms (security (all)))]]>
+ </programlisting>
+ </listitem>
+
+ <listitem>
+ <para>The <literal><link linkend="categoryset">categoryset</link></literal> statement allows <literal>expr_set</literal> to mix names and <literal>expr_key</literal> values of: <literal>and</literal>, <literal>or</literal>, <literal>not</literal>, <literal>xor</literal>, <literal>all</literal>, <literal>range</literal> as shown in the examples.</para>
+ <para>Category expressions are also allowed in <literal><link linkend="sensitivitycategory">sensitivitycategory</link></literal>, <literal><link linkend="level">level</link></literal>, and <literal><link linkend="levelrange">levelrange</link></literal> statements.</para>
+ </listitem>
+
+ <listitem>
+ <para>The <literal><link linkend="booleanif">booleanif</link></literal> and <literal><link linkend="tunableif">tunableif</link></literal> statements only allow an <literal>expr_set</literal> to have one <literal>name</literal> or <literal>expr</literal> with <literal>expr_key</literal> values of <literal>and</literal>, <literal>or</literal>, <literal>xor</literal>, <literal>not</literal>, <literal>eq</literal>, <literal>neq</literal> as shown in the examples:</para>
+ <programlisting><![CDATA[
+(booleanif disableAudio
+ (false
+ (allow process device.audio_device (chr_file_set (rw_file_perms)))
+ )
+)]]>
+ </programlisting>
+ <programlisting><![CDATA[
+(booleanif (and (not disableAudio) (not disableAudioCapture))
+ (true
+ (allow process device.audio_capture_device (chr_file_set (rw_file_perms)))
+ )
+)]]>
+ </programlisting>
+ </listitem>
+
+ <listitem>
+ <para>The <literal><link linkend="constrain">constrain</link></literal>, <literal><link linkend="mlsconstrain">mlsconstrain</link></literal>, <literal><link linkend="validatetrans">validatetrans</link></literal> and <literal><link linkend="mlsvalidatetrans">mlsvalidatetrans</link></literal> statements only allow an <literal>expr_set</literal> to have one <literal>name</literal> or <literal>expr</literal> with <literal>expr_key</literal> values of <literal>and</literal>, <literal>or</literal>, <literal>not</literal>, <literal>all</literal>, <literal>eq</literal>, <literal>neq</literal>, <literal>dom</literal>, <literal>domby</literal>, <literal>incomp</literal>. When <literal>expr_key</literal> is <literal>dom</literal>, <literal>domby</literal> or <literal>incomp</literal>, it must be followed by a string (e.g. <literal>h1</literal>, <literal>l2</literal>) and another string or a set of <literal>name</literal>s. The following examples show CIL constraint statements and their policy language equivalents:</para>
+ <programlisting><![CDATA[
+; Process transition: Require equivalence unless the subject is trusted.
+(mlsconstrain (process (transition dyntransition))
+ (or (and (eq h1 h2) (eq l1 l2)) (eq t1 mlstrustedsubject)))
+
+; The equivalent policy language mlsconstrain statememt is:
+;mlsconstrain process { transition dyntransition }
+; ((h1 eq h2 and l1 eq l2) or t1 == mlstrustedsubject);]]>
+ </programlisting>
+ <programlisting><![CDATA[
+; Process read operations: No read up unless trusted.
+(mlsconstrain (process (getsched getsession getpgid getcap getattr ptrace share))
+ (or (dom l1 l2) (eq t1 mlstrustedsubject)))
+
+; The equivalent policy language mlsconstrain statememt is:
+;mlsconstrain process { getsched getsession getpgid getcap getattr ptrace share }
+; (l1 dom l2 or t1 == mlstrustedsubject);]]>
+ </programlisting>
+ </listitem>
+ </orderedlist>
+ </sect2>
+
+ <sect2 id="name">
+ <title>Name String</title>
+ <para>Used to define <literal><link linkend="macro">macro</link></literal> statement parameter string types:</para>
+ <programlisting><![CDATA[
+(call macro1("__kmsg__"))
+
+(macro macro1 ((string ARG1))
+ (typetransition audit.process device.device chr_file ARG1 device.klog_device)
+)]]>
+ </programlisting>
+ <para>Alternatively:</para>
+ <programlisting><![CDATA[
+(call macro1("__kmsg__"))
+
+(macro macro1 ((name ARG1))
+ (typetransition audit.process device.device chr_file ARG1 device.klog_device)
+)]]>
+ </programlisting>
+ </sect2>
+
+ <sect2>
+ <title>self</title>
+ <para>The <literal>self</literal> keyword may be used as the target in AVC rule statements, and means that the target is the same as the source as shown in the following example:.</para>
+ <programlisting><![CDATA[(allow unconfined.process self (file (read write)))]]></programlisting>
+ </sect2>
+ </sect1>
+
+ &policy_config_statements;
+ &container_statements;
+ &call_macro_statements;
+ &default_object_statements;
+ &user_statements;
+ &role_statements;
+ &type_statements;
+ &class_and_permission_statements;
+ &access_vector_rules;
+ &conditional_statements;
+ &constraint_statements;
+ &mls_labeling_statements;
+ &context_statement;
+ &sid_statements;
+ &file_labeling_statements;
+ &network_labeling_statements;
+ &xen_statements;
+
+ <!-- This section will copy in the latest example ../test/policy.cil file -->
+ <appendix id="example_policy">
+ <title>Example CIL Policy</title>
+ <para>This is the example <filename>policy.cil</filename> file taken from the CIL compiler source code.</para>
+ <programlisting>&policy_cil;
+ </programlisting>
+ <para/>
+ </appendix>
+
+</article>
+
+
diff --git a/cil/docs/Makefile b/cil/docs/Makefile
new file mode 100644
index 0000000..cf18e36
--- /dev/null
+++ b/cil/docs/Makefile
@@ -0,0 +1,50 @@
+HTMLDIR ?= ./html
+PDFDIR ?= ./pdf
+MAN8DIR ?= ./man8
+
+# The CIL Reference Guide first part
+CIL_REF_GUIDE = CIL_Reference_Guide.xml
+# All the docbook files that make up the guide:
+FILE_LIST ?= $(CIL_REF_GUIDE) $(wildcard cil*.xml)
+# xmlto generates a *.proc file that can be removed.
+PROC_FILE = CIL_Reference_Guide.proc
+
+# The secilc man page:
+MANPAGE = secilc.8.xml
+
+
+# look for xmlto and dblatex packages
+XMLTO = $(shell which xmlto 2> /dev/null | grep / | head -n1)
+DBLATEX = $(shell which dblatex 2> /dev/null | grep / | head -n1)
+
+# If no xmlto then exit as cannot proceed.
+ifeq ($(XMLTO),)
+$(error xmlto package not found - install package.)
+endif
+
+all: html pdf man
+
+html: $(FILE_LIST)
+ $(XMLTO) html $(CIL_REF_GUIDE)
+ @mkdir -p $(HTMLDIR)
+ @for m in *.html; do if [ -f $$m ]; then mv $$m $(HTMLDIR); fi; done
+ @rm -f $(PROC_FILE)
+
+
+pdf: $(FILE_LIST)
+# Check if dblatex is available
+ifeq ($(DBLATEX),)
+ $(error dblatex package not found - install package for a pdf document.)
+endif
+ $(XMLTO) --with-dblatex pdf $(CIL_REF_GUIDE)
+ @mkdir -p $(PDFDIR)
+ @for m in *.pdf; do if [ -f $$m ]; then mv $$m $(PDFDIR); fi; done
+ @rm -f $(PROC_FILE)
+
+
+man: $(MANPAGE)
+ $(XMLTO) man $(MANPAGE)
+ @mkdir -p $(MAN8DIR)
+ @for m in *.8; do if [ -f $$m ]; then mv $$m $(MAN8DIR); fi; done
+ @rm -f $(MANPAGE).proc
+
diff --git a/cil/docs/cil_access_vector_rules.xml b/cil/docs/cil_access_vector_rules.xml
new file mode 100644
index 0000000..d3ce095
--- /dev/null
+++ b/cil/docs/cil_access_vector_rules.xml
@@ -0,0 +1,279 @@
+<!-- Common Interface Language (CIL) Reference Guide -->
+ <!-- access_vector_rules.xml -->
+
+ <sect1 id="av_rules">
+ <title>Access Vector Rules</title>
+ <sect2 id="allow">
+ <title>allow</title>
+ <para>Specifies the access allowed between a source and target type. Note that access may be refined by constraint rules based on the source, target and class (<literal><link linkend="validatetrans">validatetrans</link></literal> or <literal><link linkend="mlsvalidatetrans">mlsvalidatetrans</link></literal>) or source, target class and permissions (<literal><link linkend="constrain">constrain</link></literal> or <literal><link linkend="mlsconstrain">mlsconstrain</link></literal> statements).</para>
+ <para><emphasis role="bold">Rule definition:</emphasis></para>
+ <programlisting><![CDATA[(allow source_id target_id|self classpermissionset_id ...)]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2.25 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal><link linkend="allow">allow</link></literal></para>
+ </entry>
+ <entry>
+ <para>The <literal><link linkend="allow">allow</link></literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>source_id</literal></para>
+ </entry>
+ <entry>
+ <para>A single previously defined source <literal><link linkend="type">type</link></literal>, <literal><link linkend="typealias">typealias</link></literal> or <literal><link linkend="typeattribute">typeattribute</link></literal> identifier.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>target_id</literal></para>
+ </entry>
+ <entry>
+ <para>A single previously defined target <literal><link linkend="type">type</link></literal>, <literal><link linkend="typealias">typealias</link></literal> or <literal><link linkend="typeattribute">typeattribute</link></literal> identifier.</para>
+ <para>The <literal>self</literal> keyword may be used instead to signify that source and target are the same.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>classpermissionset_id</literal></para>
+ </entry>
+ <entry>
+ <para>A single named or anonymous <literal><link linkend="classpermissionset">classpermissionset</link></literal> or a single set of <literal><link linkend="classmap">classmap</link></literal>/<literal><link linkend="classmapping">classmapping</link></literal> identifiers.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+
+ <para><emphasis role="bold">Examples:</emphasis></para>
+ <para>These examples show a selection of possible permutations of <literal><link linkend="allow">allow</link></literal> rules:</para>
+ <programlisting><![CDATA[
+(class binder (impersonate call set_context_mgr transfer receive))
+(class property_service (set))
+(class zygote (specifyids specifyrlimits specifycapabilities specifyinvokewith specifyseinfo))
+
+(classpermission cps_zygote)
+(classpermissionset cps_zygote (zygote (not (specifyids))))
+
+(classmap android_classes (set_1 set_2 set_3))
+
+(classmapping android_classes set_1 (binder (all)))
+(classmapping android_classes set_1 (property_service (set)))
+(classmapping android_classes set_1 (zygote (not (specifycapabilities))))
+
+(classmapping android_classes set_2 (binder (impersonate call set_context_mgr transfer)))
+(classmapping android_classes set_2 (zygote (specifyids specifyrlimits specifycapabilities specifyinvokewith)))
+
+(classmapping android_classes set_3 cps_zygote)
+(classmapping android_classes set_3 (binder (impersonate call set_context_mgr)))
+
+(block av_rules
+ (type type_1)
+ (type type_2)
+ (type type_3)
+ (type type_4)
+ (type type_5)
+
+ (typeattribute all_types)
+ (typeattributeset all_types (all))
+
+; These examples have named and anonymous classpermissionset's and
+; classmap/classmapping statements
+ (allow type_1 self (property_service (set))) ; anonymous
+ (allow type_2 self (zygote (specifyids))) ; anonymous
+ (allow type_3 self cps_zygote) ; named
+ (allow type_4 self (android_classes (set_3))) ; classmap/classmapping
+ (allow all_types all_types (android_classes (set_2))) ; classmap/classmapping
+
+;; This rule will cause the build to fail unless --disable-neverallow
+; (neverallow type_5 all_types (property_service (set)))
+ (allow type_5 type_5 (property_service (set)))
+ (allow type_1 all_types (property_service (set)))
+)]]>
+ </programlisting>
+ </sect2>
+
+ <sect2 id="auditallow">
+ <title>auditallow</title>
+ <para>Audit the access rights defined if there is a valid allow rule. Note: It does NOT allow access, it only audits the event.</para>
+ <para><emphasis role="bold">Rule definition:</emphasis></para>
+ <programlisting><![CDATA[(auditallow source_id target_id|self classpermissionset_id ...)]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2.5 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>auditallow</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>auditallow</literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>source_id</literal></para>
+ </entry>
+ <entry>
+ <para>A single previously defined source <literal><link linkend="type">type</link></literal>, <literal><link linkend="typealias">typealias</link></literal> or <literal><link linkend="typeattribute">typeattribute</link></literal> identifier.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>target_id</literal></para>
+ </entry>
+ <entry>
+ <para>A single previously defined target <literal><link linkend="type">type</link></literal>, <literal><link linkend="typealias">typealias</link></literal> or <literal><link linkend="typeattribute">typeattribute</link></literal> identifier.</para>
+ <para>The <literal>self</literal> keyword may be used instead to signify that source and target are the same.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>classpermissionset_id</literal></para>
+ </entry>
+ <entry>
+ <para>A single named or anonymous <literal><link linkend="classpermissionset">classpermissionset</link></literal> or a single set of <literal><link linkend="classmap">classmap</link></literal>/<literal><link linkend="classmapping">classmapping</link></literal> identifiers.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+
+ <para><emphasis role="bold">Example:</emphasis></para>
+ <para>This example will log an audit event whenever the corresponding <literal><link linkend="allow">allow</link></literal> rule grants access to the specified permissions:</para>
+ <programlisting><![CDATA[
+(allow release_app.process secmark_demo.browser_packet (packet (send recv append bind)))
+
+(auditallow release_app.process secmark_demo.browser_packet (packet (send recv)))
+]]>
+ </programlisting>
+ </sect2>
+
+ <sect2 id="dontaudit">
+ <title>dontaudit</title>
+ <para>Do not audit the access rights defined when access denied. This stops excessive log entries for known events.</para>
+ <para>Note that these rules can be omitted by the CIL compiler command line parameter <literal>-D</literal> or <literal>--disable-dontaudit</literal> flags.</para>
+ <para><emphasis role="bold">Rule definition:</emphasis></para>
+ <programlisting><![CDATA[(dontaudit source_id target_id|self classpermissionset_id ...)]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2.25 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>dontaudit</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>dontaudit</literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>source_id</literal></para>
+ </entry>
+ <entry>
+ <para>A single previously defined source <literal><link linkend="type">type</link></literal>, <literal><link linkend="typealias">typealias</link></literal> or <literal><link linkend="typeattribute">typeattribute</link></literal> identifier.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>target_id</literal></para>
+ </entry>
+ <entry>
+ <para>A single previously defined target <literal><link linkend="type">type</link></literal>, <literal><link linkend="typealias">typealias</link></literal> or <literal><link linkend="typeattribute">typeattribute</link></literal> identifier.</para>
+ <para>The <literal>self</literal> keyword may be used instead to signify that source and target are the same.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>classpermissionset_id</literal></para>
+ </entry>
+ <entry>
+ <para>A single named or anonymous <literal><link linkend="classpermissionset">classpermissionset</link></literal> or a single set of <literal><link linkend="classmap">classmap</link></literal>/<literal><link linkend="classmapping">classmapping</link></literal> identifiers.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+
+ <para><emphasis role="bold">Example:</emphasis></para>
+ <para>This example will not audit the denied access:</para>
+ <programlisting><![CDATA[(dontaudit zygote.process self (capability (fsetid)))]]>
+ </programlisting>
+ </sect2>
+
+ <sect2 id="neverallow">
+ <title>neverallow</title>
+ <para>Never allow access rights defined. This is a compiler enforced action that will stop compilation until the offending rules are modified.</para>
+ <para>Note that these rules can be over-ridden by the CIL compiler command line parameter <literal>-N</literal> or <literal>--disable-neverallow</literal> flags.</para>
+ <para><emphasis role="bold">Rule definition:</emphasis></para>
+ <programlisting><![CDATA[(neverallow source_id target_id|self classpermissionset_id ...)]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2.25 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>neverallow</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>neverallow</literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>source_id</literal></para>
+ </entry>
+ <entry>
+ <para>A single previously defined source <literal><link linkend="type">type</link></literal>, <literal><link linkend="typealias">typealias</link></literal> or <literal><link linkend="typeattribute">typeattribute</link></literal> identifier.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>target_id</literal></para>
+ </entry>
+ <entry>
+ <para>A single previously defined target <literal><link linkend="type">type</link></literal>, <literal><link linkend="typealias">typealias</link></literal> or <literal><link linkend="typeattribute">typeattribute</link></literal> identifier.</para>
+ <para>The <literal>self</literal> keyword may be used instead to signify that source and target are the same.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>classpermissionset_id</literal></para>
+ </entry>
+ <entry>
+ <para>A single named or anonymous <literal><link linkend="classpermissionset">classpermissionset</link></literal> or a single set of <literal><link linkend="classmap">classmap</link></literal>/<literal><link linkend="classmapping">classmapping</link></literal> identifiers.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+
+ <para><emphasis role="bold">Example:</emphasis></para>
+ <para>This example will not compile as <literal>type_3</literal> is not allowed to be a source type for the <literal><link linkend="allow">allow</link></literal> rule:</para>
+ <programlisting><![CDATA[
+(class property_service (set))
+
+(block av_rules
+ (type type_1)
+ (type type_2)
+ (type type_3)
+ (typeattribute all_types)
+ (typeattributeset all_types ((all)))
+
+ (neverallow type_3 all_types (property_service (set)))
+ ; This rule will fail compilation:
+ (allow type_3 self (property_service (set)))
+)]]>
+ </programlisting>
+ </sect2>
+
+ </sect1>
diff --git a/cil/docs/cil_call_macro_statements.xml b/cil/docs/cil_call_macro_statements.xml
new file mode 100644
index 0000000..b783515
--- /dev/null
+++ b/cil/docs/cil_call_macro_statements.xml
@@ -0,0 +1,174 @@
+<!-- Common Interface Language (CIL) Reference Guide -->
+ <!-- call_macro_statements.xml -->
+
+ <sect1>
+ <title>Call / Macro Statements</title>
+ <sect2 id="call">
+ <title>call</title>
+ <para>Instantiate a <link linkend="macro">macro</link> within the current namespace. There may be zero or more parameters passed to the macro (with zero parameters this is similar to the <literal><link linkend="blockinherit">blockinherit</link></literal> (<literal><link linkend="call">call</link></literal>) / <literal><link linkend="blockabstract">blockabstract</link></literal> (<literal><link linkend="macro">macro</link></literal>) statements).</para>
+ <para>Each parameter passed contains an argument to be resolved by the <link linkend="macro">macro</link>, these can be named or anonymous but must conform to the parameter types defined in the <literal><link linkend="macro">macro</link></literal> statement.</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(call macro_id [(param ...)])]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal><link linkend="call">call</link></literal></para>
+ </entry>
+ <entry>
+ <para>The <literal><link linkend="call">call</link></literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>macro_id</literal></para>
+ </entry>
+ <entry>
+ <para>The identifier of the <literal><link linkend="macro">macro</link></literal> to be instantiated.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>param</literal></para>
+ </entry>
+ <entry>
+ <para>Zero or more parameters that are passed to the macro.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+ <para><emphasis role="bold">Example:</emphasis></para>
+ <para>See the <literal><link linkend="macro">macro</link></literal> statement for an example.</para>
+ </sect2>
+
+ <sect2 id="macro">
+ <title>macro</title>
+ <para>Declare a macro in the current namespace with its associated parameters. The macro identifier is used by the <literal><link linkend="call">call</link></literal> statement to instantiate the macro and resolve any parameters. The call statement may be within the body of a macro.</para>
+
+ <para>Note that when resolving macros the callers namespace is not checked, only the following places:
+ <itemizedlist>
+ <listitem><simpara>Items defined inside the macro</simpara></listitem>
+ <listitem><simpara>Items passed into the macro as arguments</simpara></listitem>
+ <listitem><simpara>Items defined in the same namespace of the macro</simpara></listitem>
+ <listitem><simpara>Items defined in the global namespace</simpara></listitem>
+ </itemizedlist>
+ </para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[
+(macro macro_id ([(param_type param_id) ...])
+ cil_statements
+ ...
+)]]>
+ </programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal><link linkend="macro">macro</link></literal></para>
+ </entry>
+ <entry>
+ <para>The <literal><link linkend="macro">macro</link></literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>macro_id</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal><link linkend="macro">macro</link></literal> identifier.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>param_type</literal></para>
+ </entry>
+ <entry>
+ <para>Zero or more parameters that are passed to the macro. The <literal>param_type</literal> is a keyword used to determine the declaration type (e.g. <literal>type</literal>, <literal>class</literal>, <literal>categoryset</literal>).</para>
+ <para>The list of valid <literal>param_type</literal> entries are:
+ <simplelist type="inline">
+ <member><literal><link linkend="type">type</link></literal></member>
+ <member><literal><link linkend="typealias">typealias</link></literal></member>
+ <member><literal><link linkend="role">role</link></literal></member>
+ <member><literal><link linkend="user">user</link></literal></member>
+ <member><literal><link linkend="sensitivity">sensitivity</link></literal></member>
+ <member><literal><link linkend="sensitivityalias">sensitivityalias</link></literal></member>
+ <member><literal><link linkend="category">category</link></literal></member>
+ <member><literal><link linkend="categoryalias">categoryalias</link></literal></member>
+ <member><literal><link linkend="categoryset">categoryset</link></literal> (named or anonymous)</member>
+ <member><literal><link linkend="level">level</link></literal> (named or anonymous)</member>
+ <member><literal><link linkend="levelrange">levelrange</link></literal> (named or anonymous)</member>
+ <member><literal><link linkend="class">class</link></literal></member>
+ <member><literal><link linkend="classpermission">classpermission</link></literal> (named or anonymous)</member>
+ <member><literal><link linkend="ipaddr">ipaddr</link></literal> (named or anonymous)</member>
+ <member><literal><link linkend="boolean">block</link></literal></member>
+ <member><literal><link linkend="name">name</link></literal> (a string)</member>
+ <member><literal><link linkend="classmap">classmap</link></literal></member>
+ </simplelist></para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>param_id</literal></para>
+ </entry>
+ <entry>
+ <para>The parameter identifier used to reference the entry within the macro body (e.g. <literal>ARG1</literal>).</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>cil_statement</literal></para>
+ </entry>
+ <entry>
+ <para>Zero or more valid CIL statements.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+
+ <para><emphasis role="bold">Examples:</emphasis></para>
+ <para>This example will instantiate the <literal>binder_call</literal> macro in the calling namespace (<literal>my_domain</literal>) and replace <literal>ARG1</literal> with <literal>appdomain</literal> and <literal>ARG2</literal> with <literal>binderservicedomain</literal>:</para>
+ <programlisting><![CDATA[
+(block my_domain
+ (call binder_call (appdomain binderservicedomain))
+)
+
+(macro binder_call ((type ARG1) (type ARG2))
+ (allow ARG1 ARG2 (binder (call transfer)))
+ (allow ARG2 ARG1 (binder (transfer)))
+ (allow ARG1 ARG2 (fd (use)))
+)]]>
+ </programlisting>
+
+ <para>This example does not pass any parameters to the macro but adds a <literal>type</literal> identifier to the current namespace:</para>
+ <programlisting><![CDATA[
+(block unconfined
+ (call add_type)
+ ....
+
+ (macro add_type ()
+ (type exec)
+ )
+)]]>
+ </programlisting>
+
+ <para>This example passes an anonymous and named IP address to the macro:</para>
+ <programlisting><![CDATA[
+(ipaddr netmask_1 255.255.255.0)
+(context netlabel_1 (system.user object_r unconfined.object low_low)
+
+(call build_nodecon ((192.168.1.64) netmask_1))
+
+(macro build_nodecon ((ipaddr ARG1) (ipaddr ARG2))
+ (nodecon ARG1 ARG2 netlabel_1)
+)]]>
+ </programlisting>
+ </sect2>
+ </sect1>
diff --git a/cil/docs/cil_class_and_permission_statements.xml b/cil/docs/cil_class_and_permission_statements.xml
new file mode 100644
index 0000000..25929b1
--- /dev/null
+++ b/cil/docs/cil_class_and_permission_statements.xml
@@ -0,0 +1,493 @@
+<!-- Common Interface Language (CIL) Reference Guide -->
+ <!-- class_and_permission_statements.xml -->
+
+ <sect1>
+ <title>Class and Permission Statements</title>
+ <sect2 id="common">
+ <title>common</title>
+ <para>Declares a common identifier in the current namespace with a set of common permissions that can be used by one or more <literal><link linkend="class">class</link></literal> identifiers. The <literal><link linkend="classcommon">classcommon</link></literal> statement is used to associate a <literal><link linkend="common">common</link></literal> identifier to a specific <literal><link linkend="class">class</link></literal> identifier.</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(common common_id (permission_id ...))]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal><link linkend="common">common</link></literal></para>
+ </entry>
+ <entry>
+ <para>The <literal><link linkend="common">common</link></literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>common_id</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal><link linkend="common">common</link></literal> identifier.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>permission_id</literal></para>
+ </entry>
+ <entry>
+ <para>One or more permissions.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+
+ <para><emphasis role="bold">Example:</emphasis></para>
+ <para>This common statement will associate the <literal><link linkend="common">common</link></literal> identifier '<literal>file</literal>' with the list of permissions:</para>
+ <programlisting><![CDATA[
+(common file (ioctl read write create getattr setattr lock relabelfrom relabelto append unlink link rename execute swapon quotaon mounton))]]>
+ </programlisting>
+ </sect2>
+
+ <sect2 id="classcommon">
+ <title>classcommon</title>
+ <para>Associate a <literal><link linkend="class">class</link></literal> identifier to a one or more permissions declared by a <literal><link linkend="common">common</link></literal> identifier.</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(classcommon class_id common_id)]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal><link linkend="classcommon">classcommon</link></literal></para>
+ </entry>
+ <entry>
+ <para>The <literal><link linkend="classcommon">classcommon</link></literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>class_id</literal></para>
+ </entry>
+ <entry>
+ <para>A single previously declared <literal><link linkend="class">class</link></literal> identifier.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>common_id</literal></para>
+ </entry>
+ <entry>
+ <para>A single previously declared <literal><link linkend="common">common</link></literal> identifier that defines the common permissions for that class.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+ <para><emphasis role="bold">Example:</emphasis></para>
+ <para>This associates the <literal>dir</literal> class with the list of permissions declared by the <literal>file common</literal> identifier:</para>
+ <programlisting><![CDATA[
+(common file (ioctl read write create getattr setattr lock relabelfrom relabelto append unlink link rename execute swapon quotaon mounton))
+
+(classcommon dir file)]]>
+ </programlisting>
+ </sect2>
+
+ <sect2 id="class">
+ <title>class</title>
+ <para>Declares a class and zero or more permissions in the current namespace.</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(class class_id (permission_id ...))]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal><link linkend="class">class</link></literal></para>
+ </entry>
+ <entry>
+ <para>The <literal><link linkend="class">class</link></literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>class_id</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal><link linkend="class">class</link></literal> identifier.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>permission_id</literal></para>
+ </entry>
+ <entry>
+ <para>Zero or more permissions declared for the class. Note that if zero permissions, an empty list is required as shown in the example.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+
+ <para><emphasis role="bold">Examples:</emphasis></para>
+ <para>This example defines a set of permissions for the <literal>binder</literal> class indentifier:</para>
+ <programlisting><![CDATA[(class binder (impersonate call set_context_mgr transfer receive))]]>
+ </programlisting>
+
+ <para>This example defines a common set of permissions to be used by the <literal>sem</literal> class, the <literal>(class sem ())</literal> does not define any other permissions (i.e. an empty list):</para>
+ <programlisting><![CDATA[
+(common ipc (create destroy getattr setattr read write associate unix_read unix_write))
+
+(classcommon sem ipc)
+(class sem ())]]>
+ </programlisting>
+ <simpara>and will produce the following set of permissions for the <literal>sem</literal> class identifier of:</simpara>
+ <programlisting><![CDATA[(class sem (create destroy getattr setattr read write associate unix_read unix_write))]]>
+ </programlisting>
+
+ <para>This example, with the following combination of the <literal><link linkend="common">common</link></literal>, <literal><link linkend="classcommon">classcommon</link></literal> and <literal><link linkend="class">class</link></literal> statements:</para>
+ <programlisting><![CDATA[
+(common file (ioctl read write create getattr setattr lock relabelfrom relabelto append unlink link rename execute swapon quotaon mounton))
+
+(classcommon dir file)
+(class dir (add_name remove_name reparent search rmdir open audit_access execmod))]]>
+ </programlisting>
+ <simpara>will produce a set of permissions for the <literal>dir</literal> class identifier of:</simpara>
+ <programlisting><![CDATA[(class dir (add_name remove_name reparent search rmdir open audit_access execmod ioctl read write create getattr setattr lock relabelfrom relabelto append unlink link rename execute swapon quotaon mounton))]]>
+ </programlisting>
+ </sect2>
+ <sect2 id="classorder">
+ <title>classorder</title>
+ <para>Defines the order of <link linkend="class">class</link>'s. This is a mandatory statement. Multiple <literal>classorder</literal> statements declared in the policy will form an ordered list.</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(classorder (class_id ...))]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>classorder</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>classorder</literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>class_id</literal></para>
+ </entry>
+ <entry>
+ <para>One or more <literal><link linkend="class">class</link></literal> identifiers.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+
+ <para><emphasis role="bold">Example:</emphasis></para>
+ <para>This will produce an ordered list of "<literal>file dir process</literal>"</para>
+ <programlisting><![CDATA[
+(class process)
+(class file)
+(class dir)
+(classorder (file dir))
+(classorder (dir process))]]>
+ </programlisting>
+ </sect2>
+ <sect2 id="classpermission">
+ <title>classpermission</title>
+ <para>Declares a class permission set identifier in the current namespace that can be used by one or more <literal><link linkend="classpermissionset">classpermissionset</link></literal>s to associate one or more classes and permissions to form a named set.</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(classpermission classpermissionset_id)]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal><link linkend="classpermission">classpermission</link></literal></para>
+ </entry>
+ <entry>
+ <para>The <literal><link linkend="classpermission">classpermission</link></literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>classpermissionset_id</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal><link linkend="classpermissionset">classpermissionset</link></literal> identifier.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+ <para><emphasis role="bold">Example:</emphasis></para>
+ <para>See the <literal><link linkend="classpermissionset">classpermissionset</link></literal> statement for examples.</para>
+ </sect2>
+
+ <sect2 id="classpermissionset">
+ <title>classpermissionset</title>
+ <para>Defines a class permission set identifier in the current namespace that associates a class and one or more permissions to form a named set. Nested expressions may be used to determine the required permissions as shown in the examples. Anonymous <literal>classpermissionset</literal>s may be used in av rules and constraints.</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(classpermissionset classpermissionset_id (class_id (permission_id | expr ...)))]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2.25 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal><link linkend="classpermissionset">classpermissionset</link></literal></para>
+ </entry>
+ <entry>
+ <para>The <literal><link linkend="classpermissionset">classpermissionset</link></literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>classpermissionset_id</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal><link linkend="classpermissionset">classpermissionset</link></literal> identifier.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>class_id</literal></para>
+ </entry>
+ <entry>
+ <para>A single previously declared <literal><link linkend="class">class</link></literal> identifier.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>permission_id</literal></para>
+ </entry>
+ <entry>
+ <para>Zero or more permissions required by the class.</para>
+ <para>Note that there must be at least one <literal>permission</literal> identifier or <literal>expr</literal> declared).</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>expr</literal></para>
+ </entry>
+ <entry>
+ <para>Zero or more <literal>expr</literal>'s, the valid operators and syntax are:</para>
+ <simpara><literal> (and (permission_id ...) (permission_id ...))</literal></simpara>
+ <simpara><literal> (or (permission_id ...) (permission_id ...))</literal></simpara>
+ <simpara><literal> (xor (permission_id ...) (permission_id ...))</literal></simpara>
+ <simpara><literal> (not (permission_id ...))</literal></simpara>
+ <simpara><literal> (all)</literal></simpara>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+
+ <para><emphasis role="bold">Examples:</emphasis></para>
+ <para>These class permission set statements will resolve to the permission sets shown in the kernel policy language <literal><link linkend="allow">allow</link></literal> rules:</para>
+ <programlisting><![CDATA[
+(class zygote (specifyids specifyrlimits specifycapabilities specifyinvokewith specifyseinfo))
+
+(type test_1)
+(type test_2)
+(type test_3)
+(type test_4)
+(type test_5)
+
+; NOT
+(classpermission zygote_1)
+(classpermissionset zygote_1 (zygote
+ (not
+ (specifyinvokewith specifyseinfo)
+ )
+))
+(allow unconfined.process test_1 zygote_1)
+;; allow unconfined.process test_1 : zygote { specifyids specifyrlimits specifycapabilities } ;
+
+; AND - ALL - NOT - Equiv to test_1
+(classpermission zygote_2)
+(classpermissionset zygote_2 (zygote
+ (and
+ (all)
+ (not (specifyinvokewith specifyseinfo))
+ )
+))
+(allow unconfined.process test_2 zygote_2)
+;; allow unconfined.process test_2 : zygote { specifyids specifyrlimits specifycapabilities } ;
+
+; OR
+(classpermission zygote_3)
+(classpermissionset zygote_3 (zygote ((or (specifyinvokewith) (specifyseinfo)))))
+(allow unconfined.process test_3 zygote_3)
+;; allow unconfined.process test_3 : zygote { specifyinvokewith specifyseinfo } ;
+
+; XOR - This will not produce an allow rule as the XOR will remove all the permissions:
+(classpermission zygote_4)
+(classpermissionset zygote_4 (zygote (xor (specifyids specifyrlimits specifycapabilities specifyinvokewith specifyseinfo) (specifyids specifyrlimits specifycapabilities specifyinvokewith specifyseinfo))))
+
+; ALL
+(classpermission zygote_all_perms)
+(classpermissionset zygote_all_perms (zygote (all)))
+(allow unconfined.process test_5 zygote_all_perms)
+;; allow unconfined.process test_5 : zygote { specifyids specifyrlimits specifycapabilities specifyinvokewith specifyseinfo } ;]]>
+ </programlisting>
+ </sect2>
+
+ <sect2 id="classmap">
+ <title>classmap</title>
+ <para>Declares a class map identifier in the current namespace and one or more class mapping identifiers. This will allow:</para>
+ <orderedlist>
+ <listitem><para>Multiple <literal><link linkend="classpermissionset">classpermissionset</link></literal>s to be linked to a pair of <literal><link linkend="classmap">classmap</link></literal> / <literal><link linkend="classmapping">classmapping</link></literal> identifiers.</para></listitem>
+ <listitem><para>Multiple <literal><link linkend="class">class</link></literal>s to be associated to statements and rules that support a list of classes:</para>
+ <simplelist type="inline">
+ <member><literal><link linkend="typetransition">typetransition</link></literal></member>
+ <member><literal><link linkend="typechange">typechange</link></literal></member>
+ <member><literal><link linkend="typemember">typemember</link></literal></member>
+ <member><literal><link linkend="rangetransition">rangetransition</link></literal></member>
+ <member><literal><link linkend="roletransition">roletransition</link></literal></member>
+ <member><literal><link linkend="defaultuser">defaultuser</link></literal></member>
+ <member><literal><link linkend="defaultrole">defaultrole</link></literal></member>
+ <member><literal><link linkend="defaulttype">defaulttype</link></literal></member>
+ <member><literal><link linkend="defaultrange">defaultrange</link></literal></member>
+ <member><literal><link linkend="validatetrans">validatetrans</link></literal></member>
+ <member><literal><link linkend="mlsvalidatetrans">mlsvalidatetrans</link></literal></member>
+ </simplelist></listitem>
+ </orderedlist>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(classmap classmap_id (classmapping_id ...))]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal><link linkend="classmap">classmap</link></literal></para>
+ </entry>
+ <entry>
+ <para>The <literal><link linkend="classmap">classmap</link></literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>classmap_id</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal><link linkend="classmap">classmap</link></literal> identifier.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>classmapping_id</literal></para>
+ </entry>
+ <entry>
+ <para>One or more <literal><link linkend="classmapping">classmapping</link></literal> identifiers.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+ <para><emphasis role="bold">Example:</emphasis></para>
+ <para>See the <literal><link linkend="classmapping">classmapping</link></literal> statement for examples.</para>
+ </sect2>
+
+ <sect2 id="classmapping">
+ <title>classmapping</title>
+ <para>Define sets of <literal><link linkend="classpermissionset">classpermissionset</link></literal>s (named or anonymous) to form a consolidated <literal><link linkend="classmapping">classmapping</link></literal> set. Generally there are multiple <literal><link linkend="classmapping">classmapping</link></literal> statements with the same <literal><link linkend="classmap">classmap</link></literal> and <literal><link linkend="classmapping">classmapping</link></literal> identifiers that form a set of different <literal><link linkend="classpermissionset">classpermissionset</link></literal>'s. This is useful when multiple class / permissions are required in rules such as the <literal><link linkend="allow">allow</link></literal> rules (as shown in the examples).</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(classmapping classmap_id classmapping_id classpermissionset_id)]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2.25 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal><link linkend="classmapping">classmapping</link></literal></para>
+ </entry>
+ <entry>
+ <para>The <literal><link linkend="classmapping">classmapping</link></literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>classmap_id</literal></para>
+ </entry>
+ <entry>
+ <para>A single previously declared <literal><link linkend="classmap">classmap</link></literal> identifier.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>classmapping_id</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal><link linkend="classmapping">classmapping</link></literal> identifier.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>classpermissionset_id</literal></para>
+ </entry>
+ <entry>
+ <para>A single named <literal><link linkend="classpermissionset">classpermissionset</link></literal> identifier or a single anonymous <literal><link linkend="classpermissionset">classpermissionset</link></literal> using <literal>expr</literal>'s as required (see the <literal><link linkend="classpermissionset">classpermissionset</link></literal> statement).</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+ <para><emphasis role="bold">Examples:</emphasis></para>
+ <para>These class mapping statements will resolve to the permission sets shown in the kernel policy language <literal><link linkend="allow">allow</link></literal> rules:</para>
+ <programlisting><![CDATA[
+(class binder (impersonate call set_context_mgr transfer receive))
+(class property_service (set))
+(class zygote (specifyids specifyrlimits specifycapabilities specifyinvokewith specifyseinfo))
+
+(classpermission cps_zygote)
+(classpermissionset cps_zygote (zygote (not (specifyids))))
+
+(classmap android_classes (set_1 set_2 set_3))
+
+(classmapping android_classes set_1 (binder (all)))
+(classmapping android_classes set_1 (property_service (set)))
+(classmapping android_classes set_1 (zygote (not (specifycapabilities))))
+
+(classmapping android_classes set_2 (binder (impersonate call set_context_mgr transfer)))
+(classmapping android_classes set_2 (zygote (specifyids specifyrlimits specifycapabilities specifyinvokewith)))
+
+(classmapping android_classes set_3 cps_zygote)
+(classmapping android_classes set_3 (binder (impersonate call set_context_mgr)))
+
+(block map_example
+ (type type_1)
+ (type type_2)
+ (type type_3)
+
+ (allow type_1 self (android_classes (set_1)))
+ (allow type_2 self (android_classes (set_2)))
+ (allow type_3 self (android_classes (set_3)))
+)
+
+; The above will resolve to the following AV rules:
+;; allow map_example.type_1 map_example.type_1 : binder { impersonate call set_context_mgr transfer receive } ;
+;; allow map_example.type_1 map_example.type_1 : property_service set ;
+;; allow map_example.type_1 map_example.type_1 : zygote { specifyids specifyrlimits specifyinvokewith specifyseinfo } ;
+
+;; allow map_example.type_2 map_example.type_2 : binder { impersonate call set_context_mgr transfer } ;
+;; allow map_example.type_2 map_example.type_2 : zygote { specifyids specifyrlimits specifycapabilities specifyinvokewith } ;
+
+;; allow map_example.type_3 map_example.type_3 : binder { impersonate call set_context_mgr } ;
+;; allow map_example.type_3 map_example.type_3 : zygote { specifyrlimits specifycapabilities specifyinvokewith specifyseinfo } ;]]>
+ </programlisting>
+ </sect2>
+
+ </sect1>
diff --git a/cil/docs/cil_conditional_statements.xml b/cil/docs/cil_conditional_statements.xml
new file mode 100644
index 0000000..aa30afa
--- /dev/null
+++ b/cil/docs/cil_conditional_statements.xml
@@ -0,0 +1,269 @@
+<!-- Common Interface Language (CIL) Reference Guide -->
+ <!-- conditional_statements.xml -->
+
+ <sect1>
+ <title>Conditional Statements</title>
+ <sect2 id="boolean">
+ <title>boolean</title>
+ <para>Declares a run time boolean as true or false in the current namespace. The <literal><link linkend="booleanif">booleanif</link></literal> statement contains the CIL code that will be in the binary policy file.</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(boolean boolean_id true|false)]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal><link linkend="boolean">boolean</link></literal></para>
+ </entry>
+ <entry>
+ <para>The <literal><link linkend="boolean">boolean</link></literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>boolean_id</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal><link linkend="boolean">boolean</link></literal> identifier.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>true | false</literal></para>
+ </entry>
+ <entry>
+ <para>The initial state of the boolean. This can be changed at run time using <emphasis role="bold"><literal>setsebool</literal></emphasis><literal>(8)</literal> and its status queried using <emphasis role="bold"><literal>getsebool</literal></emphasis><literal>(8)</literal>.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+ <para><emphasis role="bold">Example:</emphasis></para>
+ <para>See the <literal><link linkend="booleanif">booleanif</link></literal> statement for an example.</para>
+ </sect2>
+
+ <sect2 id="booleanif">
+ <title>booleanif</title>
+ <para>Contains the run time conditional statements that are instantiated in the binary policy according to the computed boolean identifier(s) state.</para>
+ <para><literal><link linkend="call">call</link></literal> statements are allowed within a <literal><link linkend="booleanif">booleanif</link></literal>, however the contents of the resulting macro must be limited to those of the <literal><link linkend="booleanif">booleanif</link></literal> statement (i.e. <literal><link linkend="allow">allow</link></literal>, <literal><link linkend="auditallow">auditallow</link></literal>, <literal><link linkend="dontaudit">dontaudit</link></literal>, <literal><link linkend="typemember">typemember</link></literal>, <literal><link linkend="typetransition">typetransition</link></literal>, <literal><link linkend="typechange">typechange</link></literal> and the compile time <literal><link linkend="tunableif">tunableif</link></literal> statement)).</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[
+(booleanif boolean_id | expr ...)
+ (true
+ cil_statements
+ ...)
+ (false
+ cil_statements
+ ...)
+)]]>
+ </programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal><link linkend="booleanif">booleanif</link></literal></para>
+ </entry>
+ <entry>
+ <para>The <literal><link linkend="booleanif">booleanif</link></literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>boolean_id</literal></para>
+ </entry>
+ <entry>
+ <para>Either a single <literal><link linkend="boolean">boolean</link></literal> identifier or one or more <literal>expr</literal>'s.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>expr</literal></para>
+ </entry>
+ <entry>
+ <para>Zero or more <literal>expr</literal>'s, the valid operators and syntax are:</para>
+ <simpara><literal> (and (boolean_id boolean_id))</literal></simpara>
+ <simpara><literal> (or (boolean_id boolean_id))</literal></simpara>
+ <simpara><literal> (xor (boolean_id boolean_id))</literal></simpara>
+ <simpara><literal> (eq (boolean_id boolean_id))</literal></simpara>
+ <simpara><literal> (neq (boolean_id boolean_id))</literal></simpara>
+ <simpara><literal> (not (boolean_id))</literal></simpara>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>true</literal></para>
+ </entry>
+ <entry>
+ <para>An optional set of CIL statements that will be instantiated when the <literal><link linkend="boolean">boolean</link></literal> is evaluated as <literal>true</literal>.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>false</literal></para>
+ </entry>
+ <entry>
+ <para>An optional set of CIL statements that will be instantiated when the <literal><link linkend="boolean">boolean</link></literal> is evaluated as <literal>false</literal>.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+
+ <para><emphasis role="bold">Examples:</emphasis></para>
+ <para>The second example also shows the kernel policy language equivalent:</para>
+ <programlisting><![CDATA[
+(boolean disableAudio false)
+
+(booleanif disableAudio
+ (false
+ (allow process mediaserver.audio_device (chr_file_set (rw_file_perms)))
+ )
+)]]>
+ </programlisting>
+ <programlisting><![CDATA[
+(boolean disableAudioCapture false)
+
+;;; if(!disableAudio && !disableAudioCapture) {
+(booleanif (and (not disableAudio) (not disableAudioCapture))
+ (true
+ (allow process mediaserver.audio_capture_device (chr_file_set (rw_file_perms)))
+ )
+)]]>
+ </programlisting>
+ </sect2>
+
+ <sect2 id="tunable">
+ <title>tunable</title>
+ <para>Tunables are similar to booleans, however they are used to manage areas of CIL statements that may or may not be in the final CIL policy that will be compiled (whereas booleans are embedded in the binary policy and can be enabled or disabled during run-time).</para>
+ <para>Note that tunables can be treated as booleans by the CIL compiler command line parameter <literal>-P</literal> or <literal>--preserve-tunables</literal> flags.</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(tunable tunable_id true|false)]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>tunable</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal><link linkend="tunable">tunable</link></literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>tunable_id</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal><link linkend="tunable">tunable</link></literal> identifier.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>true | false</literal></para>
+ </entry>
+ <entry>
+ <para>The initial state of the <literal><link linkend="tunable">tunable</link></literal>.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+ <para><emphasis role="bold">Example:</emphasis></para>
+ <para>See the <literal><link linkend="tunableif">tunableif</link></literal> statement for an example.</para>
+ </sect2>
+
+ <sect2 id="tunableif">
+ <title>tunableif</title>
+ <para>Compile time conditional statement that may or may not add CIL statements to be compiled.</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[
+(tunableif tunable_id | expr ...)
+ (true
+ cil_statements
+ ...)
+ (false
+ cil_statements
+ ...)
+)]]>
+ </programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>tunableif</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal><link linkend="tunableif">tunableif</link></literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>tunable_id</literal></para>
+ </entry>
+ <entry>
+ <para>Either a single <literal><link linkend="tunable">tunable</link></literal> identifier or one or more <literal>expr</literal>'s.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>expr</literal></para>
+ </entry>
+ <entry>
+ <para>Zero or more <literal>expr</literal>'s, the valid operators and syntax are:</para>
+ <simpara><literal> (and (tunable_id tunable_id))</literal></simpara>
+ <simpara><literal> (or (tunable_id tunable_id))</literal></simpara>
+ <simpara><literal> (xor (tunable_id tunable_id))</literal></simpara>
+ <simpara><literal> (eq (tunable_id tunable_id))</literal></simpara>
+ <simpara><literal> (neq (tunable_id tunable_id))</literal></simpara>
+ <simpara><literal> (not (tunable_id))</literal></simpara>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>true</literal></para>
+ </entry>
+ <entry>
+ <para>An optional set of CIL statements that will be instantiated when the <literal><link linkend="tunable">tunable</link></literal> is evaluated as <literal>true</literal>.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>false</literal></para>
+ </entry>
+ <entry>
+ <para>An optional set of CIL statements that will be instantiated when the <literal><link linkend="tunable">tunable</link></literal> is evaluated as <literal>false</literal>.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+
+ <para><emphasis role="bold">Example:</emphasis></para>
+ <para>This example will not add the range transition rule to the binary policy:</para>
+ <programlisting><![CDATA[
+(tunable range_trans_rule false)
+
+(block init
+ (class process (process))
+ (type process)
+
+ (tunableif range_trans_rule
+ (true
+ (rangetransition process sshd.exec process low_high)
+ )
+ ) ; End tunableif
+) ; End block]]>
+ </programlisting>
+ </sect2>
+
+ </sect1>
diff --git a/cil/docs/cil_constraint_statements.xml b/cil/docs/cil_constraint_statements.xml
new file mode 100644
index 0000000..6f5d9c6
--- /dev/null
+++ b/cil/docs/cil_constraint_statements.xml
@@ -0,0 +1,363 @@
+<!-- Common Interface Language (CIL) Reference Guide -->
+ <!-- constraint_statements.xml -->
+
+ <sect1>
+ <title>Constraint Statements</title>
+ <sect2 id="constrain">
+ <title>constrain</title>
+ <para>Enable constraints to be placed on the specified permissions of the object class based on the source and target security context components.</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(constrain classpermissionset_id ... expression | expr ...)]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2.25 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>constrain</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>constrain</literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>classpermissionset_id</literal></para>
+ </entry>
+ <entry>
+ <para>A single named or anonymous <literal><link linkend="classpermissionset">classpermissionset</link></literal> or a single set of <literal><link linkend="classmap">classmap</link></literal>/<literal><link linkend="classmapping">classmapping</link></literal> identifiers.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>expression</literal></para>
+ </entry>
+ <entry>
+ <para>There must be one constraint <literal>expression</literal> or one or more <literal>expr</literal>'s. The expression consists of an operator and two operands as follows:</para>
+ <simpara><literal> (op u1 u2)</literal></simpara>
+ <simpara><literal> (role_op r1 r2)</literal></simpara>
+ <simpara><literal> (op t1 t2)</literal></simpara>
+ <simpara><literal> (op u1 user_id)</literal></simpara>
+ <simpara><literal> (op u2 user_id)</literal></simpara>
+ <simpara><literal> (op r1 role_id)</literal></simpara>
+ <simpara><literal> (op r2 role_id)</literal></simpara>
+ <simpara><literal> (op t1 type_id)</literal></simpara>
+ <simpara><literal> (op t2 type_id)</literal></simpara>
+ <simpara>where:</simpara>
+ <simpara><literal> u1, r1, t1 = Source context: <link linkend="user">user</link>, <link linkend="role">role</link> or <link linkend="type">type</link></literal></simpara>
+ <simpara><literal> u2, r2, t2 = Target context: <link linkend="user">user</link>, <link linkend="role">role</link> or <link linkend="type">type</link></literal></simpara>
+ <simpara>and:</simpara>
+ <simpara><literal> op : eq neq</literal></simpara>
+ <simpara><literal> role_op : eq neq dom domby incomp</literal></simpara>
+ <simpara><literal> user_id : A single <link linkend="user">user</link> identifier.</literal></simpara>
+ <simpara><literal> role_id : A single <link linkend="role">role</link> or <link linkend="roleattribute">roleattribute</link> identifier.</literal></simpara>
+ <simpara><literal> type_id : A single <link linkend="type">type</link>, <link linkend="typealias">typealias</link> or <link linkend="typeattribute">typeattribute</link> identifier.</literal></simpara>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>expr</literal></para>
+ </entry>
+ <entry>
+ <para>Zero or more <literal>expr</literal>'s, the valid operators and syntax are:</para>
+ <simpara><literal> (and expression expression)</literal></simpara>
+ <simpara><literal> (or expression expression)</literal></simpara>
+ <simpara><literal> (not expression)</literal></simpara>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+
+ <para><emphasis role="bold">Examples:</emphasis></para>
+ <para>Two constrain statements are shown with their equivalent kernel policy language statements:</para>
+ <programlisting><![CDATA[
+;; constrain { file } { write }
+;; (( t1 == unconfined.process ) and ( t2 == unconfined.object ) or ( r1 eq r2 ));
+(constrain (file (write))
+ (or
+ (and
+ (eq t1 unconfined.process)
+ (eq t2 unconfined.object)
+ )
+ (eq r1 r2)
+ )
+)
+
+;; constrain { file } { read }
+;; (not( t1 == unconfined.process ) and ( t2 == unconfined.object ) or ( r1 eq r2 ));
+(constrain (file (read))
+ (not
+ (or
+ (and
+ (eq t1 unconfined.process)
+ (eq t2 unconfined.object)
+ )
+ (eq r1 r2)
+ )
+ )
+)]]>
+ </programlisting>
+ </sect2>
+
+ <sect2 id="validatetrans">
+ <title>validatetrans</title>
+ <para>The <literal>validatetrans</literal> statement is only used for <literal>file</literal> related object classes where it is used to control the ability to change the objects security context based on old, new and the current process security context.</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(validatetrans class_id expression | expr ...)]]>
+ </programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>validatetrans</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>validatetrans</literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>class_id</literal></para>
+ </entry>
+ <entry>
+ <para>A single previously declared <literal><link linkend="class">class</link></literal> or <literal><link linkend="classmap">classmap</link></literal> identifier.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>expression</literal></para>
+ </entry>
+ <entry>
+ <para>There must be one constraint <literal>expression</literal> or one or more <literal>expr</literal>'s. The expression consists of an operator and two operands as follows:</para>
+ <simpara><literal> (op u1 u2)</literal></simpara>
+ <simpara><literal> (role_op r1 r2)</literal></simpara>
+ <simpara><literal> (op t1 t2)</literal></simpara>
+ <simpara><literal> (op u1 user_id)</literal></simpara>
+ <simpara><literal> (op u2 user_id)</literal></simpara>
+ <simpara><literal> (op u3 user_id)</literal></simpara>
+ <simpara><literal> (op r1 role_id)</literal></simpara>
+ <simpara><literal> (op r2 role_id)</literal></simpara>
+ <simpara><literal> (op r3 role_id)</literal></simpara>
+ <simpara><literal> (op t1 type_id)</literal></simpara>
+ <simpara><literal> (op t2 type_id)</literal></simpara>
+ <simpara><literal> (op t3 type_id)</literal></simpara>
+ <simpara>where:</simpara>
+ <simpara><literal> u1, r1, t1 = Old context: <link linkend="user">user</link>, <link linkend="role">role</link> or <link linkend="type">type</link></literal></simpara>
+ <simpara><literal> u2, r2, t2 = New context: <link linkend="user">user</link>, <link linkend="role">role</link> or <link linkend="type">type</link></literal></simpara>
+ <simpara><literal> u3, r3, t3 = Process context: <link linkend="user">user</link>, <link linkend="role">role</link> or <link linkend="type">type</link></literal></simpara>
+ <simpara>and:</simpara>
+ <simpara><literal> op : eq neq</literal></simpara>
+ <simpara><literal> role_op : eq neq dom domby incomp</literal></simpara>
+ <simpara><literal> user_id : A single <link linkend="user">user</link> identifier.</literal></simpara>
+ <simpara><literal> role_id : A single <link linkend="role">role</link> or <link linkend="roleattribute">roleattribute</link> identifier.</literal></simpara>
+ <simpara><literal> type_id : A single <link linkend="type">type</link>, <link linkend="typealias">typealias</link> or <link linkend="typeattribute">typeattribute</link> identifier.</literal></simpara>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>expr</literal></para>
+ </entry>
+ <entry>
+ <para>Zero or more <literal>expr</literal>'s, the valid operators and syntax are:</para>
+ <simpara><literal> (and expression expression)</literal></simpara>
+ <simpara><literal> (or expression expression)</literal></simpara>
+ <simpara><literal> (not expression)</literal></simpara>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+
+ <para><emphasis role="bold">Example:</emphasis></para>
+ <para>A validate transition statement with the equivalent kernel policy language statement:</para>
+ <programlisting><![CDATA[
+; validatetrans { file } ( t1 == unconfined.process );
+
+(validatetrans file (eq t1 unconfined.process))]]>
+ </programlisting>
+ </sect2>
+
+ <sect2 id="mlsconstrain">
+ <title>mlsconstrain</title>
+ <para>Enable MLS constraints to be placed on the specified permissions of the object class based on the source and target security context components.</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(mlsconstrain classpermissionset_id ... expression | expr ...)]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2.25 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>mlsconstrain</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>mlsconstrain</literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>classpermissionset_id</literal></para>
+ </entry>
+ <entry>
+ <para>A single named or anonymous <literal><link linkend="classpermissionset">classpermissionset</link></literal> or a single set of <literal><link linkend="classmap">classmap</link></literal>/<literal><link linkend="classmapping">classmapping</link></literal> identifiers.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>expression</literal></para>
+ </entry>
+ <entry>
+ <para>There must be one constraint <literal>expression</literal> or one or more <literal>expr</literal>'s. The expression consists of an operator and two operands as follows:</para>
+ <simpara><literal> (op u1 u2)</literal></simpara>
+ <simpara><literal> (mls_role_op r1 r2)</literal></simpara>
+ <simpara><literal> (op t1 t2)</literal></simpara>
+ <simpara><literal> (mls_role_op l1 l2)</literal></simpara>
+ <simpara><literal> (mls_role_op l1 h2)</literal></simpara>
+ <simpara><literal> (mls_role_op h1 l2)</literal></simpara>
+ <simpara><literal> (mls_role_op h1 h2)</literal></simpara>
+ <simpara><literal> (mls_role_op l1 h1)</literal></simpara>
+ <simpara><literal> (mls_role_op l2 h2)</literal></simpara>
+ <simpara><literal> (op u1 user_id)</literal></simpara>
+ <simpara><literal> (op u2 user_id)</literal></simpara>
+ <simpara><literal> (op r1 role_id)</literal></simpara>
+ <simpara><literal> (op r2 role_id)</literal></simpara>
+ <simpara><literal> (op t1 type_id)</literal></simpara>
+ <simpara><literal> (op t2 type_id)</literal></simpara>
+ <simpara>where:</simpara>
+ <simpara><literal> u1, r1, t1, l1, h1 = Source context: <link linkend="user">user</link>, <link linkend="role">role</link>, <link linkend="type">type</link>, <link linkend="level">low level</link> or <link linkend="level">high level</link></literal></simpara>
+ <simpara><literal> u2, r2, t2, l2, h2 = Target context: <link linkend="user">user</link>, <link linkend="role">role</link>, <link linkend="type">type</link>, <link linkend="level">low level</link> or <link linkend="level">high level</link></literal></simpara>
+ <simpara>and:</simpara>
+ <simpara><literal> op : eq neq</literal></simpara>
+ <simpara><literal> mls_role_op : eq neq dom domby incomp</literal></simpara>
+ <simpara><literal> user_id : A single <link linkend="user">user</link> identifier.</literal></simpara>
+ <simpara><literal> role_id : A single <link linkend="role">role</link> or <link linkend="roleattribute">roleattribute</link> identifier.</literal></simpara>
+ <simpara><literal> type_id : A single <link linkend="type">type</link>, <link linkend="typealias">typealias</link> or <link linkend="typeattribute">typeattribute</link> identifier.</literal></simpara>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>expr</literal></para>
+ </entry>
+ <entry>
+ <para>Zero or more <literal>expr</literal>'s, the valid operators and syntax are:</para>
+ <simpara><literal> (and expression expression)</literal></simpara>
+ <simpara><literal> (or expression expression)</literal></simpara>
+ <simpara><literal> (not expression)</literal></simpara>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+
+ <para><emphasis role="bold">Example:</emphasis></para>
+ <para>An MLS constrain statement with the equivalent kernel policy language statement:</para>
+ <programlisting><![CDATA[
+;; mlsconstrain { file } { open }
+;; (( l1 eq l2 ) and ( u1 == u2 ) or ( r1 != r2 ));
+
+(mlsconstrain (file (open))
+ (or
+ (and
+ (eq l1 l2)
+ (eq u1 u2)
+ )
+ (neq r1 r2)
+ )
+)]]>
+ </programlisting>
+ </sect2>
+
+ <sect2 id="mlsvalidatetrans">
+ <title>mlsvalidatetrans</title>
+ <para>The <literal>mlsvalidatetrans</literal> statement is only used for <literal>file</literal> related object classes where it is used to control the ability to change the objects security context based on old, new and the current process security context.</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(mlsvalidatetrans class_id expression | expr ...)]]>
+ </programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>mlsvalidatetrans</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>mlsvalidatetrans</literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>class_id</literal></para>
+ </entry>
+ <entry>
+ <para>A single previously declared <literal><link linkend="class">class</link></literal> or <literal><link linkend="classmap">classmap</link></literal> identifier.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>expression</literal></para>
+ </entry>
+ <entry>
+ <para>There must be one constraint <literal>expression</literal> or one or more <literal>expr</literal>'s. The expression consists of an operator and two operands as follows:</para>
+ <simpara><literal> (op u1 u2)</literal></simpara>
+ <simpara><literal> (mls_role_op r1 r2)</literal></simpara>
+ <simpara><literal> (op t1 t2)</literal></simpara>
+ <simpara><literal> (mls_role_op l1 l2)</literal></simpara>
+ <simpara><literal> (mls_role_op l1 h2)</literal></simpara>
+ <simpara><literal> (mls_role_op h1 l2)</literal></simpara>
+ <simpara><literal> (mls_role_op h1 h2)</literal></simpara>
+ <simpara><literal> (mls_role_op l1 h1)</literal></simpara>
+ <simpara><literal> (mls_role_op l2 h2)</literal></simpara>
+ <simpara><literal> (op u1 user_id)</literal></simpara>
+ <simpara><literal> (op u2 user_id)</literal></simpara>
+ <simpara><literal> (op u3 user_id)</literal></simpara>
+ <simpara><literal> (op r1 role_id)</literal></simpara>
+ <simpara><literal> (op r2 role_id)</literal></simpara>
+ <simpara><literal> (op r3 role_id)</literal></simpara>
+ <simpara><literal> (op t1 type_id)</literal></simpara>
+ <simpara><literal> (op t2 type_id)</literal></simpara>
+ <simpara><literal> (op t3 type_id)</literal></simpara>
+ <simpara>where:</simpara>
+ <simpara><literal> u1, r1, t1, l1, h1 = Source context: <link linkend="user">user</link>, <link linkend="role">role</link>, <link linkend="type">type</link>, <link linkend="level">low level</link> or <link linkend="level">high level</link></literal></simpara>
+ <simpara><literal> u2, r2, t2, l2, h2 = Target context: <link linkend="user">user</link>, <link linkend="role">role</link>, <link linkend="type">type</link>, <link linkend="level">low level</link> or <link linkend="level">high level</link></literal></simpara>
+ <simpara><literal> u3, r3, t3 = Process context: <link linkend="user">user</link>, <link linkend="role">role</link> or <link linkend="type">type</link></literal></simpara>
+ <simpara>and:</simpara>
+ <simpara><literal> op : eq neq</literal></simpara>
+ <simpara><literal> mls_role_op : eq neq dom domby incomp</literal></simpara>
+ <simpara><literal> user_id : A single <link linkend="user">user</link> identifier.</literal></simpara>
+ <simpara><literal> role_id : A single <link linkend="role">role</link> or <link linkend="roleattribute">roleattribute</link> identifier.</literal></simpara>
+ <simpara><literal> type_id : A single <link linkend="type">type</link>, <link linkend="typealias">typealias</link> or <link linkend="typeattribute">typeattribute</link> identifier.</literal></simpara>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>expr</literal></para>
+ </entry>
+ <entry>
+ <para>Zero or more <literal>expr</literal>'s, the valid operators and syntax are:</para>
+ <simpara><literal> (and expression expression)</literal></simpara>
+ <simpara><literal> (or expression expression)</literal></simpara>
+ <simpara><literal> (not expression)</literal></simpara>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+
+ <para><emphasis role="bold">Example:</emphasis></para>
+ <para>An MLS validate transition statement with the equivalent kernel policy language statement:</para>
+ <programlisting><![CDATA[
+;; mlsvalidatetrans { file } ( l1 domby h2 );
+
+(mlsvalidatetrans file (domby l1 h2))]]>
+ </programlisting>
+ </sect2>
+
+ </sect1>
diff --git a/cil/docs/cil_container_statements.xml b/cil/docs/cil_container_statements.xml
new file mode 100644
index 0000000..6d7d8bf
--- /dev/null
+++ b/cil/docs/cil_container_statements.xml
@@ -0,0 +1,398 @@
+
+<!-- Common Interface Language (CIL) Reference Guide -->
+ <!-- container_statements.xml -->
+
+ <sect1>
+ <title>Container Statements</title>
+ <sect2 id="block">
+ <title>block</title>
+ <para>Start a new namespace where any CIL statement is valid.</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[
+(block block_id
+ cil_statement
+ ...
+)]]>
+ </programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>block</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal><link linkend="block">block</link></literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>block_id</literal></para>
+ </entry>
+ <entry>
+ <para>The namespace identifier.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>cil_statement</literal></para>
+ </entry>
+ <entry>
+ <para>Zero or more valid CIL statements.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+ <para><emphasis role="bold">Example:</emphasis></para>
+ <para>See the <literal><link linkend="blockinherit">blockinherit</link></literal> statement for an example.</para>
+ </sect2>
+
+ <sect2 id="blockabstract">
+ <title>blockabstract</title>
+ <para>Declares the namespace as a 'template' and does not generate code until instantiated by another namespace that has a <literal><link linkend="blockinherit">blockinherit</link></literal> statement.</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[
+(block block_id
+ (blockabstract template_id)
+ cil_statement
+ ...
+)]]>
+ </programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>block</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal><link linkend="block">block</link></literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>block_id</literal></para>
+ </entry>
+ <entry>
+ <para>The namespace identifier.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>blockabstract</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal><link linkend="blockabstract">blockabstract</link></literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>template_id</literal></para>
+ </entry>
+ <entry>
+ <para>The abstract namespace identifier. This must match the <literal><link linkend="block">block_id</link></literal> entry.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>cil_statement</literal></para>
+ </entry>
+ <entry>
+ <para>Zero or more valid CIL statements forming the abstract block.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+ <para><emphasis role="bold">Example:</emphasis></para>
+ <para>See the <literal><link linkend="blockinherit">blockinherit</link></literal> statement for an example.</para>
+ </sect2>
+
+ <sect2 id="blockinherit">
+ <title>blockinherit</title>
+ <para>Used to add common policy rules to the current namespace via a template that has been defined with the <literal><link linkend="blockabstract">blockabstract</link></literal> statement.</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[
+(block block_id
+ (blockinherit template_id)
+ cil_statement
+ ...
+)]]>
+ </programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>block</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal><link linkend="block">block</link></literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>block_id</literal></para>
+ </entry>
+ <entry>
+ <para>The namespace identifier.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>blockinherit</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal><link linkend="blockinherit">blockinherit</link></literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>template_id</literal></para>
+ </entry>
+ <entry>
+ <para>The inherited namespace identifier.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>cil_statement</literal></para>
+ </entry>
+ <entry>
+ <para>Zero or more valid CIL statements.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+ <para><emphasis role="bold">Example:</emphasis></para>
+ <para>This example contains a template <literal>client_server</literal> that is instantiated in two blocks (<literal>netserver_app</literal> and <literal>netclient_app</literal>):</para>
+ <programlisting><![CDATA[
+; This is the template block:
+(block client_server
+ (blockabstract client_server)
+
+ ; Log file labeling
+ (type log_file)
+ (typeattributeset file_type (log_file))
+ (typeattributeset data_file_type (log_file))
+ (allow process log_file (dir (write search create setattr add_name)))
+ (allow process log_file (file (create open append getattr setattr)))
+ (roletype object_r log_file)
+ (context log_file_context (u object_r log_file low_low))
+
+ ; Process labeling
+ (type process)
+ (typeattributeset domain (process))
+ (call app_domain (process))
+ (call net_domain (process))
+)
+
+; This is a policy block that will inherit the abstract block above:
+(block netclient_app
+ ; Add common policy rules to namespace:
+ (blockinherit client_server)
+ ; Label the log files
+ (filecon "/data/data/com.se4android.netclient/.*" file log_file_context)
+)
+
+; This is another policy block that will inherit the abstract block above:
+(block netserver_app
+ ; Add common policy rules to namespace:
+ (blockinherit client_server)
+
+ ; Label the log files
+ (filecon "/data/data/com.se4android.netserver/.*" file log_file_context)
+)]]>
+ </programlisting>
+ </sect2>
+
+ <sect2 id="optional">
+ <title>optional</title>
+ <para>Declare an <literal><link linkend="optional">optional</link></literal> namespace. All CIL statements in the optional block must be satisfied before instantiation in the binary policy. <literal><link linkend="tunableif">tunableif</link></literal> and <literal><link linkend="macro">macro</link></literal> statements are not allowed in optional containers. The same restrictions apply to CIL policy statements within <literal><link linkend="optional">optional</link></literal>'s that apply to kernel policy statements, i.e. only the policy statements shown in the following table are valid:</para>
+
+ <informaltable frame="all">
+ <tgroup cols="4">
+ <tbody>
+ <row>
+ <entry>
+ <para><literal><link linkend="allow">allow</link></literal></para>
+ </entry>
+ <entry>
+ <para><literal><link linkend="auditallow">auditallow</link></literal></para>
+ </entry>
+ <entry>
+ <para><literal><link linkend="booleanif">booleanif</link></literal></para>
+ </entry>
+ <entry>
+ <para><literal><link linkend="dontaudit">dontaudit</link></literal></para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal><link linkend="typepermissive">typepermissive</link></literal></para>
+ </entry>
+ <entry>
+ <para><literal><link linkend="rangetransition">rangetransition</link></literal></para>
+ </entry>
+ <entry>
+ <para><literal><link linkend="role">role</link></literal></para>
+ </entry>
+ <entry>
+ <para><literal><link linkend="roleallow">roleallow</link></literal></para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal><link linkend="roleattribute">roleattribute</link></literal></para>
+ </entry>
+ <entry>
+ <para><literal><link linkend="roletransition">roletransition</link></literal></para>
+ </entry>
+ <entry>
+ <para><literal><link linkend="type">type</link></literal></para>
+ </entry>
+ <entry>
+ <para><literal><link linkend="typealias">typealias</link></literal></para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal><link linkend="typeattribute">typeattribute</link></literal></para>
+ </entry>
+ <entry>
+ <para><literal><link linkend="typechange">typechange</link></literal></para>
+ </entry>
+ <entry>
+ <para><literal><link linkend="typemember">typemember</link></literal></para>
+ </entry>
+ <entry>
+ <para><literal><link linkend="typetransition">typetransition</link></literal></para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[
+(optional optional_id
+ cil_statement
+ ...
+)]]>
+ </programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>optional</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal><link linkend="optional">optional</link></literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>optional_id</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal><link linkend="optional">optional</link></literal> namespace identifier.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>cil_statement</literal></para>
+ </entry>
+ <entry>
+ <para>Zero or more valid CIL statements.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+
+ <para><emphasis role="bold">Example:</emphasis></para>
+ <para>This example will instantiate the optional block <literal>ext_gateway.move_file</literal> into policy providing all optional CIL statements can be resolved:</para>
+ <programlisting><![CDATA[
+(block ext_gateway
+ ......
+ (optional move_file
+ (typetransition process msg_filter.move_file.in_queue file msg_filter.move_file.in_file)
+ (allow process msg_filter.move_file.in_queue (dir (read getattr write search add_name)))
+ (allow process msg_filter.move_file.in_file (file (write create getattr)))
+ (allow msg_filter.move_file.in_file unconfined.object (filesystem (associate)))
+ (typetransition msg_filter.int_gateway.process msg_filter.move_file.out_queue file
+ msg_filter.move_file.out_file)
+ (allow msg_filter.int_gateway.process msg_filter.move_file.out_queue (dir (read write search)))
+ (allow msg_filter.int_gateway.process msg_filter.move_file.out_file (file (read getattr unlink)))
+ ) ; End optional block
+
+ .....
+) ; End block]]>
+ </programlisting>
+ </sect2>
+
+ <sect2 id="in">
+ <title>in</title>
+ <para>Allows the insertion of CIL statements into a named container (<literal><link linkend="block">block</link></literal>, <literal><link linkend="optional">optional</link></literal> or <literal><link linkend="macro">macro</link></literal>). This statement is not allowed in <literal><link linkend="booleanif">booleanif</link></literal> or <literal><link linkend="tunableif">tunableif</link></literal> statements.</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[
+(in container_id
+ cil_statement
+ ...
+)]]>
+ </programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>in</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>in</literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>container_id</literal></para>
+ </entry>
+ <entry>
+ <para>A valid <literal><link linkend="block">block</link></literal>, <literal><link linkend="optional">optional</link></literal> or <literal><link linkend="macro">macro</link></literal> namespace identifier.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>cil_statement</literal></para>
+ </entry>
+ <entry>
+ <para>Zero or more valid CIL statements.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+
+ <para><emphasis role="bold">Example:</emphasis></para>
+ <para>This will add rules to the container named <literal>system_server</literal>:</para>
+ <programlisting><![CDATA[
+(in system_server
+ (dontaudit process secmark_demo.dns_packet (packet (send recv)))
+ (allow process secmark_demo.dns_packet (packet (send recv)))
+)]]>
+ </programlisting>
+ </sect2>
+ </sect1>
+
diff --git a/cil/docs/cil_context_statement.xml b/cil/docs/cil_context_statement.xml
new file mode 100644
index 0000000..648278a
--- /dev/null
+++ b/cil/docs/cil_context_statement.xml
@@ -0,0 +1,100 @@
+<!-- Common Interface Language (CIL) Reference Guide -->
+ <!-- context_statement.xml -->
+
+ <sect1>
+ <title>Context Statement</title>
+ <para>Contexts are formed using previously declared parameters and may be named or anonymous where:</para>
+ <itemizedlist mark="none">
+ <listitem><para>Named - The context is declared with a context identifer that is used as a reference.</para></listitem>
+ <listitem><para>Anonymous - They are defined within the CIL labeling statement using user, role etc. identifiers.</para></listitem>
+ </itemizedlist>
+ <para>Each type is shown in the examples.</para>
+
+ <sect2 id="context">
+ <title>context</title>
+ <para>Declare an SELinux security context identifier for labeling. The range (or current and clearance levels) MUST be defined whether the policy is MLS/MCS enabled or not.</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(context context_id (user_id role_id type_id levelrange_id)))]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal><link linkend="context">context</link></literal></para>
+ </entry>
+ <entry>
+ <para>The <literal><link linkend="context">context</link></literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>context_id</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal><link linkend="context">context</link></literal> identifier.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>user_id</literal></para>
+ </entry>
+ <entry>
+ <para>A single previously declared <literal><link linkend="user">user</link></literal> identifier.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>role_id</literal></para>
+ </entry>
+ <entry>
+ <para>A single previously declared <literal><link linkend="role">role</link></literal> identifier.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>type_id</literal></para>
+ </entry>
+ <entry>
+ <para>A single previously declared <literal><link linkend="type">type</link></literal> or <literal><link linkend="typealias">typealias</link></literal> identifier.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>levelrange_id</literal></para>
+ </entry>
+ <entry>
+ <para>A single previously declared <literal><link linkend="levelrange">levelrange</link></literal> identifier. This entry may also be defined by anonymous or named <literal><link linkend="level">level</link></literal>, <literal><link linkend="sensitivity">sensitivity</link></literal>, <literal><link linkend="sensitivityalias">sensitivityalias</link></literal>, <literal><link linkend="category">category</link></literal>, <literal><link linkend="categoryalias">categoryalias</link></literal> or <literal><link linkend="categoryset">categoryset</link></literal> as discussed in the <link linkend="mls_labeling_statements">Multi-Level Security Labeling Statements</link> section and shown in the examples.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+
+ <para><emphasis role="bold">Examples:</emphasis></para>
+ <para>This example uses a named context definition:</para>
+ <programlisting><![CDATA[
+(context runas_exec_context (u object_r exec low_low))
+
+(filecon "/system/bin/run-as" file runas_exec_context)]]>
+ </programlisting>
+ <simpara>to resolve/build a <literal>file_contexts</literal> entry of (assuming MLS enabled policy):</simpara>
+ <programlisting><![CDATA[/system/bin/run-as -- u:object_r:runas.exec:s0-s0]]></programlisting>
+
+ <para>This example uses an anonymous context where the previously declared <literal><link linkend="user">user</link> <link linkend="role">role</link> <link linkend="type">type</link> <link linkend="levelrange">levelrange</link></literal> identifiers are used to specifiy two <literal><link linkend="portcon">portcon</link></literal> statements:</para>
+ <programlisting><![CDATA[
+(portcon udp 1024 (test.user object_r test.process ((s0) (s1))))
+(portcon tcp 1024 (test.user object_r test.process (system_low system_high)))]]>
+ </programlisting>
+
+ <para>This example uses an anonymous context for the first and named context for the second in a <literal><link linkend="netifcon">netifcon</link></literal> statement:</para>
+ <programlisting><![CDATA[
+(context netif_context (test.user object_r test.process ((s0 (c0)) (s1 (c0)))))
+
+(netifcon eth04 (test.user object_r test.process ((s0 (c0)) (s1 (c0)))) netif_context)]]>
+ </programlisting>
+
+ </sect2>
+
+ </sect1>
diff --git a/cil/docs/cil_default_object_statements.xml b/cil/docs/cil_default_object_statements.xml
new file mode 100644
index 0000000..c654435
--- /dev/null
+++ b/cil/docs/cil_default_object_statements.xml
@@ -0,0 +1,215 @@
+<!-- Common Interface Language (CIL) Reference Guide -->
+ <!-- default_object_statements.xml -->
+
+ <sect1>
+ <title>Default Object Statements</title>
+ <para>These rules allow a default user, role, type and/or range to be used when computing a context for a new object. These require policy version 27 or 28 with kernels 3.5 or greater.</para>
+ <sect2 id="defaultuser">
+ <title>defaultuser</title>
+ <para>Allows the default user to be taken from the source or target context when computing a new context for the object <literal><link linkend="class">class</link></literal> identifier. Requires policy version 27.</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(defaultuser class_id default)]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>defaultuser</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>defaultuser</literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>class_id</literal></para>
+ </entry>
+ <entry>
+ <para>A single previously declared <literal><link linkend="class">class</link></literal> or <literal><link linkend="classmap">classmap</link></literal> identifier, or a list of previously declared <literal><link linkend="class">class</link></literal> or <literal><link linkend="classmap">classmap</link></literal> identifiers enclosed within parentheses.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>default</literal></para>
+ </entry>
+ <entry>
+ <para>A keyword of either <literal>source</literal> or <literal>target</literal>.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+
+ <para><emphasis role="bold">Example:</emphasis></para>
+ <para>When creating new <literal>binder</literal>, <literal>property_service</literal>, <literal>zygote</literal> or <literal>memprotect</literal> objects the <literal><link linkend="user">user</link></literal> component of the new security context will be taken from the <literal>source</literal> context:</para>
+ <programlisting><![CDATA[
+(class binder (impersonate call set_context_mgr transfer receive))
+(class property_service (set))
+(class zygote (specifyids specifyrlimits specifycapabilities specifyinvokewith specifyseinfo))
+(class memprotect (mmap_zero))
+
+(classmap android_classes (android))
+(classmapping android_classes android (binder (all)))
+(classmapping android_classes android (property_service (set)))
+(classmapping android_classes android (zygote (not (specifycapabilities))))
+
+(defaultuser (android_classes memprotect) source)
+
+; Will produce the following in the binary policy file:
+;; default_user binder source;
+;; default_user zygote source;
+;; default_user property_service source;
+;; default_user memprotect source;]]>
+ </programlisting>
+ </sect2>
+
+ <sect2 id="defaultrole">
+ <title>defaultrole</title>
+ <para>Allows the default role to be taken from the source or target context when computing a new context for the object <literal><link linkend="class">class</link></literal> identifier. Requires policy version 27.</para>
+ <programlisting><![CDATA[(defaultrole class_id default)]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>defaultrole</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>defaultrole</literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>class_id</literal></para>
+ </entry>
+ <entry>
+ <para>A single previously declared <literal><link linkend="class">class</link></literal> or <literal><link linkend="classmap">classmap</link></literal> identifier, or a list of previously declared <literal><link linkend="class">class</link></literal> or <literal><link linkend="classmap">classmap</link></literal> identifiers enclosed within parentheses.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>default</literal></para>
+ </entry>
+ <entry>
+ <para>A keyword of either <literal>source</literal> or <literal>target</literal>.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+
+ <para><emphasis role="bold">Example:</emphasis></para>
+ <para>When creating new <literal>binder</literal>, <literal>property_service</literal> or <literal>zygote</literal> objects the <literal><link linkend="role">role</link></literal> component of the new security context will be taken from the <literal>target</literal> context:</para>
+ <programlisting><![CDATA[
+(class binder (impersonate call set_context_mgr transfer receive))
+(class property_service (set))
+(class zygote (specifyids specifyrlimits specifycapabilities specifyinvokewith specifyseinfo))
+
+(defaultrole (binder property_service zygote) target)
+
+; Will produce the following in the binary policy file:
+;; default_role binder target;
+;; default_role zygote target;
+;; default_role property_service target;]]>
+ </programlisting>
+ </sect2>
+
+ <sect2 id="defaulttype">
+ <title>defaulttype</title>
+ <para>Allows the default type to be taken from the source or target context when computing a new context for the object <literal><link linkend="class">class</link></literal> identifier. Requires policy version 28.</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(defaulttype class_id default)]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>defaulttype</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>defaulttype</literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>class_id</literal></para>
+ </entry>
+ <entry>
+ <para>A single previously declared <literal><link linkend="class">class</link></literal> or <literal><link linkend="classmap">classmap</link></literal> identifier, or a list of previously declared <literal><link linkend="class">class</link></literal> or <literal><link linkend="classmap">classmap</link></literal> identifiers enclosed within parentheses.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>default</literal></para>
+ </entry>
+ <entry>
+ <para>A keyword of either <literal>source</literal> or <literal>target</literal>.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+
+ <para><emphasis role="bold">Example:</emphasis></para>
+ <para>When creating a new <literal>socket</literal> object, the <literal><link linkend="type">type</link></literal> component of the new security context will be taken from the <literal>source</literal> context:</para>
+ <programlisting><![CDATA[(defaulttype socket source)]]></programlisting>
+ </sect2>
+
+ <sect2 id="defaultrange">
+ <title>defaultrange</title>
+ <para>Allows the default level or range to be taken from the source or target context when computing a new context for the object <literal><link linkend="class">class</link></literal> identifier. Requires policy version 27.</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(defaultrange class_id default range)]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>defaultrange</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>defaultrange</literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>class_id</literal></para>
+ </entry>
+ <entry>
+ <para>A single previously declared <literal><link linkend="class">class</link></literal> or <literal><link linkend="classmap">classmap</link></literal> identifier, or a list of previously declared <literal><link linkend="class">class</link></literal> or <literal><link linkend="classmap">classmap</link></literal> identifiers enclosed within parentheses.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>default</literal></para>
+ </entry>
+ <entry>
+ <para>A keyword of either <literal>source</literal> or <literal>target</literal>.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>range</literal></para>
+ </entry>
+ <entry>
+ <para>A keyword of either <literal>low</literal>, <literal>high</literal> or <literal>low-high</literal>.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+
+ <para><emphasis role="bold">Example:</emphasis></para>
+ <para>When creating a new <literal>file</literal> object, the appropriate <literal><link linkend="levelrange">range</link></literal> component of the new security context will be taken from the <literal>target</literal> context:</para>
+ <programlisting><![CDATA[(defaultrange file target low_high)]]></programlisting>
+ </sect2>
+
+ </sect1>
diff --git a/cil/docs/cil_design.dia b/cil/docs/cil_design.dia
new file mode 100644
index 0000000..b36c448
--- /dev/null
+++ b/cil/docs/cil_design.dia
Binary files differ
diff --git a/cil/docs/cil_design.jpeg b/cil/docs/cil_design.jpeg
new file mode 100644
index 0000000..4b3f529
--- /dev/null
+++ b/cil/docs/cil_design.jpeg
Binary files differ
diff --git a/cil/docs/cil_file_labeling_statements.xml b/cil/docs/cil_file_labeling_statements.xml
new file mode 100644
index 0000000..8cfdb24
--- /dev/null
+++ b/cil/docs/cil_file_labeling_statements.xml
@@ -0,0 +1,302 @@
+<!-- Common Interface Language (CIL) Reference Guide -->
+ <!-- file_labeling_statements.xml -->
+
+ <sect1>
+ <title>File Labeling Statements</title>
+ <sect2 id="filecon">
+ <title>filecon</title>
+ <para>Define entries for labeling files. The compiler will produce these entries in a file called <emphasis role="bold"><literal>file_contexts</literal></emphasis><literal>(5)</literal> by default in the <literal>cwd</literal>. The compiler option <literal>[-f|--filecontext &lt;filename>]</literal> may be used to specify a different path or file name.</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(filecon "path" file_type context_id)]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>filecon</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>filecon</literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>path</literal></para>
+ </entry>
+ <entry>
+ <para>A string representing the file path that may be in the form of a regular expression. The string must be enclosed within double quotes (e.g. <literal>"/this/is/a/path(/.*)?"</literal>)</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>file_type</literal></para>
+ </entry>
+ <entry>
+ <para>A single keyword representing a file type in the <literal>file_contexts</literal> file as follows:</para>
+ <para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="1 in"/>
+ <colspec colwidth="1.25 in"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><emphasis role="bold">keyword</emphasis></para>
+ </entry>
+ <entry>
+ <para><emphasis role="bold">file_contexts entry</emphasis></para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>file</literal></para>
+ </entry>
+ <entry>
+ <para><literal>--</literal></para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>dir</literal></para>
+ </entry>
+ <entry>
+ <para><literal>-d</literal></para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>char</literal></para>
+ </entry>
+ <entry>
+ <para><literal>-c</literal></para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>block</literal></para>
+ </entry>
+ <entry>
+ <para><literal>-b</literal></para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>socket</literal></para>
+ </entry>
+ <entry>
+ <para><literal>-s</literal></para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>pipe</literal></para>
+ </entry>
+ <entry>
+ <para><literal>-p</literal></para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>symlink</literal></para>
+ </entry>
+ <entry>
+ <para><literal>-l</literal></para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>any</literal></para>
+ </entry>
+ <entry>
+ <para>no entry</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>context_id</literal></para>
+ </entry>
+ <entry>
+ <para>The security context to be allocated to the file, which may be:</para>
+ <itemizedlist>
+ <listitem><para>A previously declared <literal><link linkend="context">context</link></literal> identifier or an anonymous security context (<literal><link linkend="user">user</link> <link linkend="role">role</link> <link linkend="type">type</link> <link linkend="levelrange">levelrange</link></literal>), the range MUST be defined whether the policy is MLS/MCS enabled or not.</para></listitem>
+ <listitem><para>An empty context list represented by <literal>()</literal> can be used to indicate that matching files should not be re-labeled. This will be interpreted as <literal>&lt;&lt;none>></literal> within the <emphasis role="bold"><literal>file_contexts</literal></emphasis><literal>(5)</literal> file.</para></listitem>
+ </itemizedlist>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+
+ <para><emphasis role="bold">Examples:</emphasis></para>
+ <para>These examples use one named, one anonymous and one empty context definition:</para>
+ <programlisting><![CDATA[
+(context runas_exec_context (u object_r exec low_low))
+
+(filecon "/system/bin/run-as" file runas_exec_context)
+(filecon "/dev/socket/wpa_wlan[0-9]" any u:object_r:wpa.socket:s0-s0)
+(filecon "/data/local/mine" dir ())]]>
+ </programlisting>
+ <simpara>to resolve/build <literal>file_contexts</literal> entries of (assuming MLS enabled policy):</simpara>
+ <programlisting><![CDATA[
+/system/bin/run-as -- u:object_r:runas.exec:s0
+/dev/socket/wpa_wlan[0-9] u:object_r:wpa.socket:s0
+/data/local/mine -d <<none>>]]>
+ </programlisting>
+ </sect2>
+
+ <sect2 id="fsuse">
+ <title>fsuse</title>
+ <para>Label filesystems that support SELinux security contexts.</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(fsuse fstype fsname context_id)]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>fsuse</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>fsuse</literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>fstype</literal></para>
+ </entry>
+ <entry>
+ <para>A single keyword representing the type of filesystem as follows:</para>
+ <itemizedlist mark="none">
+ <listitem><simpara><literal>task</literal> - For pseudo filesystems supporting task related services such as pipes and sockets.</simpara></listitem>
+ <listitem><simpara><literal>trans</literal> - For pseudo filesystems such as pseudo terminals and temporary objects.</simpara></listitem>
+ <listitem><simpara><literal>xattr</literal> - Filesystems supporting the extended attribute <literal>security.selinux</literal>. The labeling is persistent for filesystems that support extended attributes.</simpara></listitem>
+ </itemizedlist>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>fsname</literal></para>
+ </entry>
+ <entry>
+ <para>Name of the supported filesystem (e.g. <literal>ext4</literal> or <literal>pipefs</literal>).</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>context_id</literal></para>
+ </entry>
+ <entry>
+ <para>The security context to be allocated to the network interface.</para>
+ <para>A previously declared <literal><link linkend="context">context</link></literal> identifier or an anonymous security context (<literal><link linkend="user">user</link> <link linkend="role">role</link> <link linkend="type">type</link> <link linkend="levelrange">levelrange</link></literal>), the range MUST be defined whether the policy is MLS/MCS enabled or not.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+
+ <para><emphasis role="bold">Examples:</emphasis></para>
+ <para>The <link linkend="context">context</link> identifiers are declared in the <literal>file</literal> namespace and the <literal>fsuse</literal> statements in the global namespace:</para>
+ <programlisting><![CDATA[
+(block file
+ (type labeledfs)
+ (roletype object_r labeledfs)
+ (context labeledfs_context (u object_r labeledfs low_low))
+
+ (type pipefs)
+ (roletype object_r pipefs)
+ (context pipefs_context (u object_r pipefs low_low))
+ ...
+)
+
+(fsuse xattr ex4 file.labeledfs_context)
+(fsuse xattr btrfs file.labeledfs_context)
+
+(fsuse task pipefs file.pipefs_context)
+(fsuse task sockfs file.sockfs_context)
+
+(fsuse trans devpts file.devpts_context)
+(fsuse trans tmpfs file.tmpfs_context)]]>
+ </programlisting>
+ </sect2>
+
+ <sect2 id="genfscon">
+ <title>genfscon</title>
+ <para>Used to allocate a security context to filesystems that cannot support any of the <literal><link linkend="fsuse">fsuse</link></literal> file labeling options. Generally a filesystem would have a single default security context assigned by <literal>genfscon</literal> from the root <literal>(/)</literal> that would then be inherited by all files and directories on that filesystem. The exception to this is the <literal>/proc</literal> filesystem, where directories can be labeled with a specific security context (as shown in the examples).</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(genfscon fsname path context_id)]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>genfscon</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>genfscon</literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>fsname</literal></para>
+ </entry>
+ <entry>
+ <para>Name of the supported filesystem (e.g. <literal>rootfs</literal> or <literal>proc</literal>).</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>path</literal></para>
+ </entry>
+ <entry>
+ <para>If <literal>fsname</literal> is <literal>proc</literal>, then the partial path (see examples). For all other types this must be ‘<literal>/</literal>’.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>context_id</literal></para>
+ </entry>
+ <entry>
+ <para>A previously declared <literal><link linkend="context">context</link></literal> identifier or an anonymous security context (<literal><link linkend="user">user</link> <link linkend="role">role</link> <link linkend="type">type</link> <link linkend="levelrange">levelrange</link></literal>), the range MUST be defined whether the policy is MLS/MCS enabled or not.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+
+ <para><emphasis role="bold">Examples:</emphasis></para>
+ <para>The <link linkend="context">context</link> identifiers are declared in the <literal>file</literal> namespace and the <literal>genfscon</literal> statements are then inserted using the <literal><link linkend="in">in</link></literal> container statement:</para>
+ <programlisting><![CDATA[
+(file
+ (type rootfs)
+ (roletype object_r rootfs)
+ (context rootfs_context (u object_r rootfs low_low))
+
+ (type proc)
+ (roletype object_r proc)
+ (context rootfs_context (u object_r proc low_low))
+ ...
+)
+
+(in file
+ (genfscon rootfs / rootfs_context)
+ ; proc labeling can be further refined (longest matching prefix).
+ (genfscon proc / proc_context)
+ (genfscon proc /net/xt_qtaguid/ctrl qtaguid_proc_context)
+ (genfscon proc /sysrq-trigger sysrq_proc_context)
+ (genfscon selinuxfs / selinuxfs_context)
+)]]>
+ </programlisting>
+ </sect2>
+
+ </sect1>
diff --git a/cil/docs/cil_mls_labeling_statements.xml b/cil/docs/cil_mls_labeling_statements.xml
new file mode 100644
index 0000000..3738789
--- /dev/null
+++ b/cil/docs/cil_mls_labeling_statements.xml
@@ -0,0 +1,733 @@
+<!-- Common Interface Language (CIL) Reference Guide -->
+ <!-- mls_labeling_statements.xml -->
+
+ <sect1 id="mls_labeling_statements">
+ <title>Multi-Level Security Labeling Statements</title>
+ <para>Because there are many options for MLS labeling, the examples show a limited selection of statements, however there is a simple policy that will build shown in the <literal><link linkend="levelrange">levelrange</link></literal> section.</para>
+ <sect2 id="sensitivity">
+ <title>sensitivity</title>
+ <para>Declare a sensitivity identifier in the current namespace. Multiple <literal>sensitivity</literal> statements in the policy will form an ordered list.</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(sensitivity sensitivity_id)]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>sensitivity</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>sensitivity</literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>sensitivity_id</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal><link linkend="sensitivity">sensitivity</link></literal> identifier.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+
+ <para><emphasis role="bold">Example:</emphasis></para>
+ <para>This example declares three <literal><link linkend="sensitivity">sensitivity</link></literal> identifiers:</para>
+ <programlisting><![CDATA[
+(sensitivity s0)
+(sensitivity s1)
+(sensitivity s2)]]>
+ </programlisting>
+ </sect2>
+
+ <sect2 id="sensitivityalias">
+ <title>sensitivityalias</title>
+ <para>Declares a sensitivity alias identifier in the current namespace. See the <literal><link linkend="sensitivityaliasactual">sensitivityaliasactual</link></literal> statement for an example that associates the <literal><link linkend="sensitivityalias">sensitivityalias</link></literal> identifier.</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(sensitivityalias sensitivityalias_id)]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>sensitivityalias</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>sensitivityalias</literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>sensitivityalias_id</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal><link linkend="sensitivityalias">sensitivityalias</link></literal> identifier.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+ <para><emphasis role="bold">Example:</emphasis></para>
+ <para>See the <literal><link linkend="sensitivityaliasactual">sensitivityaliasactual</link></literal> statement.</para>
+ </sect2>
+
+ <sect2 id="sensitivityaliasactual">
+ <title>sensitivityaliasactual</title>
+ <para>Associates a previously declared <literal><link linkend="sensitivityalias">sensitivityalias</link></literal> identifier to a previously declared <literal><link linkend="sensitivity">sensitivity</link></literal> identifier.</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(sensitivityaliasactual sensitivityalias_id sensitivity_id)]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2.5 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>sensitivityaliasactual</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>sensitivityaliasactual</literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>sensitivityalias_id</literal></para>
+ </entry>
+ <entry>
+ <para>A single previously declared <literal><link linkend="sensitivityalias">sensitivityalias</link></literal> identifier.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>sensitivity_id</literal></para>
+ </entry>
+ <entry>
+ <para>A single previously declared <literal><link linkend="sensitivity">sensitivity</link></literal> identifier.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+
+ <para><emphasis role="bold">Example:</emphasis></para>
+ <para>This example will associate sensitivity <literal>s0</literal> with two sensitivity alias's:</para>
+ <programlisting><![CDATA[
+(sensitivity s0)
+(sensitivityalias unclassified)
+(sensitivityalias SystemLow)
+(sensitivityaliasactual unclassified s0)
+(sensitivityaliasactual SystemLow s0)]]>
+ </programlisting>
+ </sect2>
+
+ <sect2 id="sensitivityorder">
+ <title>sensitivityorder</title>
+ <para>Define the sensitivity order - lowest to highest. Multiple <literal><link linkend="sensitivityorder">sensitivityorder</link></literal> statements in the policy will form an ordered list.</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(sensitivityorder (sensitivity_id ...))]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>sensitivityorder</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>sensitivityorder</literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>sensitivity_id</literal></para>
+ </entry>
+ <entry>
+ <para>One or more previously declared <literal><link linkend="sensitivity">sensitivity</link></literal> or <literal><link linkend="sensitivityalias">sensitivityalias</link></literal> identifiers..</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+
+ <para><emphasis role="bold">Example:</emphasis></para>
+ <para>This example shows two <literal><link linkend="sensitivityorder">sensitivityorder</link></literal> statements that when compiled will form an ordered list. Note however that the second <literal><link linkend="sensitivityorder">sensitivityorder</link></literal> statement starts with <literal>s2</literal> so that the ordered list can be built.</para>
+ <programlisting><![CDATA[
+(sensitivity s0)
+(sensitivityalias s0 SystemLow)
+(sensitivity s1)
+(sensitivity s2)
+(sensitivityorder (SystemLow s1 s2))
+
+(sensitivity s3)
+(sensitivity s4)
+(sensitivityalias s4 SystemHigh)
+(sensitivityorder (s2 s3 SystemHigh))]]>
+ </programlisting>
+ </sect2>
+
+ <sect2 id="category">
+ <title>category</title>
+ <para>Declare a category identifier in the current namespace. Multiple category statements declared in the policy will form an ordered list.</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(category category_id)]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>category</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>category</literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>category_id</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal><link linkend="category">category</link></literal> identifier.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+
+ <para><emphasis role="bold">Example:</emphasis></para>
+ <para>This example declares a three <literal><link linkend="category">category</link></literal> identifiers:</para>
+ <programlisting><![CDATA[
+(category c0)
+(category c1)
+(category c2)]]>
+ </programlisting>
+ </sect2>
+
+ <sect2 id="categoryalias">
+ <title>categoryalias</title>
+ <para>Declares a category alias identifier in the current namespace. See the <literal><link linkend="categoryaliasactual">categoryaliasactual</link></literal> statement for an example that associates the <literal><link linkend="categoryalias">categoryalias</link></literal> identifier.</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(categoryalias categoryalias_id)]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>categoryalias</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>categoryalias</literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>categoryalias_id</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal><link linkend="categoryalias">categoryalias</link></literal> identifier.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+ </sect2>
+
+ <sect2 id="categoryaliasactual">
+ <title>categoryaliasactual</title>
+ <para>Associates a previously declared <literal><link linkend="categoryalias">categoryalias</link></literal> identifier to a previously declared <literal><link linkend="category">category</link></literal> identifier.</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(categoryaliasactual categoryalias_id category_id)]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>categoryaliasactual</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>categoryaliasactual</literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>categoryalias_id</literal></para>
+ </entry>
+ <entry>
+ <para>A single previously declared <literal><link linkend="categoryalias">categoryalias</link></literal> identifier.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>category_id</literal></para>
+ </entry>
+ <entry>
+ <para>A single previously declared <literal><link linkend="category">category</link></literal> identifier.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+
+ <para><emphasis role="bold">Example:</emphasis></para>
+ <para>Declares a category <literal>c0</literal>, a category alias of <literal>documents</literal>, and then associates them:</para>
+ <programlisting><![CDATA[
+(category c0)
+(categoryalias documents)
+(categoryaliasactual documents c0)]]>
+ </programlisting>
+ </sect2>
+
+ <sect2 id="categoryorder">
+ <title>categoryorder</title>
+ <para>Define the category order. Multiple <literal><link linkend="categoryorder">categoryorder</link></literal> statements declared in the policy will form an ordered list. Note that this statement orders the categories to allow validation of category ranges.</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(categoryorder (category_id ...))]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>categoryorder</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>categoryorder</literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>category_id</literal></para>
+ </entry>
+ <entry>
+ <para>One or more previously declared <literal><link linkend="category">category</link></literal> or <literal><link linkend="categoryalias">categoryalias</link></literal> identifiers.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+
+ <para><emphasis role="bold">Example:</emphasis></para>
+ <para>This example orders one category alias and nine categories:</para>
+ <programlisting><![CDATA[(categoryorder (documents c1 c2 c3 c4 c5 c6 c7 c8 c9)]]>
+ </programlisting>
+ </sect2>
+
+ <sect2 id="categoryset">
+ <title>categoryset</title>
+ <para>Declare an identifier for a set of contiguous or non-contiguous categories in the current namespace.</para>
+ <para>Notes:</para>
+ <itemizedlist>
+ <listitem><para>Category expressions are allowed in <literal><link linkend="categoryset">categoryset</link></literal>, <literal><link linkend="sensitivitycategory">sensitivitycategory</link></literal>, <literal><link linkend="level">level</link></literal>, and <literal><link linkend="levelrange">levelrange</link></literal> statements.</para></listitem>
+ <listitem><para>Category sets are not allowed in <literal><link linkend="categoryorder">categoryorder</link></literal> statements.</para></listitem>
+ </itemizedlist>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(categoryset categoryset_id (category_id ... | expr ...))]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>categoryset</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>categoryset</literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>categoryset_id</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal><link linkend="categoryset">categoryset</link></literal> identifier.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>category_id</literal></para>
+ </entry>
+ <entry>
+ <para>Zero or more previously declared <literal><link linkend="category">category</link></literal> or <literal><link linkend="categoryalias">categoryalias</link></literal> identifiers.</para>
+ <para>Note that there must be at least one <literal>category_id</literal> identifier or <literal>expr</literal> parameter declared.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>expr</literal></para>
+ </entry>
+ <entry>
+ <para>Zero or more <literal>expr</literal>'s, the valid operators and syntax are:</para>
+ <simpara><literal> (and (category_id ...) (category_id ...))</literal></simpara>
+ <simpara><literal> (or (category_id ...) (category_id ...))</literal></simpara>
+ <simpara><literal> (xor (category_id ...) (category_id ...))</literal></simpara>
+ <simpara><literal> (not (category_id ...))</literal></simpara>
+ <simpara><literal> (range category_id category_id)</literal></simpara>
+ <simpara><literal> (all)</literal></simpara>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+
+ <para><emphasis role="bold">Examples:</emphasis></para>
+ <para>These examples show a selection of <literal><link linkend="categoryset">categoryset</link></literal> statements:</para>
+ <programlisting><![CDATA[
+; Declare categories with two alias's:
+(category c0)
+(categoryalias documents)
+(categoryaliasactual documents c0)
+(category c1)
+(category c2)
+(category c3)
+(category c4)
+(categoryalias spreadsheets)
+(categoryaliasactual spreadsheets c4)
+
+; Set the order to determine ranges:
+(categoryorder (c0 c1 c2 c3 spreadsheets))
+
+(categoryset catrange_1 (range c2 c3))
+
+; Two methods to associate all categories:
+(categoryset all_cats (range c0 c4))
+(categoryset all_cats1 (all))
+
+(categoryset catset_1 (documents c1))
+(categoryset catset_2 (c2 c3))
+(categoryset catset_3 (c4))
+
+(categoryset just_c0 (xor (c1 c2) (documents c1 c2)))]]>
+ </programlisting>
+ </sect2>
+
+ <sect2 id="sensitivitycategory">
+ <title>sensitivitycategory</title>
+ <para>Associate a <literal><link linkend="sensitivity">sensitivity</link></literal> identifier with one or more <link linkend="category">category</link>'s. Multiple definitions for the same <literal><link linkend="sensitivity">sensitivity</link></literal> form an ordered list of categories for that sensitivity. This statement is required before a <literal><link linkend="level">level</link></literal> identifier can be declared.</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(sensitivitycategory sensitivity_id categoryset_id)]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>sensitivitycategory</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>sensitivitycategory</literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>sensitivity_id</literal></para>
+ </entry>
+ <entry>
+ <para>A single previously declared <literal><link linkend="sensitivity">sensitivity</link></literal> or <literal><link linkend="sensitivityalias">sensitivityalias</link></literal> identifier.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>categoryset_id</literal></para>
+ </entry>
+ <entry>
+ <para>A single previously declared <literal><link linkend="categoryset">categoryset</link></literal> (named or anonymous), or a list of <literal><link linkend="category">category</link></literal> and/or <literal><link linkend="categoryalias">categoryalias</link></literal> identifiers. The examples show each variation.
+</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+ <para><emphasis role="bold">Examples:</emphasis></para>
+ <para>These <literal>sensitivitycategory</literal> examples use a selection of <literal><link linkend="category">category</link></literal>, <literal><link linkend="categoryalias">categoryalias</link></literal> and <literal><link linkend="categoryset">categoryset</link></literal>'s:</para>
+ <programlisting><![CDATA[
+(sensitivitycategory s0 catrange_1)
+(sensitivitycategory s0 catset_1)
+(sensitivitycategory s0 catset_3)
+(sensitivitycategory s0 (all))
+(sensitivitycategory unclassified (range documents c2))]]>
+ </programlisting>
+ </sect2>
+
+ <sect2 id="level">
+ <title>level</title>
+ <para>Declare a <literal><link linkend="level">level</link></literal> identifier in the current namespace and associate it to a previously declared <literal><link linkend="sensitivity">sensitivity</link></literal> and zero or more categories. Note that if categories are required, then before this statement can be resolved the <literal><link linkend="sensitivitycategory">sensitivitycategory</link></literal> statement must be used to associate categories with the sensitivity.</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[level level_id (sensitivity_id [categoryset_id])]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>level</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>level</literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>level_id</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal><link linkend="level">level</link></literal> identifier.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>sensitivity_id</literal></para>
+ </entry>
+ <entry>
+ <para>A single previously declared <literal><link linkend="sensitivity">sensitivity</link></literal> or <literal><link linkend="sensitivityalias">sensitivityalias</link></literal> identifier.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>categoryset_id</literal></para>
+ </entry>
+ <entry>
+ <para>A single previously declared <literal><link linkend="categoryset">categoryset</link></literal> (named or anonymous), or a list of <literal><link linkend="category">category</link></literal> and/or <literal><link linkend="categoryalias">categoryalias</link></literal> identifiers. The examples show each variation.
+</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+ <para><emphasis role="bold">Examples:</emphasis></para>
+ <para>These <literal>level</literal> examples use a selection of <literal><link linkend="category">category</link></literal>, <literal><link linkend="categoryalias">categoryalias</link></literal> and <literal><link linkend="categoryset">categoryset</link></literal>'s:</para>
+ <programlisting><![CDATA[
+(level systemLow (s0))
+(level level_1 (s0))
+(level level_2 (s0 (catrange_1)))
+(level level_3 (s0 (all_cats)))
+(level level_4 (unclassified (c2 c3 c4)))]]>
+ </programlisting>
+ </sect2>
+
+ <sect2 id="levelrange">
+ <title>levelrange</title>
+ <para>Declare a level range identifier in the current namespace and associate a current and clearance level.</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(levelrange levelrange_id (low_level_id high_level_id))]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>levelrange</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>levelrange</literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>levelrange_id</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal><link linkend="levelrange">levelrange</link></literal> identifier.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>low_level_id</literal></para>
+ </entry>
+ <entry>
+ <para>The current level specified by a previously declared <literal><link linkend="level">level</link></literal> identifier. This may be formed by named or anonymous components as discussed in the <literal><link linkend="level">level</link></literal> section and shown in the examples.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>high_level_id</literal></para>
+ </entry>
+ <entry>
+ <para>The clearance or high level specified by a previously declared <literal><link linkend="level">level</link></literal> identifier. This may be formed by named or anonymous components as discussed in the <literal><link linkend="level">level</link></literal> section and shown in the examples.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+ <para><emphasis role="bold">Examples:</emphasis></para>
+ <para>This example policy shows <literal><link linkend="levelrange">levelrange</link></literal> statement and all the other MLS labeling statements discussed in this section and will compile as a standalone policy:</para>
+ <programlisting><![CDATA[
+(handleunknown allow)
+(mls true)
+
+; There must be least one set of SID statements in a policy:
+(sid kernel)
+(sidorder (kernel))
+(sidcontext kernel unconfined.context_1)
+
+(sensitivitycategory s0 (c4 c2 c3 c1 c0 c3))
+
+(category c0)
+(categoryalias documents)
+(categoryaliasactual documents c0)
+(category c1)
+(category c2)
+(category c3)
+(category c4)
+(categoryalias spreadsheets)
+(categoryaliasactual spreadsheets c4)
+
+(categoryorder (c0 c1 c2 c3 spreadsheets))
+
+(categoryset catrange_1 (range c2 c3))
+(categoryset all_cats (range c0 c4))
+(categoryset all_cats1 (all))
+
+(categoryset catset_1 (documents c1))
+(categoryset catset_2 (c2 c3))
+(categoryset catset_3 (c4))
+
+(categoryset just_c0 (xor (c1 c2) (documents c1 c2)))
+
+(sensitivity s0)
+(sensitivityalias unclassified)
+(sensitivityaliasactual unclassified s0)
+
+(sensitivityorder (s0))
+(sensitivitycategory s0 (c0))
+
+(sensitivitycategory s0 catrange_1)
+(sensitivitycategory s0 catset_1)
+(sensitivitycategory s0 catset_3)
+(sensitivitycategory s0 (all))
+(sensitivitycategory s0 (range documents c2))
+
+(level systemLow (s0))
+(level level_1 (s0))
+(level level_2 (s0 (catrange_1)))
+(level level_3 (s0 (all_cats)))
+(level level_4 (unclassified (c2 c3 c4)))
+
+(levelrange levelrange_2 (level_2 level_2))
+(levelrange levelrange_1 ((s0) level_2))
+(levelrange low_low (systemLow systemLow))
+
+(context context_2 (unconfined.user object_r unconfined.object (level_1 level_3)))
+
+; Define object_r role. This must be assigned in CIL.
+(role object_r)
+
+(block unconfined
+ (user user)
+ (role role)
+ (type process)
+ (type object)
+ (userrange user (systemLow systemLow))
+ (userlevel user systemLow)
+ (userrole user role)
+ (userrole user object_r)
+ (roletype role process)
+ (roletype role object)
+ (roletype object_r object)
+
+ (class file (open execute read write))
+
+ ; There must be least one allow rule in a policy:
+ (allow process self (file (read)))
+
+ (context context_1 (user object_r object low_low))
+) ; End unconfined namespace]]>
+ </programlisting>
+ </sect2>
+
+ <sect2 id="rangetransition">
+ <title>rangetransition</title>
+ <para>Allows an objects level to transition to a different level. Generally used to ensure processes run with their correct MLS range, for example <literal>init</literal> would run at <literal>SystemHigh</literal> and needs to initialise / run other processes at their correct MLS range.</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(rangetransition source_id target_id class_id new_range_id)]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>rangetransition</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>rangetransition</literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>source_type_id</literal></para>
+ </entry>
+ <entry>
+ <para>A single previously declared <literal><link linkend="type">type</link></literal>, <literal><link linkend="typealias">typealias</link></literal> or <literal><link linkend="typeattribute">typeattribute</link></literal> identifier.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>target_type_id</literal></para>
+ </entry>
+ <entry>
+ <para>A single previously declared <literal><link linkend="type">type</link></literal>, <literal><link linkend="typealias">typealias</link></literal> or <literal><link linkend="typeattribute">typeattribute</link></literal> identifier.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>class_id</literal></para>
+ </entry>
+ <entry>
+ <para>A single previously declared <literal><link linkend="class">class</link></literal> or <literal><link linkend="classmap">classmap</link></literal> identifier.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>new_range_id</literal></para>
+ </entry>
+ <entry>
+ <para>The new MLS range for the object class that is a previously declared <literal><link linkend="levelrange">levelrange</link></literal> identifier. This entry may also be defined as an anonymous or named <literal><link linkend="level">level</link></literal>, <literal><link linkend="sensitivity">sensitivity</link></literal>, <literal><link linkend="sensitivityalias">sensitivityalias</link></literal>, <literal><link linkend="category">category</link></literal>, <literal><link linkend="categoryalias">categoryalias</link></literal> or <literal><link linkend="categoryset">categoryset</link></literal> identifier.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+
+ <para><emphasis role="bold">Examples:</emphasis></para>
+ <para>This rule will transition the range of <literal>sshd.exec</literal> to <literal>s0 - s1:c0.c3</literal> on execution from the <literal>init.process</literal>:</para>
+ <programlisting><![CDATA[
+(sensitivity s0)
+(sensitivity s1)
+(sensitivityorder s0 s1)
+(category c0)
+...
+(level systemlow (s0)
+(level systemhigh (s1 (c0 c1 c2)))
+(levelrange low_high (systemlow systemhigh))
+
+(rangetransition init.process sshd.exec process low_high)]]>
+ </programlisting>
+ </sect2>
+
+ <sect2>
+ <title>mlsconstrain</title>
+ <para>This is described in the <link linkend="mlsconstrain">Contraints</link> section.</para>
+ </sect2>
+
+ <sect2>
+ <title>mlsvalidatetrans</title>
+ <para>This is described in the <link linkend="mlsvalidatetrans">Contraints</link> section.</para>
+ </sect2>
+
+ </sect1>
diff --git a/cil/docs/cil_network_labeling_statements.xml b/cil/docs/cil_network_labeling_statements.xml
new file mode 100644
index 0000000..785b583
--- /dev/null
+++ b/cil/docs/cil_network_labeling_statements.xml
@@ -0,0 +1,234 @@
+<!-- Common Interface Language (CIL) Reference Guide -->
+ <!-- network_labeling_statements.xml -->
+
+ <sect1 id="network_labeling">
+ <title>Network Labeling Statements</title>
+ <sect2 id="ipaddr">
+ <title>ipaddr</title>
+ <para>Declares a named IP address in IPv4 or IPv6 format that may be referenced by other CIL statements (i.e. <literal>netifcon</literal>).</para>
+ <para>Notes:</para>
+ <itemizedlist>
+ <listitem><para>CIL statements utilising an IP address may reference a named IP address or use an anonymous address, the examples will show each option.</para></listitem>
+
+ <listitem><para>IP Addresses may be declared without a previous declaration by enclosing within parentheses e.g. <literal>(127.0.0.1)</literal> or <literal>(::1)</literal>.</para></listitem>
+ </itemizedlist>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(ipaddr ipaddr_id ip_address)]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>ipaddr</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>ipaddr</literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>ipaddr_id</literal></para>
+ </entry>
+ <entry>
+ <para>The IP address identifier.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>ip_address</literal></para>
+ </entry>
+ <entry>
+ <para>A correctly formatted IP address in IPv4 or IPv6 format.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+
+ <para><emphasis role="bold">Example:</emphasis></para>
+ <para>This example declares a named IP address and also passes an 'explicit anonymously declared' IP address to a macro:</para>
+ <programlisting><![CDATA[
+(ipaddr netmask_1 255.255.255.0)
+(context netlabel_1 (system.user object_r unconfined.object low_low)
+
+(call build_nodecon ((192.168.1.64) netmask_1))
+
+(macro build_nodecon ((ipaddr ARG1) (ipaddr ARG2))
+ (nodecon ARG1 ARG2 netlabel_1))]]>
+ </programlisting>
+ </sect2>
+
+ <sect2 id="netifcon">
+ <title>netifcon</title>
+ <para>Label network interface objects (e.g. <literal>eth0</literal>).</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(netifcon netif_name netif_context_id packet_context_id)]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>netifcon</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>netifcon</literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>netif_name</literal></para>
+ </entry>
+ <entry>
+ <para>The network interface name (e.g. <literal>wlan0</literal>).</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>netif_context_id</literal></para>
+ </entry>
+ <entry>
+ <para>The security context to be allocated to the network interface.</para>
+ <para>A previously declared <literal><link linkend="context">context</link></literal> identifier or an anonymous security context (<literal><link linkend="user">user</link> <link linkend="role">role</link> <link linkend="type">type</link> <link linkend="levelrange">levelrange</link></literal>), the range MUST be defined whether the policy is MLS/MCS enabled or not.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>packet_context_id</literal></para>
+ </entry>
+ <entry>
+ <para>The security context to be allocated to packets. Note that these are defined but currently unused as the <emphasis role="bold"><literal>iptables</literal></emphasis><literal>(8)</literal> SECMARK services should be used to label packets.</para>
+ <para>A previously declared <literal><link linkend="context">context</link></literal> identifier or an anonymous security context (<literal><link linkend="user">user</link> <link linkend="role">role</link> <link linkend="type">type</link> <link linkend="levelrange">levelrange</link></literal>), the range MUST be defined whether the policy is MLS/MCS enabled or not.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+
+ <para><emphasis role="bold">Examples:</emphasis></para>
+ <para>These examples show named and anonymous <literal>netifcon</literal> statements:</para>
+ <programlisting><![CDATA[
+(context context_1 (unconfined.user object_r unconfined.object low_low))
+(context context_2 (unconfined.user object_r unconfined.object (systemlow level_2)))
+
+(netifcon eth0 context_1 (unconfined.user object_r unconfined.object levelrange_1))
+(netifcon eth1 context_1 (unconfined.user object_r unconfined.object ((s0) level_1)))
+(netifcon eth3 context_1 context_2)]]>
+ </programlisting>
+ </sect2>
+
+ <sect2 id="nodecon">
+ <title>nodecon</title>
+ <para>Label network address objects that represent IPv4 or IPv6 IP addresses and network masks.</para>
+ <para>IP Addresses may be declared without a previous declaration by enclosing within parentheses e.g. <literal>(127.0.0.1)</literal> or <literal>(::1)</literal>.</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(nodecon subnet_id netmask_id context_id)]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>nodecon</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>nodecon</literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>subnet_id</literal></para>
+ </entry>
+ <entry>
+ <para>A previously declared <literal><link linkend="ipaddr">ipaddr</link></literal> identifier, or an anonymous IPv4 or IPv6 formatted address.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>netmask_id</literal></para>
+ </entry>
+ <entry>
+ <para>A previously declared <literal><link linkend="ipaddr">ipaddr</link></literal> identifier, or an anonymous IPv4 or IPv6 formatted address.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>context_id</literal></para>
+ </entry>
+ <entry>
+ <para>A previously declared <literal><link linkend="context">context</link></literal> identifier or an anonymous security context (<literal><link linkend="user">user</link> <link linkend="role">role</link> <link linkend="type">type</link> <link linkend="levelrange">levelrange</link></literal>), the range MUST be defined whether the policy is MLS/MCS enabled or not.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+
+ <para><emphasis role="bold">Examples:</emphasis></para>
+ <para>These examples show named and anonymous <literal>nodecon</literal> statements:</para>
+ <programlisting><![CDATA[
+(context context_1 (unconfined.user object_r unconfined.object low_low))
+(context context_2 (unconfined.user object_r unconfined.object (systemlow level_2)))
+
+(ipaddr netmask_1 255.255.255.0)
+(ipaddr ipv4_1 192.168.1.64)
+
+(nodecon netmask_1 ipv4_1 context_2)
+(nodecon (255.255.255.0) (192.168.1.64) context_1)
+(nodecon netmask_1 (192.168.1.64) (unconfined.user object_r unconfined.object ((s0) (s0 (c0)))))]]>
+ </programlisting>
+ </sect2>
+
+ <sect2 id="portcon">
+ <title>portcon</title>
+ <para>Label a udp or tcp port.</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(portcon protocol port context_id)]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>portcon</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>portcon</literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>protocol</literal></para>
+ </entry>
+ <entry>
+ <para>The protocol keyword <literal>tcp</literal> or <literal>udp</literal>.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>context_id</literal></para>
+ </entry>
+ <entry>
+ <para>A previously declared <literal><link linkend="context">context</link></literal> identifier or an anonymous security context (<literal><link linkend="user">user</link> <link linkend="role">role</link> <link linkend="type">type</link> <link linkend="levelrange">levelrange</link></literal>), the range MUST be defined whether the policy is MLS/MCS enabled or not.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+
+ <para><emphasis role="bold">Examples:</emphasis></para>
+ <para>These examples show named and anonymous <literal>portcon</literal> statements:</para>
+ <programlisting><![CDATA[
+(portcon tcp 1111 (unconfined.user object_r unconfined.object ((s0) (s0 (c0)))))
+(portcon tcp 2222 (unconfined.user object_r unconfined.object levelrange_2))
+(portcon tcp 3333 (unconfined.user object_r unconfined.object levelrange_1))
+(portcon udp 4444 (unconfined.user object_r unconfined.object ((s0) level_2)))
+(portcon tcp 55555 (unconfined.user object_r unconfined.object (systemlow level_3)))]]>
+ </programlisting>
+ </sect2>
+
+ </sect1>
diff --git a/cil/docs/cil_policy_config_statements.xml b/cil/docs/cil_policy_config_statements.xml
new file mode 100644
index 0000000..771e4dd
--- /dev/null
+++ b/cil/docs/cil_policy_config_statements.xml
@@ -0,0 +1,118 @@
+<!-- Common Interface Language (CIL) Reference Guide -->
+ <!-- policy_config_statements.xml -->
+
+ <sect1>
+ <title>Policy Configuration Statements</title>
+ <sect2 id="mls">
+ <title>mls</title>
+ <para>Defines whether the policy is built as an MLS or non-MLS policy by the CIL compiler. There MUST only be one <literal>mls</literal> entry in the policy otherwise the compiler will exit with an error.</para>
+ <para>Note that this can be over-ridden by the CIL compiler command line parameter <literal>-M true|false</literal> or <literal>--mls true|false</literal> flags.</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(mls boolean)]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>mls</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>mls</literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>boolean</literal></para>
+ </entry>
+ <entry>
+ <para>Set to either <literal>true</literal> or <literal>false</literal>.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+ <para><emphasis role="bold">Example:</emphasis></para>
+ <programlisting><![CDATA[(mls true)]]></programlisting>
+ </sect2>
+
+ <sect2 id="handleunknown">
+ <title>handleunknown</title>
+ <para>Defines how the kernel will handle unknown object classes and permissions when loading the policy. There MUST only be one <literal>handleunknown</literal> entry in the policy otherwise the compiler will exit with an error.</para>
+ <para>Note that this can be over-ridden by the CIL compiler command line parameter <literal>-U</literal> or <literal>--handle-unknown</literal> flags.</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(handleunknown action)]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="1.5 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>handleunknown</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>handleunknown</literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>action</literal></para>
+ </entry>
+ <entry>
+ <para>A keyword of either <literal>allow</literal>, <literal>deny</literal> or <literal>reject</literal>. The kernel will handle these keywords as follows:</para>
+ <simpara><literal> allow</literal> unknown class / permissions. This will set the returned AV with all 1's.</simpara>
+ <simpara><literal> deny</literal> unknown class / permissions (the default). This will set the returned AV with all 0's.</simpara>
+ <simpara><literal> reject</literal> loading the policy if it does not contain all the object classes / permissions.</simpara>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+ <para><emphasis role="bold">Example:</emphasis></para>
+ <para>This will allow unknown classes / permissions to be present in the policy:</para>
+ <programlisting><![CDATA[(handleunknown allow)]]></programlisting>
+ </sect2>
+
+ <sect2 id="policycap">
+ <title>policycap</title>
+ <para>Allow policy capabilities to be enabled via policy. These should be declared in the global namespace and be valid policy capabilities as they are checked against those known in libsepol by the CIL compiler.</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(policycap policycap_id)]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>policycap</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>policycap</literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>policycap_id</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>policycap</literal> identifer (e.g. <literal>open_perms</literal>).</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+ <para><emphasis role="bold">Example:</emphasis></para>
+ <para>These set two valid policy capabilities:</para>
+ <programlisting><![CDATA[
+; Enable networking controls.
+(policycap network_peer_controls)
+
+; Enable open permission check.
+(policycap open_perms)]]>
+ </programlisting>
+ </sect2>
+ </sect1>
+
diff --git a/cil/docs/cil_role_statements.xml b/cil/docs/cil_role_statements.xml
new file mode 100644
index 0000000..47ca8c7
--- /dev/null
+++ b/cil/docs/cil_role_statements.xml
@@ -0,0 +1,374 @@
+<!-- Common Interface Language (CIL) Reference Guide -->
+ <!-- role_statements.xml -->
+
+
+
+ <sect1>
+ <title>Role Statements</title>
+ <sect2 id="role">
+ <title>role</title>
+ <para>Declares a role identifier in the current namespace.</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(role role_id)]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>role</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>role</literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>role_id</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>role</literal> identifier.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+
+ <para><emphasis role="bold">Example:</emphasis></para>
+ <para>This example declares two roles: <literal>object_r</literal> in the global namespace and <literal>unconfined.role</literal>:</para>
+ <programlisting><![CDATA[
+(role object_r)
+
+(block unconfined
+ (role role)
+)]]>
+ </programlisting>
+ </sect2>
+
+ <sect2 id="roletype">
+ <title>roletype</title>
+ <para>Authorises a <literal><link linkend="role">role</link></literal> to access a <literal><link linkend="type">type</link></literal> identifier.</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(role role_id type_id)]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>roletype</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>roletype</literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>role_id</literal></para>
+ </entry>
+ <entry>
+ <para>A single previously declared <literal><link linkend="role">role</link></literal> or <literal><link linkend="roleattribute">roleattribute</link></literal> identifier.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>type_id</literal></para>
+ </entry>
+ <entry>
+ <para>A single previously declared <literal><link linkend="type">type</link></literal>, <literal><link linkend="typealias">typealias</link></literal> or <literal><link linkend="typeattribute">typeattribute</link></literal> identifier.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+
+ <para><emphasis role="bold">Example:</emphasis></para>
+ <para>This example will declare <literal><link linkend="role">role</link></literal> and <literal><link linkend="type">type</link></literal> identifiers, then associate them:</para>
+ <programlisting><![CDATA[
+(block unconfined
+ (role role)
+ (type process)
+ (roletype role process)
+)]]>
+ </programlisting>
+ </sect2>
+
+ <sect2 id="roleattribute">
+ <title>roleattribute</title>
+ <para>Declares a role attribute identifier in the current namespace. The identifier may have zero or more <literal><link linkend="role">role</link></literal> and <literal><link linkend="roleattribute">roleattribute</link></literal> identifiers associated to it via the <literal><link linkend="roleattributeset">typeattributeset</link></literal> statement.</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(roleattribute roleattribute_id)]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>roleattribute</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>roleattribute</literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>roleattribute_id</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>roleattribute</literal> identifier.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+
+ <para><emphasis role="bold">Example:</emphasis></para>
+ <para>This example will declare a role attribute <literal>roles.role_holder</literal> that will have an empty set:</para>
+ <programlisting><![CDATA[
+(block roles
+ (roleattribute role_holder)
+)]]>
+ </programlisting>
+ </sect2>
+
+ <sect2 id="roleattributeset">
+ <title>roleattributeset</title>
+ <para>Allows the association of one or more previously declared <literal><link linkend="role">role</link></literal> identifiers to a <literal><link linkend="roleattribute">roleattribute</link></literal> identifier. Expressions may be used to refine the associations as shown in the examples.</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(roleattributeset roleattribute_id (role_id ... | expr ...))]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>roleattributeset</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>roleattributeset</literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>roleattribute_id</literal></para>
+ </entry>
+ <entry>
+ <para>A single previously declared <literal><link linkend="roleattribute">roleattribute</link></literal> identifier.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>role_id</literal></para>
+ </entry>
+ <entry>
+ <para>Zero or more previously declared <literal><link linkend="role">role</link></literal> or <literal><link linkend="roleattribute">roleattribute</link></literal> identifiers.</para>
+ <para>Note that there must be at least one <literal>role_id</literal> or <literal>expr</literal> parameter declared.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>expr</literal></para>
+ </entry>
+ <entry>
+ <para>Zero or more <literal>expr</literal>'s, the valid operators and syntax are:</para>
+ <simpara><literal> (and (role_id ...) (role_id ...))</literal></simpara>
+ <simpara><literal> (or (role_id ...) (role_id ...))</literal></simpara>
+ <simpara><literal> (xor (role_id ...) (role_id ...))</literal></simpara>
+ <simpara><literal> (not (role_id ...))</literal></simpara>
+ <simpara><literal> (all)</literal></simpara>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+
+ <para><emphasis role="bold">Example:</emphasis></para>
+ <para>This example will declare three roles and two role attributes, then associate all the roles to them as shown:</para>
+ <programlisting><![CDATA[
+(block roles
+ (role role_1)
+ (role role_2)
+ (role role_3)
+
+ (roleattribute role_holder)
+ (roleattributeset role_holder (role_1 role_2 role_3))
+
+ (roleattribute role_holder_all)
+ (roleattributeset role_holder_all (all))
+)]]>
+ </programlisting>
+ </sect2>
+
+ <sect2 id="roleallow">
+ <title>roleallow</title>
+ <para>Authorise the current role to assume a new role.</para>
+ <para>Notes:</para>
+ <itemizedlist>
+ <listitem><para>May require a <literal><link linkend="roletransition">roletransition</link></literal> rule to ensure transition to the new role.</para></listitem>
+ <listitem><para>This rule is not allowed in <literal><link linkend="booleanif">booleanif</link></literal> statements.</para></listitem>
+ </itemizedlist>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(roleallow current_role_id new_role_id)]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>roleallow</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>roleallow</literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>current_role_id</literal></para>
+ </entry>
+ <entry>
+ <para>A single previously declared <literal><link linkend="role">role</link></literal> or <literal><link linkend="roleattribute">roleattribute</link></literal> identifier.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>new_role_id</literal></para>
+ </entry>
+ <entry>
+ <para>A single previously declared <literal><link linkend="role">role</link></literal> or <literal><link linkend="roleattribute">roleattribute</link></literal> identifier.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+ <para><emphasis role="bold">Example:</emphasis></para>
+ <para>See the <literal><link linkend="roletransition">roletransition</link></literal> statement for an example.</para>
+ </sect2>
+
+ <sect2 id="roletransition">
+ <title>roletransition</title>
+ <para>Specify a role transition from the current role to a new role when computing a context for the target type. The <literal><link linkend="class">class</link></literal> identifier would normally be <literal>process</literal>, however for kernel versions 2.6.39 with policy version >= 25 and above, any valid class may be used. Note that a <literal><link linkend="roleallow">roleallow</link></literal> rule must be used to authorise the transition.</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(roletransition current_role_id target_type_id class_id new_role_id)]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>roletransition</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>roletransition</literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>current_role_id</literal></para>
+ </entry>
+ <entry>
+ <para>A single previously declared <literal><link linkend="role">role</link></literal> or <literal><link linkend="roleattribute">roleattribute</link></literal> identifier.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>target_type_id</literal></para>
+ </entry>
+ <entry>
+ <para>A single previously declared <literal><link linkend="type">type</link></literal>, <literal><link linkend="typealias">typealias</link></literal> or <literal><link linkend="typeattribute">typeattribute</link></literal> identifier.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>class_id</literal></para>
+ </entry>
+ <entry>
+ <para>A single previously declared <literal><link linkend="class">class</link></literal> or <literal><link linkend="classmap">classmap</link></literal> identifier.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>new_role_id</literal></para>
+ </entry>
+ <entry>
+ <para>A single previously declared <literal><link linkend="role">role</link></literal> identifier to be set on transition.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+
+ <para><emphasis role="bold">Example:</emphasis></para>
+ <para>This example will authorise the <literal>unconfined.role</literal> to assume the <literal>msg_filter.role</literal> role, and then transition to that role:</para>
+ <programlisting><![CDATA[
+(block ext_gateway
+ (type process)
+ (type exec)
+
+ (roletype msg_filter.role process)
+ (roleallow unconfined.role msg_filter.role)
+ (roletransition unconfined.role exec process msg_filter.role)
+)]]>
+ </programlisting>
+ </sect2>
+
+ <sect2 id="rolebounds">
+ <title>rolebounds</title>
+ <para>Defines a hierarchical relationship between roles where the child role cannot have more privileges than the parent.</para>
+ <para>Notes:</para>
+ <itemizedlist>
+ <listitem><para>It is not possible to bind the parent role to more than one child role.</para></listitem>
+ <listitem><para>While this is added to the binary policy, it is not enforced by the SELinux kernel services.</para></listitem>
+ </itemizedlist>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(rolebounds parent_role_id child_role_id)]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>rolebounds</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>rolebounds</literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>parent_role_id</literal></para>
+ </entry>
+ <entry>
+ <para>A single previously declared <literal><link linkend="role">role</link></literal> identifier.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>child_role_id</literal></para>
+ </entry>
+ <entry>
+ <para>A single previously declared <literal><link linkend="role">role</link></literal> identifier.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+ <para><emphasis role="bold">Example:</emphasis></para>
+ <para>In this example the role <literal>test</literal> cannot have greater priviledges than <literal>unconfined.role</literal>:</para>
+ <programlisting><![CDATA[
+(role test)
+
+(unconfined
+ (role role)
+ (rolebounds role .test)
+)]]>
+ </programlisting>
+ </sect2>
+
+ </sect1>
diff --git a/cil/docs/cil_sid_statements.xml b/cil/docs/cil_sid_statements.xml
new file mode 100644
index 0000000..c0ca3ff
--- /dev/null
+++ b/cil/docs/cil_sid_statements.xml
@@ -0,0 +1,142 @@
+<!-- Common Interface Language (CIL) Reference Guide -->
+ <!-- sid_statements.xml -->
+
+ <sect1>
+ <title>SID Statements</title>
+ <sect2 id="sid">
+ <title>sid</title>
+ <para>Declares a new SID identifier in the current namespace.</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(sid sid_id)]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>sid</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>sid</literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>sid_id</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>sid</literal> identifier.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+
+ <para><emphasis role="bold">Examples:</emphasis></para>
+ <para>These examples show three <literal>sid</literal> declarations:</para>
+ <programlisting><![CDATA[
+(sid kernel)
+(sid security)
+(sid igmp_packet)]]>
+ </programlisting>
+ </sect2>
+
+ <sect2 id="sidorder">
+ <title>sidorder</title>
+ <para>Defines the order of <link linkend="sid">sid</link>'s. This is a mandatory statement when SIDs are defined. Multiple <literal>sidorder</literal> statements declared in the policy will form an ordered list.</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(sidorder (sid_id ...))]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>sidorder</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>sidorder</literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>sid_id</literal></para>
+ </entry>
+ <entry>
+ <para>One or more <literal><link linkend="sid">sid</link></literal> identifiers.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+
+ <para><emphasis role="bold">Example:</emphasis></para>
+ <para>This will produce an ordered list of "<literal>kernel security unlabeled</literal>"</para>
+ <programlisting><![CDATA[
+(sid kernel)
+(sid security)
+(sid unlabeled)
+(sidorder (kernel security))
+(sidorder (security unlabeled))]]>
+ </programlisting>
+ </sect2>
+
+ <sect2 id="sidcontext">
+ <title>sidcontext</title>
+ <para>Associates an SELinux security <link linkend="context">context</link> to a previously declared <literal><link linkend="sid">sid</link></literal> identifier.</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(sidcontext sid_id context_id)]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>sidcontext</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>sidcontext</literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>sid_id</literal></para>
+ </entry>
+ <entry>
+ <para>A single previously declared <literal><link linkend="sid">sid</link></literal> identifier.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>context_id</literal></para>
+ </entry>
+ <entry>
+ <para>A previously declared <literal><link linkend="context">context</link></literal> identifier or an anonymous security context (<literal><link linkend="user">user</link> <link linkend="role">role</link> <link linkend="type">type</link> <link linkend="levelrange">levelrange</link></literal>), the range MUST be defined whether the policy is MLS/MCS enabled or not.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+
+ <para><emphasis role="bold">Examples:</emphasis></para>
+ <para>This shows two named security context examples plus an anonymous context:</para>
+ <programlisting><![CDATA[
+; Two named context:
+(sid kernel)
+(context kernel_context (u r process low_low))
+(sidcontext kernel kernel_context)
+
+(sid security)
+(context security_context (u object_r process low_low))
+(sidcontext security security_context)
+
+; An anonymous context:
+(sid unlabeled)
+(sidcontext unlabeled (u object_r ((s0) (s0))))]]>
+ </programlisting>
+ </sect2>
+
+ </sect1>
diff --git a/cil/docs/cil_type_statements.xml b/cil/docs/cil_type_statements.xml
new file mode 100644
index 0000000..b140f86
--- /dev/null
+++ b/cil/docs/cil_type_statements.xml
@@ -0,0 +1,581 @@
+<!-- Common Interface Language (CIL) Reference Guide -->
+ <!-- type_statements.xml -->
+
+ <sect1>
+ <title>Type Statements</title>
+ <sect2 id="type">
+ <title>type</title>
+ <para>Declares a type identifier in the current namespace.</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(type type_id)]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>type</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>type</literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>type_id</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>type</literal> identifier.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+
+ <para><emphasis role="bold">Example:</emphasis></para>
+ <para>This example declares a type identifier <literal>bluetooth.process</literal>:</para>
+ <programlisting><![CDATA[
+(block bluetooth
+ (type process)
+)]]>
+ </programlisting>
+ </sect2>
+
+ <sect2 id="typealias">
+ <title>typealias</title>
+ <para>Declares a type alias in the current namespace.</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(typealias typealias_id)]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>typealias</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>typealias</literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>typealias_id</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>typealias</literal> identifier.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+ <para><emphasis role="bold">Example:</emphasis></para>
+ <para>See the <literal><link linkend="typealiasactual">typealiasactual</link></literal> statement for an example that associates the <literal><link linkend="typealias">typealias</link></literal> identifier.</para>
+ </sect2>
+
+ <sect2 id="typealiasactual">
+ <title>typealiasactual</title>
+ <para>Associates a previously declared <literal><link linkend="typealias">typealias</link></literal> identifier to a previously declared <literal><link linkend="type">type</link></literal> identifier.</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(typealiasactual typealias_id type_id)]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>typealiasactual</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>typealiasactual</literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>typealias_id</literal></para>
+ </entry>
+ <entry>
+ <para>A single previously declared <literal><link linkend="typealias">typealias</link></literal> identifier.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>type_id</literal></para>
+ </entry>
+ <entry>
+ <para>A single previously declared <literal><link linkend="type">type</link></literal> identifier.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+
+ <para><emphasis role="bold">Example:</emphasis></para>
+ <para>This example will alias <literal>unconfined.process</literal> as <literal>unconfined_t</literal> in the global namespace:</para>
+ <programlisting><![CDATA[
+(typealias unconfined_t)
+(typealiasactual unconfined_t unconfined.process)
+
+(block unconfined
+ (type process)
+)]]>
+ </programlisting>
+ </sect2>
+
+ <sect2 id="typeattribute">
+ <title>typeattribute</title>
+ <para>Declares a type attribute identifier in the current namespace. The identifier may have zero or more <literal><link linkend="type">type</link></literal>, <literal><link linkend="typealias">typealias</link></literal> and <literal><link linkend="typeattribute">typeattribute</link></literal> identifiers associated to it via the <literal><link linkend="typeattributeset">typeattributeset</link></literal> statement.</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(typeattribute typeattribute_id)]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>typeattribute</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>typeattribute</literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>typeattribute_id</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal><link linkend="typeattribute">typeattribute</link></literal> identifier.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+
+ <para><emphasis role="bold">Example:</emphasis></para>
+ <para>This example declares a type attribute <literal>domain</literal> in global namespace that will have an empty set:</para>
+ <programlisting><![CDATA[(typeattribute domain)]]>
+ </programlisting>
+ </sect2>
+
+ <sect2 id="typeattributeset">
+ <title>typeattributeset</title>
+ <para>Allows the association of one or more previously declared <literal><link linkend="type">type</link></literal>, <literal><link linkend="typealias">typealias</link></literal> or <literal><link linkend="typeattribute">typeattribute</link></literal> identifiers to a <literal><link linkend="typeattribute">typeattribute</link></literal> identifier. Expressions may be used to refine the associations as shown in the examples.</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(typeattributeset typeattribute_id (type_id ... | expr ...))]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>typeattributeset</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>typeattributeset</literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>typeattribute_id</literal></para>
+ </entry>
+ <entry>
+ <para>A single previously declared <literal><link linkend="typeattribute">typeattribute</link></literal> identifier.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>type_id</literal></para>
+ </entry>
+ <entry>
+ <para>Zero or more previously declared <literal><link linkend="type">type</link></literal>, <literal><link linkend="typealias">typealias</link></literal> or <literal><link linkend="typeattribute">typeattribute</link></literal> identifiers.</para>
+ <para>Note that there must be at least one <literal>type_id</literal> or <literal>expr</literal> parameter declared.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>expr</literal></para>
+ </entry>
+ <entry>
+ <para>Zero or more <literal>expr</literal>'s, the valid operators and syntax are:</para>
+ <simpara><literal> (and (type_id ...) (type_id ...))</literal></simpara>
+ <simpara><literal> (or (type_id ...) (type_id ...))</literal></simpara>
+ <simpara><literal> (xor (type_id ...) (type_id ...))</literal></simpara>
+ <simpara><literal> (not (type_id ...))</literal></simpara>
+ <simpara><literal> (all)</literal></simpara>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+
+ <para><emphasis role="bold">Examples:</emphasis></para>
+ <para>This example will take all the policy types and exclude those in <literal>appdomain</literal>. It is equivalent to <literal>~appdomain</literal> in the kernel policy language.</para>
+ <programlisting><![CDATA[
+(typeattribute not_in_appdomain)
+
+(typeattributeset not_in_appdomain (not (appdomain)))]]>
+ </programlisting>
+ <para>This example is equivalent to <literal>{ domain -kernel.process -ueventd.process -init.process }</literal> in the kernel policy language:</para>
+ <programlisting><![CDATA[
+(typeattribute na_kernel_or_ueventd_or_init_in_domain)
+
+(typeattributeset na_kernel_or_ueventd_or_init_in_domain
+ (and
+ (and
+ (and
+ (domain)
+ (not (kernel.process))
+ )
+ (not (ueventd.process))
+ )
+ (not (init.process))
+ )
+)]]>
+ </programlisting>
+ </sect2>
+
+ <sect2 id="typebounds">
+ <title>typebounds</title>
+ <para>This defines a hierarchical relationship between domains where the bounded domain cannot have more permissions than its bounding domain (the parent).</para>
+ <para>Requires kernel 2.6.28 and above to control the security context associated to threads in multi-threaded applications. Note that an <literal><link linkend="allow">allow</link></literal> rule must be used to authorise the bounding.</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(typebounds parent_type_id child_type_id)]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>typebounds</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>typebounds</literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>parent_type_id</literal></para>
+ </entry>
+ <entry>
+ <para>A single previously declared <literal><link linkend="type">type</link></literal> or <literal><link linkend="typealias">typealias</link></literal> identifier that is the parent domain.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>child_type_id</literal></para>
+ </entry>
+ <entry>
+ <para>A single previously declared <literal><link linkend="type">type</link></literal> or <literal><link linkend="typealias">typealias</link></literal> identifier that is the bound (child) domain.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+ <para><emphasis role="bold">Example:</emphasis></para>
+ <para>In this example the <literal>httpd.child.process</literal> cannot have <literal>file (write)</literal> due to lack of permissions on <literal>httpd.process</literal> which is the parent. It means the child domain will always have equal or less privileges than the parent:</para>
+ <programlisting><![CDATA[
+(class file (getattr read write))
+
+(block httpd
+ (type process)
+ (type object)
+
+ (typebounds process child.process)
+ ; The parent is allowed file 'getattr' and 'read':
+ (allow process object (file (getattr read)))
+
+ (block child
+ (type process)
+ (type object)
+
+ ; However the child process has been given 'write' access that will be denied.
+ (allow process httpd.object (file (read write)))
+ )
+)]]>
+ </programlisting>
+ </sect2>
+
+ <sect2 id="typechange">
+ <title>typechange</title>
+ <para>The type change rule is used to define a different label of an object for userspace SELinux-aware applications. These applications would use <emphasis role="bold"><literal>security_compute_relabel</literal></emphasis><literal>(3)</literal> and <literal>typechange</literal> rules in the policy to determine the new context to be applied. Note that an <literal><link linkend="allow">allow</link></literal> rule must be used to authorise the change.</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(typechange source_type_id target_type_id class_id change_type_id)]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>typechange</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>typechange</literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>source_type_id</literal></para>
+ </entry>
+ <entry>
+ <para>A single previously declared <literal><link linkend="type">type</link></literal>, <literal><link linkend="typealias">typealias</link></literal> or <literal><link linkend="typeattribute">typeattribute</link></literal> identifier.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>target_type_id</literal></para>
+ </entry>
+ <entry>
+ <para>A single previously declared <literal><link linkend="type">type</link></literal>, <literal><link linkend="typealias">typealias</link></literal> or <literal><link linkend="typeattribute">typeattribute</link></literal> identifier.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>class_id</literal></para>
+ </entry>
+ <entry>
+ <para>A single previously declared <literal><link linkend="class">class</link></literal> or <literal><link linkend="classmap">classmap</link></literal> identifier.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>change_type_id</literal></para>
+ </entry>
+ <entry>
+ <para>A single previously declared <literal><link linkend="type">type</link></literal> or <literal><link linkend="typealias">typealias</link></literal> identifier that will become the new type.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+ <para><emphasis role="bold">Example:</emphasis></para>
+ <para>Whenever <emphasis role="bold"><literal>security_compute_relabel</literal></emphasis><literal>(3)</literal> is called with the following parameters:</para>
+ <simpara><literal> scon=unconfined.object tcon=unconfined.object class=file</literal></simpara>
+ <simpara>the function will return a context of:</simpara>
+ <simpara><literal> unconfined.object:object_r:unconfined.change_label:s0</literal></simpara>
+ <programlisting><![CDATA[
+(class file (getattr read write))
+
+(block unconfined
+ (type process)
+ (type object)
+ (type change_label)
+
+ (typechange object object file change_label)
+)]]>
+ </programlisting>
+ </sect2>
+
+ <sect2 id="typemember">
+ <title>typemember</title>
+ <para>The type member rule is used to define a new polyinstantiated label of an object for SELinux-aware applications. These applications would use <emphasis role="bold"><literal>avc_compute_member</literal></emphasis><literal>(3)</literal> or <emphasis role="bold"><literal>security_compute_member</literal></emphasis><literal>(3)</literal> with the <literal>typemember</literal> rules in the policy to determine the context to be applied. The application would then manage any required polyinstantiation. Note that an <literal><link linkend="allow">allow</link></literal> rule must be used to authorise the membership.</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(typemember source_type_id target_type_id class_id member_type_id)]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>typemember</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>typemember</literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>source_type_id</literal></para>
+ </entry>
+ <entry>
+ <para>A single previously declared <literal><link linkend="type">type</link></literal>, <literal><link linkend="typealias">typealias</link></literal> or <literal><link linkend="typeattribute">typeattribute</link></literal> identifier.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>target_type_id</literal></para>
+ </entry>
+ <entry>
+ <para>A single previously declared <literal><link linkend="type">type</link></literal>, <literal><link linkend="typealias">typealias</link></literal> or <literal><link linkend="typeattribute">typeattribute</link></literal> identifier.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>class_id</literal></para>
+ </entry>
+ <entry>
+ <para>A single previously declared <literal><link linkend="class">class</link></literal> or <literal><link linkend="classmap">classmap</link></literal> identifier.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>member_type_id</literal></para>
+ </entry>
+ <entry>
+ <para>A single previously declared <literal><link linkend="type">type</link></literal> or <literal><link linkend="typealias">typealias</link></literal> identifier that will become the new member type.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+ <para><emphasis role="bold">Example:</emphasis></para>
+ <para>Whenever <emphasis role="bold"><literal>avc_compute_member</literal></emphasis><literal>(3)</literal> or <emphasis role="bold"><literal>security_compute_member</literal></emphasis><literal>(3)</literal> is called with the following parameters:</para>
+ <simpara><literal> scon=unconfined.object tcon=unconfined.object class=file</literal></simpara>
+ <simpara>the function will return a context of:</simpara>
+ <simpara><literal> unconfined.object:object_r:unconfined.member_label:s0</literal></simpara>
+ <programlisting><![CDATA[
+(class file (getattr read write))
+
+(block unconfined
+ (type process)
+ (type object)
+ (type change_label)
+
+ (typemember object object file member_label)
+)]]>
+ </programlisting>
+ </sect2>
+
+ <sect2 id="typetransition">
+ <title>typetransition</title>
+ <para>The type transition rule specifies the labeling and object creation allowed between the <literal>source_type</literal> and <literal>target</literal>_type when a domain transition is requested. Kernels from 2.6.39 with policy versions from 25 and above also support a 'name transition' rule, however this is not allowed inside conditionals and currently only supports the file classes. Note that an <literal><link linkend="allow">allow</link></literal> rule must be used to authorise the transition.</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(typetransition source_type_id target_type_id class_id [object_name] default_type_id)]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>typetransition</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>typetransition</literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>source_type_id</literal></para>
+ </entry>
+ <entry>
+ <para>A single previously declared <literal><link linkend="type">type</link></literal>, <literal><link linkend="typealias">typealias</link></literal> or <literal><link linkend="typeattribute">typeattribute</link></literal> identifier.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>target_type_id</literal></para>
+ </entry>
+ <entry>
+ <para>A single previously declared <literal><link linkend="type">type</link></literal>, <literal><link linkend="typealias">typealias</link></literal> or <literal><link linkend="typeattribute">typeattribute</link></literal> identifier.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>class_id</literal></para>
+ </entry>
+ <entry>
+ <para>A single previously declared <literal><link linkend="class">class</link></literal> or <literal><link linkend="classmap">classmap</link></literal> identifier.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>object_name</literal></para>
+ </entry>
+ <entry>
+ <para>A optional string within double quotes representing an object name for the 'name transition' rule. This string will be matched against the objects name (if a path then the last component of that path). If the string matches exactly, the <literal>default_type_id</literal> will then become the new type.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>default_type_id</literal></para>
+ </entry>
+ <entry>
+ <para>A single previously declared <literal><link linkend="type">type</link></literal> or <literal><link linkend="typealias">typealias</link></literal> identifier that will become the new type.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+
+ <para><emphasis role="bold">Examples:</emphasis></para>
+ <para>This example shows a process transition rule with its supporting <literal><link linkend="allow">allow</link></literal> rule:</para>
+ <programlisting><![CDATA[
+(macro domain_auto_trans ((type ARG1) (type ARG2) (type ARG3))
+ ; Allow the necessary permissions.
+ (call domain_trans (ARG1 ARG2 ARG3))
+ ; Make the transition occur by default.
+ (typetransition ARG1 ARG2 process ARG3)
+)]]>
+ </programlisting>
+
+ <para>This example shows a file object transition rule with its supporting <literal><link linkend="allow">allow</link></literal> rule:</para>
+ <programlisting><![CDATA[
+(macro tmpfs_domain ((type ARG1))
+ (type tmpfs)
+ (typeattributeset file_type (tmpfs))
+ (typetransition ARG1 file.tmpfs file tmpfs)
+ (allow ARG1 tmpfs (file (read write execute execmod)))
+)]]>
+ </programlisting>
+
+ <para>This example shows the 'name transition' rule with its supporting <literal><link linkend="allow">allow</link></literal> rule:</para>
+ <programlisting><![CDATA[
+(macro write_klog ((type ARG1))
+ (typetransition ARG1 device.device chr_file "__kmsg__" device.klog_device)
+ (allow ARG1 device.klog_device (chr_file (create open write unlink)))
+ (allow ARG1 device.device (dir (write add_name remove_name)))
+)]]>
+ </programlisting>
+
+ </sect2>
+
+ <sect2 id="typepermissive">
+ <title>typepermissive</title>
+ <para>Policy database version 23 introduced the permissive statement to allow the named domain to run in permissive mode instead of running all SELinux domains in permissive mode (that was the only option prior to version 23). Note that the permissive statement only tests the source context for any policy denial.</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(typepermissive source_type_id)]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>typepermissive</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>typepermissive</literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>source_type_id</literal></para>
+ </entry>
+ <entry>
+ <para>A single previously declared <literal><link linkend="type">type</link></literal> or <literal><link linkend="typealias">typealias</link></literal> identifier.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+ <para><emphasis role="bold">Example:</emphasis></para>
+ <para>This example will allow SELinux to run the <literal>healthd.process</literal> domain in permissive mode even when enforcing is enabled:</para>
+ <programlisting><![CDATA[
+(block healthd
+ (type process)
+ (typepermissive process)
+
+ (allow ...)
+)]]>
+ </programlisting>
+ </sect2>
+
+ </sect1>
diff --git a/cil/docs/cil_user_statements.xml b/cil/docs/cil_user_statements.xml
new file mode 100644
index 0000000..9fa1a51
--- /dev/null
+++ b/cil/docs/cil_user_statements.xml
@@ -0,0 +1,420 @@
+<!-- Common Interface Language (CIL) Reference Guide -->
+ <!-- user_statements.xml -->
+
+ <sect1>
+ <title>User Statements</title>
+ <sect2 id="user">
+ <title>user</title>
+ <para>Declares an SELinux user identifier in the current namespace.</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(user user_id)]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>user</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>user</literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>user_id</literal></para>
+ </entry>
+ <entry>
+ <para>The SELinux <literal>user</literal> identifier.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+
+ <para><emphasis role="bold">Example:</emphasis></para>
+ <para>This will declare an SELinux user as <literal>unconfined.user</literal>:</para>
+ <programlisting><![CDATA[
+(block unconfined
+ (user user)
+)]]>
+ </programlisting>
+ </sect2>
+
+ <sect2 id="userrole">
+ <title>userrole</title>
+ <para>Associates a previously declared <literal><link linkend="user">user</link></literal> identifier with a previously declared <literal><link linkend="role">role</link></literal> identifier.</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(userrole user_id role_id)]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>userrole</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>userrole</literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>user_id</literal></para>
+ </entry>
+ <entry>
+ <para>A previously declared SELinux <literal><link linkend="user">user</link></literal> identifier.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>role_id</literal></para>
+ </entry>
+ <entry>
+ <para>A previously declared <literal><link linkend="role">role</link></literal> or <literal><link linkend="roleattribute">roleattribute</link></literal> identifier.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+
+ <para><emphasis role="bold">Example:</emphasis></para>
+ <para>This example will associate <literal>unconfined.user</literal> to <literal>unconfined.role</literal>:</para>
+ <programlisting><![CDATA[
+(block unconfined
+ (user user)
+ (role role)
+ (userrole user role)
+)]]>
+ </programlisting>
+ </sect2>
+
+ <sect2 id="userlevel">
+ <title>userlevel</title>
+ <para>Associates a previously declared <literal><link linkend="user">user</link></literal> identifier with a previously declared <literal><link linkend="level">level</link></literal> identifier. The <literal><link linkend="level">level</link></literal> may be named or anonymous.</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(userlevel user_id level_id)]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>userlevel</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>userlevel</literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>user_id</literal></para>
+ </entry>
+ <entry>
+ <para>A previously declared SELinux <literal><link linkend="user">user</link></literal> identifier.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>level_id</literal></para>
+ </entry>
+ <entry>
+ <para>A previously declared <literal><link linkend="level">level</link></literal> identifier. This may consist of a single <literal><link linkend="sensitivity">sensitivity</link></literal> with zero or more mixed named and anonymous <literal><link linkend="category">category</link></literal>'s as discussed in the <literal><link linkend="level">level</link></literal> statement.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+
+ <para><emphasis role="bold">Example:</emphasis></para>
+ <para>This example will associate <literal>unconfined.user</literal> with a named <literal><link linkend="level">level</link></literal> of <literal>systemlow</literal>:</para>
+ <programlisting><![CDATA[
+(sensitivity s0)
+(level systemlow (s0))
+
+(block unconfined
+ (user user)
+ (userlevel user systemlow)
+ ; An anonymous example:
+ ;(userlevel user (s0))
+)]]>
+ </programlisting>
+ </sect2>
+
+ <sect2 id="userrange">
+ <title>userrange</title>
+ <para>Associates a previously declared <literal><link linkend="user">user</link></literal> identifer with a previously declared <literal><link linkend="levelrange">levelrange</link></literal> identifier. The <literal><link linkend="levelrange">levelrange</link></literal> may be named or anonymous.</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(userrange user_id levelrange_id)]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>userrange</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>userrange</literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>user_id</literal></para>
+ </entry>
+ <entry>
+ <para>A previously declared SELinux <literal><link linkend="user">user</link></literal> identifier.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>levelrange_id</literal></para>
+ </entry>
+ <entry>
+ <para>A previously declared <literal><link linkend="levelrange">levelrange</link></literal> identifier. This may be formed by named or anonymous components as discussed in the <literal><link linkend="levelrange">levelrange</link></literal> statement and shown in the examples.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+
+ <para><emphasis role="bold">Example:</emphasis></para>
+ <para>This example will associate <literal>unconfined.user</literal> with a named <literal><link linkend="levelrange">levelrange</link></literal> of <literal>low_high</literal>, other anonymous examples are also shown:</para>
+ <programlisting><![CDATA[
+(category c0)
+(category c1)
+(categoryorder (c0 c1))
+(sensitivity s0)
+(sensitivity s1)
+(dominance (s0 s1))
+(sensitivitycategory s0 (c0 c1))
+(level systemLow (s0))
+(level systemHigh (s0 (c0 c1)))
+(levelrange low_high (systemLow systemHigh))
+
+(block unconfined
+ (user user)
+ (role role)
+ (userrole user role)
+ ; Named example:
+ (userrange user low_high)
+ ; Anonymous examples:
+ ;(userrange user (systemLow systemHigh))
+ ;(userrange user (systemLow (s0 (c0 c1))))
+ ;(userrange user ((s0) (s0 (c0 c1))))
+)]]>
+ </programlisting>
+ </sect2>
+
+ <sect2 id="userbounds">
+ <title>userbounds</title>
+ <para>Defines a hierarchical relationship between users where the child user cannot have more priviledges than the parent.</para>
+ <para>Notes:</para>
+ <itemizedlist>
+ <listitem><para>It is not possible to bind the parent to more than one child.</para></listitem>
+ <listitem><para>While this is added to the binary policy, it is not enforced by the SELinux kernel services.</para></listitem>
+ </itemizedlist>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(userbounds parent_user_id child_user_id)]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>userbounds</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>userbounds</literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>parent_user_id</literal></para>
+ </entry>
+ <entry>
+ <para>A previously declared SELinux <literal><link linkend="user">user</link></literal> identifier.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>child_user_id</literal></para>
+ </entry>
+ <entry>
+ <para>A previously declared SELinux <literal><link linkend="user">user</link></literal> identifier.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+
+ <para><emphasis role="bold">Example:</emphasis></para>
+ <para>The user <literal>test</literal> cannot have greater priviledges than <literal>unconfined.user</literal>:</para>
+ <programlisting><![CDATA[
+(user test)
+
+(unconfined
+ (user user)
+ (userbounds user .test)
+)]]>
+ </programlisting>
+ </sect2>
+
+ <sect2 id="userprefix">
+ <title>userprefix</title>
+ <para>Declare a user prefix that will be replaced by the file labeling utilities described at <ulink url="http://selinuxproject.org/page/PolicyStoreConfigurationFiles#file_contexts.template_File">http://selinuxproject.org/page/PolicyStoreConfigurationFiles</ulink> that details the <filename>file_contexts</filename> entries.</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(userprefix user_id prefix)]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>userprefix</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>userprefix</literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>user_id</literal></para>
+ </entry>
+ <entry>
+ <para>A previously declared SELinux <literal><link linkend="user">user</link></literal> identifier.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>prefix</literal></para>
+ </entry>
+ <entry>
+ <para>The string to be used by the file labeling utilities.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+
+ <para><emphasis role="bold">Example:</emphasis></para>
+ <para>This example will associate <literal>unconfined.admin</literal> user with a prefix of "<literal>user</literal>":</para>
+ <programlisting><![CDATA[
+(block unconfined
+ (user admin
+ (userprefix admin user)
+)]]>
+ </programlisting>
+ </sect2>
+
+ <sect2 id="selinuxuser">
+ <title>selinuxuser</title>
+ <para>Associates a GNU/Linux user to a previously declared <literal><link linkend="user">user</link></literal> identifier with a previously declared MLS <literal><link linkend="userrange">userrange</link></literal>. Note that the <literal><link linkend="userrange">userrange</link></literal> is required even if the policy is non-MCS/MLS.</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(selinuxuser user_name user_id userrange_id)]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>selinuxuser</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>selinuxuser</literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>user_name</literal></para>
+ </entry>
+ <entry>
+ <para>A string representing the GNU/Linux user name</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>user_id</literal></para>
+ </entry>
+ <entry>
+ <para>A previously declared SELinux <literal><link linkend="user">user</link></literal> identifier.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>userrange_id</literal></para>
+ </entry>
+ <entry>
+ <para>A previously declared <literal><link linkend="userrange">userrange</link></literal> identifier that has been associated to the <literal>user</literal> identifier. This may be formed by named or anonymous components as discussed in the <literal><link linkend="userrange">userrange</link></literal> statement and shown in the examples.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+
+ <para><emphasis role="bold">Example:</emphasis></para>
+ <para>This example will associate <literal>unconfined.admin</literal> user with a GNU / Linux user "<literal>admin_1</literal>":</para>
+ <programlisting><![CDATA[
+(block unconfined
+ (user admin)
+ (selinuxuser admin_1 admin low_low)
+)]]>
+ </programlisting>
+ </sect2>
+
+ <sect2 id="selinuxuserdefault">
+ <title>selinuxuserdefault</title>
+ <para>Declares the default SELinux user. Only one <literal>selinuxuserdefault</literal> statement is allowed in the policy. Note that the <literal><link linkend="userrange">userrange</link></literal> identifier is required even if the policy is non-MCS/MLS.</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(selinuxuserdefault user_id userrange_id)]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>selinuxuserdefault</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>selinuxuserdefault</literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>user_id</literal></para>
+ </entry>
+ <entry>
+ <para>A previously declared SELinux <literal><link linkend="user">user</link></literal> identifier.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>userrange_id</literal></para>
+ </entry>
+ <entry>
+ <para>A previously declared <literal><link linkend="userrange">userrange</link></literal> identifier that has been associated to the <literal><link linkend="user">user</link></literal> identifier. This may be formed by named or anonymous components as discussed in the <literal><link linkend="userrange">userrange</link></literal> statement and shown in the examples.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+
+ <para><emphasis role="bold">Example:</emphasis></para>
+ <para>This example will define the <literal>unconfined.user</literal> as the default SELinux user:</para>
+ <programlisting><![CDATA[
+(block unconfined
+ (user user)
+ (selinuxuserdefault user low_low)
+)]]>
+ </programlisting>
+ </sect2>
+
+ </sect1>
diff --git a/cil/docs/cil_xen_statements.xml b/cil/docs/cil_xen_statements.xml
new file mode 100644
index 0000000..1035b68
--- /dev/null
+++ b/cil/docs/cil_xen_statements.xml
@@ -0,0 +1,183 @@
+<!-- Common Interface Language (CIL) Reference Guide -->
+ <!-- xen_statements.xml -->
+
+ <sect1>
+ <title>Xen Statements</title>
+ <para>See the <ulink url="http://xenbits.xen.org/docs/4.2-testing/misc/xsm-flask.txt">"XSM/FLASK Configuration"</ulink> document for further information (<ulink url="http://xenbits.xen.org/docs/4.2-testing/misc/xsm-flask.txt"></ulink>)</para>
+ <sect2 id="iomemcon">
+ <title>iomemcon</title>
+ <para>Label i/o memory. This may be a single memory location or a range.</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(iomemcon mem_addr|(mem_low mem_high) context_id)]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>iomemcon</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>iomemcon</literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>mem_addr |</literal></para>
+ <para><literal>(mem_low mem_high)</literal></para>
+ </entry>
+ <entry>
+ <para>A single memory address to apply the context, or a range of addresses.</para>
+ <para>The entries must consist of numerics <literal>[0-9]</literal>.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>context_id</literal></para>
+ </entry>
+ <entry>
+ <para>A previously declared <literal><link linkend="context">context</link></literal> identifier or an anonymous security context (<literal><link linkend="user">user</link> <link linkend="role">role</link> <link linkend="type">type</link> <link linkend="levelrange">levelrange</link></literal>), the range MUST be defined whether the policy is MLS/MCS enabled or not.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+
+ <para><emphasis role="bold">Example:</emphasis></para>
+ <para>An anonymous context for a memory address range of <literal>0xfebe0-0xfebff</literal>:</para>
+ <programlisting><![CDATA[(iomemcon (1043424 1043455) (unconfined.user object_r unconfined.object low_low))]]></programlisting>
+ </sect2>
+
+ <sect2 id="ioportcon">
+ <title>ioportcon</title>
+ <para>Label i/o ports. This may be a single port or a range.</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(ioportcon port|(port_low port_high) context_id)]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2.25 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>ioportcon</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>ioportcon</literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>port |</literal></para>
+ <para><literal>(port_low port_high)</literal></para>
+ </entry>
+ <entry>
+ <para>A single port to apply the context, or a range of ports.</para>
+ <para>The entries must consist of numerics <literal>[0-9]</literal>.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>context_id</literal></para>
+ </entry>
+ <entry>
+ <para>A previously declared <literal><link linkend="context">context</link></literal> identifier or an anonymous security context (<literal><link linkend="user">user</link> <link linkend="role">role</link> <link linkend="type">type</link> <link linkend="levelrange">levelrange</link></literal>), the range MUST be defined whether the policy is MLS/MCS enabled or not.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+
+ <para><emphasis role="bold">Example:</emphasis></para>
+ <para>An anonymous context for a single port of :<literal>0xecc0</literal>:</para>
+ <programlisting><![CDATA[(ioportcon 60608 (unconfined.user object_r unconfined.object low_low))]]></programlisting>
+ </sect2>
+
+ <sect2 id="pcidevicecon">
+ <title>pcidevicecon</title>
+ <para>Label a PCI device.</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(pcidevicecon device context_id)]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>pcidevicecon</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>pcidevicecon</literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>device</literal></para>
+ </entry>
+ <entry>
+ <para>The device number.The entries must consist of numerics <literal>[0-9]</literal>.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>context_id</literal></para>
+ </entry>
+ <entry>
+ <para>A previously declared <literal><link linkend="context">context</link></literal> identifier or an anonymous security context (<literal><link linkend="user">user</link> <link linkend="role">role</link> <link linkend="type">type</link> <link linkend="levelrange">levelrange</link></literal>), the range MUST be defined whether the policy is MLS/MCS enabled or not.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+
+ <para><emphasis role="bold">Example:</emphasis></para>
+ <para>An anonymous context for a pci device address of <literal>0xc800</literal>:</para>
+ <programlisting><![CDATA[(pcidevicecon 51200 (unconfined.user object_r unconfined.object low_low))]]></programlisting>
+ </sect2>
+
+ <sect2 id="pirqcon">
+ <title>pirqcon</title>
+ <para>Label an interrupt level.</para>
+ <para><emphasis role="bold">Statement definition:</emphasis></para>
+ <programlisting><![CDATA[(pirqcon irq_level context_id)]]></programlisting>
+ <para><emphasis role="bold">Where:</emphasis></para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colwidth="2 *"/>
+ <colspec colwidth="6 *"/>
+ <tbody>
+ <row>
+ <entry>
+ <para><literal>pirqcon</literal></para>
+ </entry>
+ <entry>
+ <para>The <literal>pirqcon</literal> keyword.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>irq_level</literal></para>
+ </entry>
+ <entry>
+ <para>The interrupt request number. The entries must consist of numerics <literal>[0-9]</literal>.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para><literal>context_id</literal></para>
+ </entry>
+ <entry>
+ <para>A previously declared <literal><link linkend="context">context</link></literal> identifier or an anonymous security context (<literal><link linkend="user">user</link> <link linkend="role">role</link> <link linkend="type">type</link> <link linkend="levelrange">levelrange</link></literal>), the range MUST be defined whether the policy is MLS/MCS enabled or not.</para>
+ </entry>
+ </row>
+ </tbody></tgroup>
+ </informaltable>
+
+ <para><emphasis role="bold">Example:</emphasis></para>
+ <para>An anonymous context for IRQ 33:</para>
+ <programlisting><![CDATA[(pirqcon 33 (unconfined.user object_r unconfined.object low_low))]]></programlisting>
+ </sect2>
+
+ </sect1>
diff --git a/cil/docs/secilc.8.xml b/cil/docs/secilc.8.xml
new file mode 100644
index 0000000..12d72b7
--- /dev/null
+++ b/cil/docs/secilc.8.xml
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<refentry>
+ <refentryinfo>
+ <author>
+ <firstname>Richard</firstname><surname>Haines</surname><contrib></contrib>
+ </author>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>SECILC</refentrytitle>
+ <manvolnum>8</manvolnum>
+ <refmiscinfo class="date">12 May 2014</refmiscinfo>
+ <refmiscinfo class="source">secilc</refmiscinfo>
+ <refmiscinfo class="manual">SELinux CIL Compiler</refmiscinfo>
+ </refmeta>
+ <refnamediv id="name">
+ <refname>secilc</refname>
+ <refpurpose>invoke the SELinux Common Intermediate Language (CIL) Compiler</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv id="synopsis">
+ <cmdsynopsis>
+ <command>secilc</command>
+ <arg choice="opt" rep="repeat"><replaceable>OPTION</replaceable></arg>
+ <arg choice="plain"><replaceable>file</replaceable></arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1 id="description"><title>DESCRIPTION</title>
+ <para><emphasis role="italic">secilc</emphasis> invokes the CIL compiler with the specified <emphasis role="italic">argument</emphasis>s to build a kernel binary policy. A <emphasis role="bold">file_contexts</emphasis> file will also be built as described in the <emphasis role="bold">FILE FORMAT</emphasis> section of <citerefentry><refentrytitle>file_contexts</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
+ </refsect1>
+
+ <refsect1 id="options"><title>OPTIONS</title>
+ <para><option>-o, --output=&lt;file></option></para>
+ <para>Write binary policy to <emphasis role="italic">file</emphasis> (default: policy.<emphasis role="italic">version</emphasis>)</para>
+
+ <para><option>-f, --filecontext=&lt;file></option></para>
+ <para>Write file contexts to <emphasis role="italic">file</emphasis> (default: <emphasis role="bold">file_contexts</emphasis>)</para>
+
+ <para><option>-t, --target=&lt;type></option></para>
+ <para>Specify target architecture. May be <emphasis role="bold">selinux</emphasis> or <emphasis role="bold">xen</emphasis> (default: <emphasis role="bold">selinux</emphasis>)</para>
+
+ <para><option>-M, --mls true|false</option></para>
+ <para>Build an mls policy. Must be <emphasis role="bold">true</emphasis> or <emphasis role="bold">false</emphasis>. This will override the <emphasis role="bold">(mls <emphasis role="italic">boolean</emphasis></emphasis><emphasis role="bold">)</emphasis> statement if present in the policy.</para>
+
+ <para><option>-c, --policyvers=&lt;version></option></para>
+ <para>Build a binary policy with a given <emphasis role="italic">version</emphasis> (default: depends on the systems SELinux policy <emphasis role="italic">version</emphasis>, see <citerefentry><refentrytitle>sestatus</refentrytitle><manvolnum>8</manvolnum></citerefentry>)</para>
+
+ <para><option>-U, --handle-unknown=&lt;action></option></para>
+ <para>How to handle unknown classes or permissions. May be <emphasis role="bold">deny</emphasis>, <emphasis role="bold">allow</emphasis>, or <emphasis role="bold">reject</emphasis> (default: <emphasis role="bold">deny</emphasis>). This will override the <emphasis role="bold">(handleunknown <emphasis role="italic">action</emphasis></emphasis><emphasis role="bold">)</emphasis> statement if present in the policy.</para>
+
+ <para><option>-D, --disable-dontaudit</option></para>
+ <para>Do not add <emphasis role="bold">dontaudit</emphasis> rules to the binary policy.</para>
+
+ <para><option>-P, --preserve-tunables</option></para>
+ <para>Treat tunables as booleans.</para>
+
+ <para><option>-N, --disable-neverallow</option></para>
+ <para>Do not check <emphasis role="bold">neverallow</emphasis> rules.</para>
+
+ <para><option>-v, --verbose</option></para>
+ <para>Increment verbosity level.</para>
+
+ <para><option>-h, --help</option></para>
+ <para>Display usage information.</para>
+ </refsect1>
+
+ <refsect1 id="see_also"><title>SEE ALSO</title>
+ <para>
+ <simplelist type="inline">
+ <member><citerefentry>
+ <refentrytitle>file_contexts</refentrytitle>
+ <manvolnum>5</manvolnum>
+ </citerefentry></member>
+ <member><citerefentry>
+ <refentrytitle>sestatus</refentrytitle>
+ <manvolnum>8</manvolnum>
+ </citerefentry></member>
+ </simplelist>
+ </para>
+ <para>HTML documentation describing the CIL language statements is available starting with <emphasis role="italic">docs/html/index.html</emphasis>.</para>
+ <para>PDF documentation describing the CIL language statements is available at: <emphasis role="italic">docs/pdf/CIL_Reference_Guide.pdf</emphasis>.</para>
+ <para>There is a CIL Design Wiki at: <ulink url="http://userspace.selinuxproject.org/trac/wiki/CilDesign"></ulink> that describes the goals and features of the CIL language.</para>
+ </refsect1>
+</refentry>
+
diff --git a/cil/include/cil/cil.h b/cil/include/cil/cil.h
new file mode 100644
index 0000000..902ca3e
--- /dev/null
+++ b/cil/include/cil/cil.h
@@ -0,0 +1,69 @@
+/*
+ * 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 <sepol/policydb/policydb.h>
+
+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, sepol_policydb_t *sepol_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, sepol_policydb_t *sepol_db, char **out, size_t *size);
+extern int cil_selinuxusers_to_string(cil_db_t *db, sepol_policydb_t *sepol_db, char **out, size_t *size);
+extern int cil_filecons_to_string(cil_db_t *db, sepol_policydb_t *sepol_db, char **out, size_t *size);
+extern void cil_set_disable_dontaudit(cil_db_t *db, int disable_dontaudit);
+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);
+
+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));
+
+#endif
diff --git a/cil/secilc.c b/cil/secilc.c
new file mode 100644
index 0000000..8f16c98
--- /dev/null
+++ b/cil/secilc.c
@@ -0,0 +1,353 @@
+/*
+ * 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 <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <getopt.h>
+#include <sys/stat.h>
+
+#include <cil/cil.h>
+#include <sepol/policydb.h>
+
+void usage(char *prog)
+{
+ printf("Usage: %s [OPTION]... FILE...\n", prog);
+ printf("\n");
+ printf("Options:\n");
+ printf(" -o, --output=<file> write binary policy to <file>\n");
+ printf(" (default: policy.<version>)\n");
+ printf(" -f, --filecontext=<file> write file contexts to <file>\n");
+ printf(" (default: file_contexts)\n");
+ printf(" -t, --target=<type> specify target architecture. may be selinux or\n");
+ printf(" xen. (default: selinux)\n");
+ printf(" -M, --mls true|false build an mls policy. Must be true or false.\n");
+ printf(" This will override the (mls boolean) statement\n");
+ printf(" if present in the policy\n");
+ printf(" -c, --policyvers=<version> build a binary policy with a given <version>\n");
+ printf(" (default: %i)\n", POLICYDB_VERSION_MAX);
+ printf(" -U, --handle-unknown=<action> how to handle unknown classes or permissions.\n");
+ printf(" may be deny, allow, or reject. (default: deny)\n");
+ printf(" This will override the (handleunknown action)\n");
+ printf(" statement if present in the policy\n");
+ printf(" -D, --disable-dontaudit do not add dontaudit rules to the binary policy\n");
+ printf(" -P, --preserve-tunables treat tunables as booleans\n");
+ printf(" -N, --disable-neverallow do not check neverallow rules\n");
+ printf(" -v, --verbose increment verbosity level\n");
+ printf(" -h, --help display usage information\n");
+ exit(1);
+}
+
+int main(int argc, char *argv[])
+{
+ int rc = SEPOL_ERR;
+ sepol_policydb_t *pdb = NULL;
+ struct sepol_policy_file *pf = NULL;
+ FILE *binary = NULL;
+ FILE *file_contexts;
+ FILE *file = NULL;
+ char *buffer = NULL;
+ struct stat filedata;
+ uint32_t file_size;
+ char *output = NULL;
+ char *filecontexts = NULL;
+ struct cil_db *db = NULL;
+ int target = SEPOL_TARGET_SELINUX;
+ int mls = -1;
+ int disable_dontaudit = 0;
+ int disable_neverallow = 0;
+ int preserve_tunables = 0;
+ int handle_unknown = -1;
+ int policyvers = POLICYDB_VERSION_MAX;
+ int opt_char;
+ int opt_index = 0;
+ char *fc_buf = NULL;
+ size_t fc_size;
+ enum cil_log_level log_level = CIL_ERR;
+ static struct option long_opts[] = {
+ {"help", no_argument, 0, 'h'},
+ {"verbose", no_argument, 0, 'v'},
+ {"target", required_argument, 0, 't'},
+ {"mls", required_argument, 0, 'M'},
+ {"policyversion", required_argument, 0, 'c'},
+ {"handle-unknown", required_argument, 0, 'U'},
+ {"disable-dontaudit", no_argument, 0, 'D'},
+ {"disable-neverallow", no_argument, 0, 'N'},
+ {"preserve-tunables", no_argument, 0, 'P'},
+ {"output", required_argument, 0, 'o'},
+ {"filecontexts", required_argument, 0, 'f'},
+ {0, 0, 0, 0}
+ };
+ int i;
+
+ while (1) {
+ opt_char = getopt_long(argc, argv, "o:f:U:hvt:M:PDNc:", long_opts, &opt_index);
+ if (opt_char == -1) {
+ break;
+ }
+ switch (opt_char) {
+ case 'v':
+ log_level++;
+ break;
+ case 't':
+ if (!strcmp(optarg, "selinux")) {
+ target = SEPOL_TARGET_SELINUX;
+ } else if (!strcmp(optarg, "xen")) {
+ target = SEPOL_TARGET_XEN;
+ } else {
+ fprintf(stderr, "Unknown target: %s\n", optarg);
+ usage(argv[0]);
+ }
+ break;
+ case 'M':
+ if (!strcasecmp(optarg, "true") || !strcasecmp(optarg, "1")) {
+ mls = 1;
+ } else if (!strcasecmp(optarg, "false") || !strcasecmp(optarg, "0")) {
+ mls = 0;
+ } else {
+ usage(argv[0]);
+ }
+ break;
+ case 'c': {
+ char *endptr = NULL;
+ errno = 0;
+ policyvers = strtol(optarg, &endptr, 10);
+ if (errno != 0 || endptr == optarg || *endptr != '\0') {
+ fprintf(stderr, "Bad policy version: %s\n", optarg);
+ usage(argv[0]);
+ }
+ if (policyvers > POLICYDB_VERSION_MAX || policyvers < POLICYDB_VERSION_MIN) {
+ fprintf(stderr, "Policy version must be between %d and %d\n",
+ POLICYDB_VERSION_MIN, POLICYDB_VERSION_MAX);
+ usage(argv[0]);
+ }
+ break;
+ }
+ case 'U':
+ if (!strcasecmp(optarg, "deny")) {
+ handle_unknown = SEPOL_DENY_UNKNOWN;
+ } else if (!strcasecmp(optarg, "allow")) {
+ handle_unknown = SEPOL_ALLOW_UNKNOWN;
+ } else if (!strcasecmp(optarg, "reject")) {
+ handle_unknown = SEPOL_REJECT_UNKNOWN;
+ } else {
+ usage(argv[0]);
+ }
+ break;
+ case 'D':
+ disable_dontaudit = 1;
+ break;
+ case 'N':
+ disable_neverallow = 1;
+ break;
+ case 'P':
+ preserve_tunables = 1;
+ break;
+ case 'o':
+ output = strdup(optarg);
+ break;
+ case 'f':
+ filecontexts = strdup(optarg);
+ break;
+ case 'h':
+ usage(argv[0]);
+ case '?':
+ break;
+ default:
+ fprintf(stderr, "Unsupported option: %s\n", optarg);
+ usage(argv[0]);
+ }
+ }
+ if (optind >= argc) {
+ fprintf(stderr, "No cil files specified\n");
+ usage(argv[0]);
+ }
+
+ cil_set_log_level(log_level);
+
+ cil_db_init(&db);
+ cil_set_disable_dontaudit(db, disable_dontaudit);
+ cil_set_disable_neverallow(db, disable_neverallow);
+ cil_set_preserve_tunables(db, preserve_tunables);
+ if (handle_unknown != -1) {
+ rc = cil_set_handle_unknown(db, handle_unknown);
+ if (rc != SEPOL_OK) {
+ goto exit;
+ }
+ }
+
+ cil_set_mls(db, mls);
+
+ for (i = optind; i < argc; i++) {
+ file = fopen(argv[i], "r");
+ if (!file) {
+ cil_log(CIL_ERR, "Could not open file: %s\n", argv[i]);
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+ rc = stat(argv[i], &filedata);
+ if (rc == -1) {
+ cil_log(CIL_ERR, "Could not stat file: %s\n", argv[i]);
+ goto exit;
+ }
+ file_size = filedata.st_size;
+
+ buffer = malloc(file_size);
+ rc = fread(buffer, file_size, 1, file);
+ if (rc != 1) {
+ cil_log(CIL_ERR, "Failure reading file: %s\n", argv[i]);
+ goto exit;
+ }
+ fclose(file);
+ file = NULL;
+
+ rc = cil_add_file(db, argv[i], buffer, file_size);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_ERR, "Failure adding %s\n", argv[i]);
+ goto exit;
+ }
+
+ free(buffer);
+ buffer = NULL;
+ }
+
+ rc = sepol_policydb_create(&pdb);
+ if (rc < 0) {
+ cil_log(CIL_ERR, "Failed to create policy db\n");
+ goto exit;
+ }
+ pdb->p.policy_type = POLICY_KERN;
+ pdb->p.target_platform = target;
+
+ rc = sepol_policydb_set_vers(pdb, policyvers);
+ if (rc != 0) {
+ cil_log(CIL_ERR, "Failed to set policy version: %d\n", rc);
+ goto exit;
+ }
+ rc = cil_compile(db, pdb);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_ERR, "Failed to compile cildb: %d\n", rc);
+ goto exit;
+ }
+
+ rc = cil_build_policydb(db, pdb);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_ERR, "Failed to build policydb\n");
+ goto exit;
+ }
+
+ if (output == NULL) {
+ int size = snprintf(NULL, 0, "policy.%d", policyvers);
+ output = malloc((size + 1) * sizeof(char));
+ if (output == NULL) {
+ cil_log(CIL_ERR, "Failed to create output filename\n");
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+ if (snprintf(output, size + 1, "policy.%d", policyvers) != size) {
+ cil_log(CIL_ERR, "Failed to create output filename\n");
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+ }
+
+ cil_log(CIL_INFO, "Writing binary to %s\n", output);
+
+ binary = fopen(output, "w");
+ if (binary == NULL) {
+ cil_log(CIL_ERR, "Failure opening binary file for writing\n");
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+
+ rc = sepol_policy_file_create(&pf);
+ if (rc != 0) {
+ cil_log(CIL_ERR, "Failed to create policy file: %d\n", rc);
+ goto exit;
+ }
+
+ sepol_policy_file_set_fp(pf, binary);
+
+ rc = sepol_policydb_write(pdb, pf);
+ if (rc != 0) {
+ cil_log(CIL_ERR, "Failed to write binary policy: %d\n", rc);
+ goto exit;
+ }
+
+ fclose(binary);
+ binary = NULL;
+
+ cil_log(CIL_INFO, "Writing file contexts\n");
+
+ rc = cil_filecons_to_string(db, pdb, &fc_buf, &fc_size);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_ERR, "Failed to get file context data\n");
+ goto exit;
+ }
+
+ if (filecontexts == NULL) {
+ file_contexts = fopen("file_contexts", "w+");
+ } else {
+ file_contexts = fopen(filecontexts, "w+");
+ }
+
+ if (file_contexts == NULL) {
+ cil_log(CIL_ERR, "Failed to open file_contexts file\n");
+ goto exit;
+ }
+
+ if (fwrite(fc_buf, sizeof(char), fc_size, file_contexts) != fc_size) {
+ cil_log(CIL_ERR, "Failed to write file_contexts file\n");
+ goto exit;
+ }
+
+ fclose(file_contexts);
+ file_contexts = NULL;
+
+ rc = SEPOL_OK;
+
+exit:
+ cil_log(CIL_INFO,"Exiting\n");
+
+ if (binary != NULL) {
+ fclose(binary);
+ }
+ if (file != NULL) {
+ fclose(file);
+ }
+ free(buffer);
+ free(output);
+ free(filecontexts);
+ cil_db_destroy(&db);
+ sepol_policydb_free(pdb);
+ sepol_policy_file_free(pf);
+ free(fc_buf);
+ return rc;
+}
diff --git a/cil/src/cil.c b/cil/src/cil.c
new file mode 100644
index 0000000..a8a989f
--- /dev/null
+++ b/cil/src/cil.c
@@ -0,0 +1,2307 @@
+/*
+ * 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 <stdlib.h>
+#include <stdio.h>
+
+#include <sepol/policydb/policydb.h>
+#include <sepol/policydb/symtab.h>
+
+#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"
+
+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},
+ {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_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_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_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_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_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("<root>");
+ CIL_KEY_NODE = cil_strpool_add("<node>");
+ CIL_KEY_PERM = cil_strpool_add("perm");
+}
+
+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);
+ (*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)->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)->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)->num_types = 0;
+ (*db)->num_roles = 0;
+ (*db)->num_cats = 0;
+ (*db)->val_to_type = NULL;
+ (*db)->val_to_role = NULL;
+
+ (*db)->disable_dontaudit = CIL_FALSE;
+ (*db)->disable_neverallow = CIL_FALSE;
+ (*db)->preserve_tunables = CIL_FALSE;
+ (*db)->handle_unknown = -1;
+ (*db)->mls = -1;
+}
+
+void cil_db_destroy(struct cil_db **db)
+{
+ if (db == NULL || *db == NULL) {
+ return;
+ }
+
+ cil_tree_destroy(&(*db)->parse);
+ cil_destroy_ast_symtabs((*db)->ast->root);
+ 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)->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)->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);
+ *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_ERR, "Failed to parse %s\n", name);
+ goto exit;
+ }
+
+ free(buffer);
+ buffer = NULL;
+
+ rc = SEPOL_OK;
+
+exit:
+ free(buffer);
+
+ return rc;
+}
+
+int cil_compile(struct cil_db *db, sepol_policydb_t *sepol_db)
+{
+ int rc = SEPOL_ERR;
+
+ if (db == NULL || sepol_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_ERR, "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_ERR, "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_ERR, "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_ERR, "Post process failed\n");
+ goto exit;
+ }
+
+exit:
+
+ return rc;
+}
+
+int cil_build_policydb(cil_db_t *db, sepol_policydb_t *sepol_db)
+{
+ 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_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_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_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:
+ cil_destroy_avrule(*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_PORTCON:
+ cil_destroy_portcon(*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_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_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:
+ *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;
+ 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 "<none>";
+ case CIL_ROOT:
+ return CIL_KEY_ROOT;
+ case CIL_NODE:
+ return CIL_KEY_NODE;
+ case CIL_STRING:
+ return "string";
+ case CIL_DATUM:
+ return "<datum>";
+ case CIL_LIST:
+ return "<list>";
+ case CIL_LIST_ITEM:
+ return "<list_item>";
+ case CIL_PARAM:
+ return "<param>";
+ case CIL_ARGS:
+ return "<args>";
+ 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_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_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_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_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_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_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 "<unknown>";
+}
+
+int cil_userprefixes_to_string(struct cil_db *db, __attribute__((unused)) sepol_policydb_t *sepol_db, char **out, size_t *size)
+{
+ 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.name) + 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.name,
+ userprefix->prefix_str);
+ str_len -= buf_pos;
+ str_tmp += buf_pos;
+ }
+
+ rc = SEPOL_OK;
+exit:
+ return rc;
+
+}
+
+static int cil_level_equals(policydb_t *pdb, struct cil_level *low, struct cil_level *high)
+{
+ mls_level_t l;
+ mls_level_t h;
+ int rc;
+
+ cil_level_to_mls_level(pdb, low, &l);
+ cil_level_to_mls_level(pdb, high, &h);
+
+ rc = mls_level_eq(&l, &h);
+
+ mls_level_destroy(&l);
+ mls_level_destroy(&h);
+
+ 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.name);
+
+ 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.name;
+ first = cat->value;
+ last = first;
+ } else if (cat->value == last + 1) {
+ last++;
+ str2 = cat->datum.name;
+ } else {
+ if (first == last) {
+ str_len += strlen(str1) + strlen(cat->datum.name) + 1;
+ } else if (last == first + 1) {
+ str_len += strlen(str1) + strlen(str2) + strlen(cat->datum.name) + 2;
+ } else {
+ str_len += strlen(str1) + strlen(str2) + strlen(cat->datum.name) + 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.name);
+ 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.name;
+ first = cat->value;
+ last = first;
+ } else if (cat->value == last + 1) {
+ last++;
+ str2 = cat->datum.name;
+ } else {
+ if (first == last) {
+ buf_pos = sprintf(str_tmp, "%s,%s", str1, cat->datum.name);
+ str_tmp += buf_pos;
+ } else if (last == first + 1) {
+ buf_pos = sprintf(str_tmp, "%s,%s,%s", str1, str2, cat->datum.name);
+ str_tmp += buf_pos;
+ } else {
+ buf_pos = sprintf(str_tmp, "%s.%s,%s",str1, str2, cat->datum.name);
+ 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;
+}
+
+int cil_selinuxusers_to_string(struct cil_db *db, sepol_policydb_t *sepol_db, char **out, size_t *size)
+{
+ 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.name) + 1;
+
+ if (sepol_db->p.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.name);
+ str_tmp += buf_pos;
+
+ if (sepol_db->p.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;
+}
+
+int cil_filecons_to_string(struct cil_db *db, sepol_policydb_t *sepol_db, char **out, size_t *size)
+{
+ 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.name) + strlen(role->datum.name) + strlen(type->datum.name) + 3);
+
+ if (sepol_db->p.mls == CIL_TRUE) {
+ struct cil_levelrange *range = ctx->range;
+ if (cil_level_equals(&sepol_db->p, 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<<none>>");
+ }
+
+ 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.name, role->datum.name,
+ type->datum.name);
+ str_tmp += buf_pos;
+
+ if (sepol_db->p.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(&sepol_db->p, 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<<none>>");
+ str_tmp += buf_pos;
+ }
+
+ buf_pos = sprintf(str_tmp, "\n");
+ str_tmp += buf_pos;
+ }
+
+ return SEPOL_OK;
+}
+
+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_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_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_log(CIL_ERR, "Failed to get symtab from node at line %d of %s\n",
+ ast_node->line, ast_node->path);
+ 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_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;
+}
+
+void cil_blockinherit_init(struct cil_blockinherit **inherit)
+{
+ *inherit = cil_malloc(sizeof(**inherit));
+ (*inherit)->block_str = 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;
+}
+
+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_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)->rule_kind = CIL_NONE;
+ (*avrule)->src_str = NULL;
+ (*avrule)->src = NULL;
+ (*avrule)->tgt_str = NULL;
+ (*avrule)->tgt = NULL;
+ (*avrule)->classperms = 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_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_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;
+}
+
+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));
+ 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;
+}
diff --git a/cil/src/cil_binary.c b/cil/src/cil_binary.c
new file mode 100644
index 0000000..e43a7cf
--- /dev/null
+++ b/cil/src/cil_binary.c
@@ -0,0 +1,3751 @@
+/*
+ * 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 <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include <netinet/in.h>
+
+#include <sepol/policydb/policydb.h>
+#include <sepol/policydb/polcaps.h>
+#include <sepol/policydb/conditional.h>
+#include <sepol/policydb/constraint.h>
+#include <sepol/policydb/flask.h>
+
+#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"
+
+/* 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
+
+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;
+};
+
+struct cil_args_booleanif {
+ const struct cil_db *db;
+ policydb_t *pdb;
+ cond_node_t *cond_node;
+ enum cil_flavor cond_flavor;
+ struct cil_list *neverallows;
+ hashtab_t filename_trans_table;
+};
+
+struct cil_neverallow {
+ struct cil_tree_node *node;
+ struct cil_list *rules;
+};
+
+struct cil_neverallow_rule {
+ struct cil_symtab_datum *src;
+ struct cil_symtab_datum *tgt;
+ uint32_t class;
+ uint32_t perms;
+};
+
+void cil_neverallows_list_destroy(struct cil_list *neverallows)
+{
+ struct cil_list_item *i;
+ struct cil_list_item *j;
+
+ cil_list_for_each(i, neverallows) {
+ struct cil_neverallow *neverallow = i->data;
+ cil_list_for_each(j, neverallow->rules) {
+ struct cil_neverallow_rule *rule = j->data;
+ free(rule);
+ }
+ cil_list_destroy(&neverallow->rules, CIL_FALSE);
+ free(neverallow);
+ }
+ cil_list_destroy(&neverallows, CIL_FALSE);
+}
+
+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->name);
+ if (*sepol_user == NULL) {
+ cil_log(CIL_INFO, "Failed to find user %s in sepol hashtab\n", datum->name);
+ 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->name);
+ if (*sepol_role == NULL) {
+ cil_log(CIL_INFO, "Failed to find role %s in sepol hashtab\n", datum->name);
+ 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->name);
+ if (*sepol_type == NULL) {
+ cil_log(CIL_INFO, "Failed to find type %s in sepol hashtab\n", datum->name);
+ 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->name);
+ if (*sepol_class == NULL) {
+ cil_log(CIL_INFO, "Failed to find class %s in sepol hashtab\n", datum->name);
+ 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->name);
+ if (*sepol_cat == NULL) {
+ cil_log(CIL_INFO, "Failed to find category %s in sepol hashtab\n", datum->name);
+ 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->name);
+ if (*sepol_level == NULL) {
+ cil_log(CIL_INFO, "Failed to find level %s in sepol hashtab\n", datum->name);
+ return SEPOL_ERR;
+ }
+
+ return SEPOL_OK;
+}
+
+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;
+}
+
+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;
+}
+
+static 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;
+}
+
+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.name);
+ 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.name);
+ 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)
+{
+ 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;
+ struct cil_tree_node *node = cil_class->datum.nodes->head->data;
+ struct cil_tree_node *cil_perm = node->cl_head;
+ 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.name);
+ 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;
+
+ rc = symtab_init(&sepol_class->permissions, PERM_SYMTAB_SIZE);
+ if (rc != SEPOL_OK) {
+ goto exit;
+ }
+
+ if (cil_class->common != NULL) {
+ struct cil_class *cil_common = cil_class->common;
+
+ key = cil_class->common->datum.name;
+ 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;
+ }
+
+ while (cil_perm != NULL) {
+ struct cil_perm *curr_perm = 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_perm->datum.name);
+ 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++;
+ cil_perm = cil_perm->next;
+ }
+ }
+
+ 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.name == 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.name);
+ 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.name);
+ 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)
+{
+ 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.name);
+ 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;
+
+ 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.name);
+ 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.name);
+ 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)
+{
+ int rc = SEPOL_ERR;
+ uint32_t value = 0;
+ char *key = NULL;
+ type_datum_t *sepol_attr = NULL;
+
+ if (cil_attr->used == CIL_FALSE) {
+ 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.name);
+ 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;
+
+ 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));
+
+ uint32_t i = 0;
+ for (i = 0; i < pdb->p_types.nprim; i++) {
+ ebitmap_init(&pdb->type_attr_map[i]);
+ if (ebitmap_set_bit(&pdb->type_attr_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->used == CIL_FALSE) {
+ 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);
+ }
+
+ 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.name);
+ 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.name);
+ 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.name);
+ return SEPOL_ERR;
+}
+
+int cil_userrole_to_policydb(policydb_t *pdb, const struct cil_db *db, struct cil_userrole *userrole)
+{
+ int rc = SEPOL_ERR;
+ user_datum_t *sepol_user = NULL;
+ role_datum_t *sepol_role = NULL;
+ ebitmap_t role_bitmap;
+ ebitmap_node_t *rnode;
+ unsigned int i;
+
+ rc = __cil_get_sepol_user_datum(pdb, DATUM(userrole->user), &sepol_user);
+ if (rc != SEPOL_OK) goto exit;
+
+ rc = __cil_expand_role(userrole->role, &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) 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");
+ goto exit;
+ }
+ }
+
+ rc = SEPOL_OK;
+
+exit:
+ ebitmap_destroy(&role_bitmap);
+ 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.name);
+ 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.name);
+ 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.name);
+ rc = symtab_insert(pdb, SYM_CATS, key, sepol_alias, SCOPE_DECL, 0, NULL);
+ if (rc != SEPOL_OK) {
+ free(key);
+ 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.name);
+ 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.name);
+ 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_level);
+ 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, 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\n");
+ 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\n");
+ 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, 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 *new = 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;
+ uint32_t *otype = NULL;
+
+ 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;
+ 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;
+
+ new = cil_malloc(sizeof(*new));
+ memset(new, 0, sizeof(*new));
+ new->stype = sepol_src->s.value;
+ new->ttype = sepol_tgt->s.value;
+ new->tclass = sepol_obj->s.value;
+ new->otype = sepol_result->s.value;
+ new->name = cil_strdup(name);
+
+ rc = hashtab_insert(filename_trans_table, (hashtab_key_t)new, &(new->otype));
+ if (rc != SEPOL_OK) {
+ if (rc == SEPOL_EEXIST) {
+ add = CIL_FALSE;
+ otype = hashtab_search(filename_trans_table, (hashtab_key_t)new);
+ if (new->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) {
+ new->next = pdb->filename_trans;
+ pdb->filename_trans = new;
+ } else {
+ free(new->name);
+ free(new);
+ 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 __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) {
+ perm_datum_t *sepol_perm;
+ cil_perm = curr_perm->data;
+ key = cil_perm->datum.name;
+ sepol_perm = hashtab_search(sepol_class->permissions.table, key);
+ if (sepol_perm == NULL) {
+ common_datum_t *sepol_common = sepol_class->comdatum;
+ sepol_perm = hashtab_search(sepol_common->permissions.table, key);
+ if (sepol_perm == NULL) {
+ cil_log(CIL_ERR, "Failed to find datum for perm %s\n", key);
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+ }
+ data |= 1 << (sepol_perm->s.value - 1);
+ }
+
+ *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;
+}
+
+static void __cil_neverallow_handle(struct cil_list *neverallows, struct cil_symtab_datum *src, struct cil_symtab_datum *tgt, uint32_t class, uint32_t perms)
+{
+ struct cil_neverallow *neverallow = neverallows->head->data;
+ struct cil_list *neverallow_rules = neverallow->rules;
+ struct cil_neverallow_rule *new = NULL;
+
+ new = cil_malloc(sizeof(*new));
+ new->src = src;
+ new->tgt = tgt;
+ new->class = class;
+ new->perms = perms;
+
+ cil_list_append(neverallow_rules, CIL_LIST_ITEM, new);
+}
+
+static int __cil_is_type_match(enum cil_flavor f1, struct cil_symtab_datum *t1, enum cil_flavor f2, struct cil_symtab_datum *t2)
+{
+ if (t1->name == t2->name) {
+ return CIL_TRUE;
+ } else if (f1 == CIL_TYPEATTRIBUTE && f2 != CIL_TYPEATTRIBUTE) {
+ struct cil_typeattribute *a = (struct cil_typeattribute *)t1;
+ struct cil_type *t = (struct cil_type *)t2;
+ if (ebitmap_get_bit(a->types, t->value)) {
+ return CIL_TRUE;
+ }
+ } else if (f1 != CIL_TYPEATTRIBUTE && f2 == CIL_TYPEATTRIBUTE) {
+ struct cil_typeattribute *a = (struct cil_typeattribute *)t2;
+ struct cil_type *t = (struct cil_type *)t1;
+ if (ebitmap_get_bit(a->types, t->value)) {
+ return CIL_TRUE;
+ }
+ } else if (f1 == CIL_TYPEATTRIBUTE && f2 == CIL_TYPEATTRIBUTE) {
+ struct cil_typeattribute *a1 = (struct cil_typeattribute *)t2;
+ struct cil_typeattribute *a2 = (struct cil_typeattribute *)t1;
+ /* abusing the ebitmap abstraction for speed */
+ ebitmap_node_t *n1 = a1->types->node;
+ ebitmap_node_t *n2 = a2->types->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 CIL_TRUE;
+ }
+ n1 = n1->next;
+ n2 = n2->next;
+ }
+ }
+ }
+ return CIL_FALSE;
+}
+
+static int __cil_check_neverallows(struct cil_list *neverallows, struct cil_symtab_datum *src, struct cil_symtab_datum *tgt, uint32_t class, uint32_t perms)
+{
+ struct cil_list_item *curr = NULL;
+ enum cil_flavor al_src_flavor = ((struct cil_tree_node*)src->nodes->head->data)->flavor;
+ enum cil_flavor al_tgt_flavor = ((struct cil_tree_node*)tgt->nodes->head->data)->flavor;
+ cil_list_for_each(curr, neverallows) {
+ struct cil_neverallow *neverallow = curr->data;
+ struct cil_tree_node *node = neverallow->node;
+ struct cil_list_item *curr_item = NULL;
+ cil_list_for_each(curr_item, neverallow->rules) {
+ struct cil_neverallow_rule *curr_rule = curr_item->data;
+ enum cil_flavor nv_src_flavor = ((struct cil_tree_node*)curr_rule->src->nodes->head->data)->flavor;
+ enum cil_flavor nv_tgt_flavor = ((struct cil_tree_node*)curr_rule->tgt->nodes->head->data)->flavor;
+ if ((curr_rule->perms & perms) && (class == curr_rule->class)) {
+ int src_match = __cil_is_type_match(al_src_flavor, src, nv_src_flavor, curr_rule->src);
+ if (src_match) {
+ int tgt_match = __cil_is_type_match(al_tgt_flavor, tgt, nv_tgt_flavor, curr_rule->tgt);
+ if (tgt_match) {
+ cil_log(CIL_ERR, "Neverallow found that matches avrule at line %d of %s\n", node->line, node->path);
+ return SEPOL_ERR;
+ }
+ }
+ }
+ }
+ }
+ return SEPOL_OK;
+}
+
+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, struct cil_list *neverallows, 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_NEVERALLOW) {
+ __cil_neverallow_handle(neverallows, src, tgt, sepol_class->s.value, data);
+ } else {
+ if (kind == CIL_AVRULE_DONTAUDIT) {
+ data = ~data;
+ } else if (neverallows != NULL && kind == CIL_AVRULE_ALLOWED) {
+ rc = __cil_check_neverallows(neverallows, src, tgt, sepol_class->s.value, data);
+ if (rc != SEPOL_OK) {
+ goto exit;
+ }
+ }
+
+ 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, struct cil_list *neverallows, 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, neverallows, 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, neverallows, 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, neverallows, cond_node, cond_flavor);
+ if (rc != SEPOL_OK) {
+ goto exit;
+ }
+ }
+ }
+
+ return SEPOL_OK;
+
+exit:
+ return rc;
+}
+
+int __cil_avrule_to_avtab(policydb_t *pdb, const struct cil_db *db, struct cil_avrule *cil_avrule, struct cil_list *neverallows, 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->classperms;
+
+ 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;
+ }
+
+ if (cil_avrule->rule_kind == CIL_AVRULE_NEVERALLOW && db->disable_neverallow == CIL_TRUE) {
+ // ignore neverallow rules
+ rc = SEPOL_OK;
+ goto exit;
+ }
+
+ src = cil_avrule->src;
+ tgt = cil_avrule->tgt;
+
+ if (tgt->name == CIL_KEY_SELF) {
+ ebitmap_t type_bitmap;
+ ebitmap_node_t *tnode;
+ unsigned int i;
+
+ rc = __cil_expand_type(src, &type_bitmap);
+ if (rc != SEPOL_OK) goto exit;
+
+ ebitmap_for_each_bit(&type_bitmap, tnode, i) {
+ if (!ebitmap_get_bit(&type_bitmap, i)) continue;
+
+ src = DATUM(db->val_to_type[i]);
+ rc = __cil_avrule_expand(pdb, kind, src, src, classperms, neverallows, cond_node, cond_flavor);
+ if (rc != SEPOL_OK) {
+ ebitmap_destroy(&type_bitmap);
+ goto exit;
+ }
+ }
+ ebitmap_destroy(&type_bitmap);
+ } else {
+ rc = __cil_avrule_expand(pdb, kind, src, tgt, classperms, neverallows, cond_node, cond_flavor);
+ if (rc != SEPOL_OK) goto exit;
+ }
+
+ return SEPOL_OK;
+
+exit:
+ return rc;
+}
+
+int cil_avrule_to_policydb(policydb_t *pdb, const struct cil_db *db, struct cil_avrule *cil_avrule, struct cil_list *neverallows)
+{
+ return __cil_avrule_to_avtab(pdb, db, cil_avrule, neverallows, NULL, CIL_FALSE);
+}
+
+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)->name != CIL_KEY_STAR) {
+ cil_log(CIL_ERR, "typetransition with file name not allowed within a booleanif block.\n");
+ cil_log(CIL_ERR,"Invalid typetransition statement at line %d of %s\n",
+ node->line, node->path);
+ goto exit;
+ }
+ rc = __cil_typetransition_to_avtab(pdb, db, cil_typetrans, cond_node, cond_flavor, filename_trans_table);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_ERR, "Failed to insert type transition into avtab at line %d of %s\n", node->line, node->path);
+ 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_log(CIL_ERR, "Failed to insert typerule into avtab at line %d of %s\n", node->line, node->path);
+ goto exit;
+ }
+ break;
+ case CIL_AVRULE:
+ cil_avrule = node->data;
+ rc = __cil_avrule_to_avtab(pdb, db, cil_avrule, args->neverallows, cond_node, cond_flavor);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_ERR, "Failed to insert avrule into avtab at line %d of %s\n", node->line, node->path);
+ goto exit;
+ }
+ break;
+ case CIL_CALL:
+ case CIL_TUNABLEIF:
+ break;
+ default:
+ cil_log(CIL_ERR, "Invalid statement within booleanif at line %d of %s\n",
+ node->line, node->path);
+ 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);
+
+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)->name;
+ 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:
+ 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, struct cil_list *neverallows, 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_log(CIL_INFO, "Failed to create sepol conditional node at line %d of %s\n",
+ node->line, node->path);
+ goto exit;
+ }
+
+ rc = __cil_cond_expr_to_sepol_expr(pdb, cil_boolif->datum_expr, &tmp_cond->expr);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_INFO, "Failed to convert CIL conditional expression to sepol expression at line %d of %s\n", node->line, node->path);
+ 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);
+
+ 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.neverallows = neverallows;
+ 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_log(CIL_ERR, "Failure while walking true conditional block at line %d of %s\n", true_node->line, true_node->path);
+ 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_log(CIL_ERR, "Failure while walking false conditional block at line %d of %s\n", false_node->line, false_node->path);
+ goto exit;
+ }
+ }
+
+ return SEPOL_OK;
+
+exit:
+ 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 = SEPOL_OK;
+ 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;
+ rc = __cil_get_sepol_user_datum(pdb, item->data, &sepol_user);
+ if (rc != SEPOL_OK) goto exit;
+
+ if (ebitmap_set_bit(&expr->names, sepol_user->s.value - 1, 1)) {
+ goto exit;
+ }
+ } 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) {
+ ebitmap_destroy(&type_bitmap);
+ goto exit;
+ }
+
+ if (ebitmap_set_bit(&expr->type_names->types, sepol_type->s.value - 1, 1)) {
+ ebitmap_destroy(&type_bitmap);
+ 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.name);
+ 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.name);
+ 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 *new;
+ 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;
+
+ new = cil_malloc(sizeof(*new));
+ memset(new, 0, sizeof(range_trans_t));
+ new->source_type = sepol_src->s.value;
+ new->target_type = sepol_tgt->s.value;
+ new->target_class = sepol_class->s.value;
+ rc = __cil_levelrange_to_mls_range(pdb, rangetrans->range, &new->target_range);
+ if (rc != SEPOL_OK) {
+ free(new);
+ goto exit;
+ }
+
+ rc = SEPOL_OK;
+ rc = hashtab_insert(range_trans_table, (hashtab_key_t)new, &(new->target_range));
+ if (rc != SEPOL_OK) {
+ if (rc == SEPOL_EEXIST) {
+ add = CIL_FALSE;
+ o_range = hashtab_search(range_trans_table, (hashtab_key_t)new);
+ if (!mls_range_eq(&new->target_range, 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) {
+ new->next = pdb->range_tr;
+ pdb->range_tr = new;
+ } else {
+ mls_range_destroy(&new->target_range);
+ free(new);
+ 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_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;
+ 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_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_addr32[0], 16);
+ memcpy(new_ocon->u.node6.mask, &cil_nodecon->mask->ip.v6.s6_addr32[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_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)->name);
+ 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)->name);
+ 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)->name);
+ 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)->name);
+ 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;
+ 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;
+
+ 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);
+ break;
+ case CIL_TYPEATTRIBUTE:
+ rc = cil_typeattribute_to_policydb(pdb, node->data);
+ 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);
+ }
+ break;
+ case CIL_USERROLE:
+ 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: {
+ struct cil_avrule *rule = node->data;
+ struct cil_list *neverallows = args->neverallows;
+ if (rule->rule_kind == CIL_AVRULE_NEVERALLOW) {
+ struct cil_neverallow *new_rule = NULL;
+
+ new_rule = cil_malloc(sizeof(*new_rule));
+ cil_list_init(&new_rule->rules, CIL_LIST_ITEM);
+ new_rule->node = node;
+
+ cil_list_prepend(neverallows, CIL_LIST_ITEM, new_rule);
+
+ rc = cil_avrule_to_policydb(pdb, db, node->data, neverallows);
+ }
+ 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, args->neverallows, 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, args->neverallows);
+ }
+ }
+ break;
+ case CIL_ROLEALLOW:
+ rc = cil_roleallow_to_policydb(pdb, db, node->data);
+ break;
+ default:
+ break;
+ }
+ default:
+ break;
+ }
+
+exit:
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_ERR, "Binary policy creation failed at line %d of %s\n", node->line, node->path);
+ }
+ return rc;
+}
+
+int __cil_binary_create_helper(struct cil_tree_node *node, __attribute__((unused)) 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_OPTIONAL) {
+ struct cil_optional *opt = node->data;
+ if (opt->datum.state != CIL_STATE_ENABLED) {
+ *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;
+ }
+
+ if (pdb->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;
+ }
+ }
+ 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_init(policydb_t *pdb, const struct cil_db *db)
+{
+ int rc = SEPOL_ERR;
+
+ pdb->handle_unknown = db->handle_unknown;
+ pdb->mls = db->mls;
+
+ rc = cil_classorder_to_policydb(pdb, db);
+ 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, hashtab_key_t key)
+{
+ filename_trans_t *k = (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)), hashtab_key_t key1,
+ hashtab_key_t key2)
+{
+ filename_trans_t *a = (filename_trans_t *)key1;
+ filename_trans_t *b = (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, hashtab_key_t key)
+{
+ range_trans_t *k = (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)), hashtab_key_t key1,
+ hashtab_key_t key2)
+{
+ range_trans_t *a = (range_trans_t *)key1;
+ range_trans_t *b = (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, hashtab_key_t key)
+{
+ role_trans_t *k = (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)), hashtab_key_t key1,
+ hashtab_key_t key2)
+{
+ role_trans_t *a = (role_trans_t *)key1;
+ role_trans_t *b = (role_trans_t *)key2;
+
+ return a->role != b->role || a->type != b->type || a->tclass != b->tclass;
+}
+
+int cil_binary_create(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;
+
+ 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;
+ }
+
+ rc = __cil_policydb_init(pdb, db);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_ERR,"Problem in policydb_init\n");
+ return SEPOL_ERR;
+ }
+
+ 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;
+ }
+
+ 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;
+ 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;
+ }
+ }
+ }
+
+ 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);
+
+ rc = SEPOL_OK;
+
+exit:
+ hashtab_destroy(filename_trans_table);
+ hashtab_destroy(range_trans_table);
+ hashtab_destroy(role_trans_table);
+ cil_neverallows_list_destroy(neverallows);
+ return rc;
+}
diff --git a/cil/src/cil_binary.h b/cil/src/cil_binary.h
new file mode 100644
index 0000000..c3f0357
--- /dev/null
+++ b/cil/src/cil_binary.h
@@ -0,0 +1,436 @@
+/*
+ * 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 <sepol/policydb/policydb.h>
+
+#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);
+
+/**
+ * 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);
+
+/**
+ * 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);
+
+/**
+ * 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] datum The cil_userrole datum.
+ *
+ * @return SEPOL_OK upon success or SEPOL_ERR otherwise.
+ */
+int cil_userrole_to_policydb(policydb_t *pdb, const struct cil_db *db, struct cil_userrole *userrole);
+
+/**
+ * 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, struct cil_list *neverallows);
+
+/**
+ * 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, struct cil_list *neverallows, 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 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_
diff --git a/cil/src/cil_build_ast.c b/cil/src/cil_build_ast.c
new file mode 100644
index 0000000..01b3979
--- /dev/null
+++ b/cil/src/cil_build_ast.c
@@ -0,0 +1,5927 @@
+/*
+ * 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 <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <sepol/policydb/conditional.h>
+
+#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;
+}
+
+int cil_gen_node(__attribute__((unused)) 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;
+
+ 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) {
+ 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_log(CIL_ERR, "Previous declaration at line %d of %s\n",
+ node->line, node->path);
+ }
+ }
+ goto exit;
+ }
+ }
+
+ 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(__attribute__((unused)) 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_log(CIL_ERR, "Bad block declaration at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ 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);
+
+ free(block);
+}
+
+int cil_gen_blockinherit(__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_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_log(CIL_ERR, "Bad blockinherit declaration at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ cil_destroy_blockinherit(inherit);
+ return rc;
+}
+
+void cil_destroy_blockinherit(struct cil_blockinherit *inherit)
+{
+ if (inherit == NULL) {
+ return;
+ }
+
+ free(inherit);
+}
+
+int cil_gen_blockabstract(__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_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_log(CIL_ERR, "Bad blockabstract declaration at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ cil_destroy_blockabstract(abstract);
+ return rc;
+}
+
+void cil_destroy_blockabstract(struct cil_blockabstract *abstract)
+{
+ if (abstract == NULL) {
+ return;
+ }
+
+ free(abstract);
+}
+
+int cil_gen_in(__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_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_log(CIL_ERR, "Bad in statement at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ 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(__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_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;
+
+ 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;
+ }
+ }
+
+ return SEPOL_OK;
+
+exit:
+ cil_log(CIL_ERR, "Bad class declaration at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ 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(__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_LIST,
+ CIL_SYN_END
+ };
+ int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ struct cil_classorder *classorder = 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;
+ }
+ ast_node->data = classorder;
+ ast_node->flavor = CIL_CLASSORDER;
+
+ return SEPOL_OK;
+
+exit:
+ cil_log(CIL_ERR, "Bad classorder declaration at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ 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(__attribute__((unused)) 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;
+
+ 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(__attribute__((unused)) 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->path = current_perm->path;
+
+ rc = cil_gen_perm(db, current_perm, new_ast, flavor, num_perms);
+ if (rc != SEPOL_OK) {
+ 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");
+ 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(__attribute__((unused)) 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_log(CIL_ERR, "Bad classpermission declaration at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ 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(__attribute__((unused)) 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_log(CIL_ERR, "Bad classpermissionset at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ 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(__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_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_log(CIL_ERR, "Bad map class declaration at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ cil_destroy_class(map);
+ cil_clear_node(ast_node);
+ return rc;
+}
+
+int cil_gen_classmapping(__attribute__((unused)) 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_log(CIL_ERR, "Bad classmapping declaration at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ 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(__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_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;
+ }
+
+ return SEPOL_OK;
+
+exit:
+ cil_log(CIL_ERR, "Bad common declaration at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ cil_destroy_class(common);
+ cil_clear_node(ast_node);
+ return rc;
+
+}
+
+int cil_gen_classcommon(__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_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_log(CIL_ERR, "Bad classcommon declaration at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ cil_destroy_classcommon(clscom);
+ return rc;
+
+}
+
+void cil_destroy_classcommon(struct cil_classcommon *clscom)
+{
+ if (clscom == NULL) {
+ return;
+ }
+
+ free(clscom);
+}
+
+int cil_gen_sid(__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_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_log(CIL_ERR, "Bad sid declaration at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ 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(__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_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_log(CIL_ERR, "Bad sidcontext declaration at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ 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(__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_LIST,
+ CIL_SYN_END
+ };
+ int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ struct cil_sidorder *sidorder = 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;
+ }
+ ast_node->data = sidorder;
+ ast_node->flavor = CIL_SIDORDER;
+
+ return SEPOL_OK;
+
+exit:
+ cil_log(CIL_ERR, "Bad sidorder declaration at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ 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(__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_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_log(CIL_ERR, "Bad user declaration at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ 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);
+ cil_list_destroy(&user->roles, CIL_FALSE);
+ free(user);
+}
+
+int cil_gen_userlevel(__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_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_log(CIL_ERR, "Bad userlevel declaration at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ 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(__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_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_log(CIL_ERR, "Bad userrange declaration at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ 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(__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_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_log(CIL_ERR, "Bad userprefix declaration at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ cil_destroy_userprefix(userprefix);
+ return rc;
+}
+
+void cil_destroy_userprefix(struct cil_userprefix *userprefix)
+{
+ if (userprefix == NULL) {
+ return;
+ }
+
+ free(userprefix);
+}
+
+int cil_gen_selinuxuser(__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);
+ 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_log(CIL_ERR, "Bad selinuxuser declaration at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ cil_destroy_selinuxuser(selinuxuser);
+ return rc;
+}
+
+int cil_gen_selinuxuserdefault(__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_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_log(CIL_ERR, "Bad selinuxuserdefault declaration at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ 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(__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_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_log(CIL_ERR, "Bad role declaration at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ 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(__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_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_log(CIL_ERR, "Bad roletype declaration at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ cil_destroy_roletype(roletype);
+ return rc;
+}
+
+void cil_destroy_roletype(struct cil_roletype *roletype)
+{
+ if (roletype == NULL) {
+ return;
+ }
+
+ free(roletype);
+}
+
+int cil_gen_userrole(__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_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_log(CIL_ERR, "Bad userrole declaration at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ 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_log(CIL_ERR, "Bad roletransition rule at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ cil_destroy_roletransition(roletrans);
+ return rc;
+}
+
+void cil_destroy_roletransition(struct cil_roletransition *roletrans)
+{
+ if (roletrans == NULL) {
+ return;
+ }
+
+ free(roletrans);
+}
+
+int cil_gen_roleallow(__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_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_log(CIL_ERR, "Bad roleallow rule at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ cil_destroy_roleallow(roleallow);
+ return rc;
+}
+
+void cil_destroy_roleallow(struct cil_roleallow *roleallow)
+{
+ if (roleallow == NULL) {
+ return;
+ }
+
+ free(roleallow);
+}
+
+int cil_gen_roleattribute(__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_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_log(CIL_ERR, "Bad roleattribute declaration at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ 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(__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_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_log(CIL_ERR, "Bad roleattributeset declaration at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ 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->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->classperms);
+ if (rc != SEPOL_OK) {
+ goto exit;
+ }
+
+ ast_node->data = rule;
+ ast_node->flavor = CIL_AVRULE;
+
+ return SEPOL_OK;
+
+exit:
+ cil_log(CIL_ERR, "Bad allow rule at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ cil_destroy_avrule(rule);
+ return rc;
+}
+
+void cil_destroy_avrule(struct cil_avrule *rule)
+{
+ if (rule == NULL) {
+ return;
+ }
+
+ cil_destroy_classperms_list(&rule->classperms);
+
+ free(rule);
+}
+
+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_log(CIL_ERR, "Bad type rule at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ 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(__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_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_log(CIL_ERR, "Bad type declaration at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ 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(__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_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_log(CIL_ERR, "Bad typeattribute declaration at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ 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(__attribute__((unused)) 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_log(CIL_ERR, "Bad tunable (treated as a boolean due to preserve-tunables) declaration at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ } else {
+ cil_log(CIL_ERR, "Bad boolean declaration at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ }
+ 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(__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_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_log(CIL_ERR, "Bad tunable declaration at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ 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 */
+ else if (op == CIL_KEY_RANGE) return CIL_RANGE; /* Only catset */
+ 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) {
+ 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) {
+ 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(__attribute__((unused)) 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_log(CIL_ERR, "Bad tunableif (treated as a booleanif due to preserve-tunables) declaration at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ } else {
+ cil_log(CIL_ERR, "Bad booleanif declaration at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ }
+ 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(__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_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_log(CIL_ERR, "Bad tunableif declaration at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ 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(__attribute__((unused)) 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_log(CIL_ERR, "Bad %s condition declaration at line %d of %s\n",
+ (char*)parse_current->data, parse_current->line, parse_current->path);
+ 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(__attribute__((unused)) 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_log(CIL_ERR, "Bad %s declaration at line %d of %s\n",
+ (char*)parse_current->data, parse_current->line, parse_current->path);
+ 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(__attribute__((unused)) 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_log(CIL_ERR, "Bad %s association at line %d of %s\n",
+ cil_node_to_string(parse_current),parse_current->line, parse_current->path);
+ 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(__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_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_log(CIL_ERR, "Bad typeattributeset statement at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ 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_typepermissive(__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_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_log(CIL_ERR, "Bad typepermissive declaration at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ cil_destroy_typepermissive(typeperm);
+ return rc;
+}
+
+void cil_destroy_typepermissive(struct cil_typepermissive *typeperm)
+{
+ if (typeperm == NULL) {
+ return;
+ }
+
+ free(typeperm);
+}
+
+int cil_gen_typetransition(__attribute__((unused)) 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_log(CIL_ERR, "Bad typetransition declaration at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ 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(__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_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_log(CIL_ERR, "Bad rangetransition declaration at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ 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(__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_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_log(CIL_ERR, "Bad sensitivity declaration at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ 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(__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_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_log(CIL_ERR, "Bad category declaration at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ 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(__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_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_log(CIL_ERR, "Bad categoryset declaration at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ 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(__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_LIST,
+ CIL_SYN_END
+ };
+ int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ struct cil_catorder *catorder = 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;
+ }
+ ast_node->data = catorder;
+ ast_node->flavor = CIL_CATORDER;
+
+ return SEPOL_OK;
+
+exit:
+ cil_log(CIL_ERR, "Bad categoryorder declaration at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ 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(__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_LIST,
+ CIL_SYN_END
+ };
+ int syntax_len = sizeof(syntax)/sizeof(*syntax);
+ struct cil_sensorder *sensorder = 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;
+ }
+
+ ast_node->data = sensorder;
+ ast_node->flavor = CIL_SENSITIVITYORDER;
+
+ return SEPOL_OK;
+
+exit:
+ cil_log(CIL_ERR, "Bad sensitivityorder declaration at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ 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(__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_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_log(CIL_ERR, "Bad sensitivitycategory declaration at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ 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(__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_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_log(CIL_ERR, "Bad level declaration at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ 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(__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_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_log(CIL_ERR, "Bad levelrange declaration at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ 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(__attribute__((unused)) 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_log(CIL_ERR, "Bad constrain declaration at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ 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(__attribute__((unused)) 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_log(CIL_ERR, "Bad validatetrans declaration at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ 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(__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_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_log(CIL_ERR, "Bad context declaration at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ 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(__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_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_log(CIL_ERR, "Bad filecon declaration at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ 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_portcon(__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_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 {
+ 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);
+ 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);
+ 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);
+ 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_log(CIL_ERR, "Bad portcon declaration at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ 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(__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_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_log(CIL_ERR, "Bad nodecon declaration at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ 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(__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_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_log(CIL_ERR, "Bad genfscon declaration at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ 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(__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_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_log(CIL_ERR, "Bad netifcon declaration at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ 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_pirqcon(__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_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);
+ 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_log(CIL_ERR, "Bad pirqcon declaration at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ 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(__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_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_integer(parse_current->next->cl_head, &iomemcon->iomem_low);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_ERR, "Improper iomem specified\n");
+ goto exit;
+ }
+ rc = cil_fill_integer(parse_current->next->cl_head->next, &iomemcon->iomem_high);
+ 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_integer(parse_current->next, &iomemcon->iomem_low);;
+ 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_log(CIL_ERR, "Bad iomemcon declaration at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ 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(__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_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);
+ 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);
+ 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);
+ 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_log(CIL_ERR, "Bad ioportcon declaration at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ 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(__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_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);
+ 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_log(CIL_ERR, "Bad pcidevicecon declaration at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ 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_fsuse(__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);
+ 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_log(CIL_ERR, "Bad fsuse declaration at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ 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(__attribute__((unused)) 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(&macro);
+
+ 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(&macro->params, CIL_LIST_ITEM);
+ }
+
+ kind = current_item->cl_head->data;
+ cil_param_init(&param);
+
+ 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_log(CIL_ERR, "Bad macro declaration at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ 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(&macro->datum);
+ cil_symtab_array_destroy(macro->symtab);
+
+ if (macro->params != NULL) {
+ cil_list_destroy(&macro->params, 1);
+ }
+
+ free(macro);
+}
+
+int cil_gen_call(__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_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_log(CIL_ERR, "Bad macro call at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ 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(__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_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_log(CIL_ERR, "Bad optional at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ 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(__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_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_log(CIL_ERR, "Bad policycap statement at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ 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(__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_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_log(CIL_ERR, "Bad ipaddr statement at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ 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 rc = SEPOL_ERR;
+ char *endptr = NULL;
+ int val;
+
+ if (int_node == NULL || integer == NULL) {
+ goto exit;
+ }
+
+ errno = 0;
+ val = strtol(int_node->data, &endptr, 10);
+ 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);
+ }
+
+ 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(__attribute__((unused)) 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_log(CIL_ERR, "Bad bounds declaration at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ 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);
+ rc = SEPOL_OK;
+ } else {
+ rc = cil_fill_list(parse_current->next->cl_head, CIL_CLASS, &def->class_strs);
+ }
+
+ 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_log(CIL_ERR, "Bad %s declaration at line %d of %s\n",
+ cil_node_to_string(parse_current), parse_current->line, parse_current->path);
+ 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);
+ rc = SEPOL_OK;
+ } else {
+ rc = cil_fill_list(parse_current->next->cl_head, CIL_CLASS, &def->class_strs);
+ }
+
+ 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_log(CIL_ERR, "Bad defaultrange declaration at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ 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_log(CIL_ERR, "Bad handleunknown at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ 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_log(CIL_ERR, "Bad mls at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ cil_destroy_mls(mls);
+ return rc;
+}
+
+void cil_destroy_mls(struct cil_mls *mls)
+{
+ free(mls);
+}
+
+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_log(CIL_ERR, "Keyword expected after open parenthesis in line %d of %s\n", parse_current->line, parse_current->path);
+ }
+ goto exit;
+ }
+
+ if (macro != NULL) {
+ if (parse_current->data == CIL_KEY_MACRO) {
+ rc = SEPOL_ERR;
+ cil_log(CIL_ERR, "Found macro at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ cil_log(CIL_ERR, "Macros cannot be defined within macro statement\n");
+ goto exit;
+ }
+
+ if (parse_current->data == CIL_KEY_TUNABLE) {
+ rc = SEPOL_ERR;
+ cil_log(CIL_ERR, "Found tunable at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ cil_log(CIL_ERR, "Tunables cannot be defined within macro statement\n");
+ goto exit;
+ }
+
+ if (parse_current->data == CIL_KEY_IN) {
+ rc = SEPOL_ERR;
+ cil_log(CIL_ERR, "Found in at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ cil_log(CIL_ERR, "in-statements cannot be defined within macro statement\n");
+ 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_log(CIL_ERR, "Found %s at line %d of %s\n",
+ (char*)parse_current->data, parse_current->line, parse_current->path);
+ 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_log(CIL_ERR, "Found tunable at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ 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_log(CIL_ERR, "Found in-statement at line %d of %s\n",
+ parse_current->line, parse_current->path);
+ 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->path = parse_current->path;
+
+ 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_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_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_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_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_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 {
+ 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(__attribute__((unused)) 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;
+}
diff --git a/cil/src/cil_build_ast.h b/cil/src/cil_build_ast.h
new file mode 100644
index 0000000..5b07c14
--- /dev/null
+++ b/cil/src/cil_build_ast.h
@@ -0,0 +1,219 @@
+/*
+ * 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 <stdint.h>
+
+#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_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_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_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_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_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_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 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_ */
diff --git a/cil/src/cil_copy_ast.c b/cil/src/cil_copy_ast.c
new file mode 100644
index 0000000..0e54545
--- /dev/null
+++ b/cil/src/cil_copy_ast.c
@@ -0,0 +1,1939 @@
+/*
+ * 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 <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#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;
+
+ *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_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;
+
+ 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_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_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;
+}
+
+int cil_copy_avrule(__attribute__((unused)) 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->rule_kind = orig->rule_kind;
+ new->src_str = orig->src_str;
+ new->tgt_str = orig->tgt_str;
+ cil_copy_classperms_list(orig->classperms, &new->classperms);
+
+ *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_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_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;
+
+ 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);
+ 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_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;
+
+ 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_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_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:
+ copy_func = &cil_copy_avrule;
+ 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_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_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;
+ 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->path = orig->path;
+ new->flavor = orig->flavor;
+ new->data = data;
+
+ if (orig->flavor >= CIL_MIN_DECLARATIVE) {
+ 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_log(CIL_ERR, "%s %s shadows a macro parameter (%s line:%d)\n", cil_node_to_string(new), ((struct cil_symtab_datum*)orig->data)->name, orig->path, orig->line);
+ cil_log(CIL_ERR, "Note: macro declaration (%s line:%d)\n", namespace->path, namespace->line);
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ 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;
+}
+
diff --git a/cil/src/cil_copy_ast.h b/cil/src/cil_copy_ast.h
new file mode 100644
index 0000000..bd3a231
--- /dev/null
+++ b/cil/src/cil_copy_ast.h
@@ -0,0 +1,117 @@
+/*
+ * 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_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_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
diff --git a/cil/src/cil_flavor.h b/cil/src/cil_flavor.h
new file mode 100644
index 0000000..7295b19
--- /dev/null
+++ b/cil/src/cil_flavor.h
@@ -0,0 +1,185 @@
+/*
+ * 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_USERLEVEL,
+ CIL_USERRANGE,
+ CIL_USERBOUNDS,
+ CIL_SELINUXUSER,
+ CIL_SELINUXUSERDEFAULT,
+ CIL_ROLEATTRIBUTESET,
+ CIL_ROLETYPE,
+ CIL_ROLEBOUNDS,
+ CIL_TYPEATTRIBUTESET,
+ CIL_TYPEALIASACTUAL,
+ CIL_TYPEBOUNDS,
+ CIL_TYPEPERMISSIVE,
+ CIL_SENSALIASACTUAL,
+ CIL_SENSITIVITYORDER,
+ CIL_SENSCAT,
+ CIL_CATALIASACTUAL,
+ CIL_CATORDER,
+ CIL_SIDORDER,
+ CIL_ROLEALLOW,
+ CIL_AVRULE,
+ 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_DEFAULTUSER,
+ CIL_DEFAULTROLE,
+ CIL_DEFAULTTYPE,
+ CIL_DEFAULTRANGE,
+ CIL_HANDLEUNKNOWN,
+ CIL_MLS,
+
+/*
+ * 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_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,
+};
+
+
+#endif /* CIL_FLAVOR_H_ */
diff --git a/cil/src/cil_fqn.c b/cil/src/cil_fqn.c
new file mode 100644
index 0000000..d745988
--- /dev/null
+++ b/cil/src/cil_fqn.c
@@ -0,0 +1,221 @@
+/*
+ * 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 <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "cil_internal.h"
+#include "cil_log.h"
+#include "cil_mem.h"
+#include "cil_tree.h"
+#include "cil_strpool.h"
+
+struct cil_args_qualify {
+ char fqparent[CIL_MAX_NAME_LENGTH];
+ int len;
+};
+
+int __cil_fqn_qualify_last_child_helper(struct cil_tree_node *node, void *extra_args)
+{
+ struct cil_args_qualify *args = NULL;
+ struct cil_symtab_datum *datum = NULL;
+ int rc = SEPOL_ERR;
+
+ if (node == NULL || extra_args == NULL) {
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+
+ if (node->parent->flavor != CIL_BLOCK) {
+ rc = SEPOL_OK;
+ goto exit;
+ }
+
+ datum = node->parent->data;
+ args = extra_args;
+ args->len -= (strlen(datum->name) + 1);
+ args->fqparent[args->len] = '\0';
+
+ return SEPOL_OK;
+
+exit:
+ return rc;
+}
+
+int __cil_fqn_qualify_first_child_helper(struct cil_tree_node *node, void *extra_args)
+{
+ struct cil_args_qualify *args = NULL;
+ struct cil_symtab_datum *datum = NULL;
+ int rc = SEPOL_ERR;
+
+ if (node == NULL || extra_args == NULL) {
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+
+ if (node->parent->flavor != CIL_BLOCK) {
+ rc = SEPOL_OK;
+ goto exit;
+ }
+
+ args = extra_args;
+ datum = node->parent->data;
+
+ if (args->len + strlen(datum->name) + 1 >= CIL_MAX_NAME_LENGTH) {
+ cil_log(CIL_INFO, "Fully qualified name too long at line %d of %s\n",
+ node->line, node->path);
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+
+ strcat(args->fqparent, datum->name);
+ strcat(args->fqparent, ".");
+ args->len += (strlen(datum->name) + 1);
+
+ return SEPOL_OK;
+
+exit:
+ return rc;
+}
+
+int __cil_fqn_qualify_node_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args)
+{
+ struct cil_args_qualify *args = NULL;
+ struct cil_symtab_datum *datum = NULL;
+ char *fqn = NULL;
+ int newlen = 0;
+ int rc = SEPOL_ERR;
+
+ if (node == NULL || finished == NULL || extra_args == NULL) {
+ goto exit;
+ }
+
+ if (node->flavor < CIL_MIN_DECLARATIVE || node->flavor == CIL_PERM || node->flavor == CIL_MAP_PERM) {
+ rc = SEPOL_OK;
+ goto exit;
+ }
+
+ args = extra_args;
+ datum = node->data;
+
+ switch (node->flavor) {
+ case CIL_OPTIONAL:
+ if (datum->state == CIL_STATE_DISABLED) {
+ *finished = CIL_TREE_SKIP_HEAD;
+ }
+ break;
+ case CIL_MACRO:
+ *finished = CIL_TREE_SKIP_HEAD;
+ break;
+ case CIL_BLOCK:
+ if (((struct cil_block *)datum)->is_abstract == CIL_TRUE) {
+ *finished = CIL_TREE_SKIP_HEAD;
+ }
+ break;
+ case CIL_STRING:
+ case CIL_NAME:
+ /* Strings don't change */
+ break;
+ case CIL_TYPEATTRIBUTE:
+ case CIL_ROLEATTRIBUTE:
+ case CIL_BOOL:
+ case CIL_CAT:
+ case CIL_CATALIAS:
+ case CIL_CATSET:
+ case CIL_CLASS:
+ case CIL_MAP_CLASS:
+ case CIL_CLASSPERMISSION:
+ case CIL_COMMON:
+ case CIL_CONTEXT:
+ case CIL_IPADDR:
+ case CIL_LEVEL:
+ case CIL_LEVELRANGE:
+ case CIL_POLICYCAP:
+ case CIL_ROLE:
+ case CIL_SENS:
+ case CIL_SENSALIAS:
+ case CIL_SID:
+ case CIL_TUNABLE:
+ case CIL_TYPE:
+ case CIL_TYPEALIAS:
+ case CIL_USER:
+ if (node != ((struct cil_symtab_datum*)node->data)->nodes->head->data) {
+ break;
+ }
+
+ if (args->len == 0) {
+ rc = SEPOL_OK;
+ goto exit;
+ }
+
+ newlen = args->len + strlen(datum->name);
+ if (newlen >= CIL_MAX_NAME_LENGTH) {
+ cil_log(CIL_INFO, "Fully qualified name too long at line %d of %s\n",
+ node->line, node->path);
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+ fqn = cil_malloc(newlen + 1);
+ strcpy(fqn, args->fqparent);
+ strcat(fqn, datum->name);
+
+ datum->name = cil_strpool_add(fqn);
+ free(fqn);
+ break;
+ default:
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+
+ return SEPOL_OK;
+
+exit:
+ return rc;
+}
+
+int cil_fqn_qualify(struct cil_tree_node *root)
+{
+ struct cil_args_qualify extra_args;
+ int rc = SEPOL_ERR;
+
+ extra_args.fqparent[0] = '\0';
+ extra_args.len = 0;
+
+ rc = cil_tree_walk(root, __cil_fqn_qualify_node_helper, __cil_fqn_qualify_first_child_helper, __cil_fqn_qualify_last_child_helper, &extra_args);
+ if (rc != SEPOL_OK) {
+ goto exit;
+ }
+
+ return SEPOL_OK;
+
+exit:
+ return rc;
+}
+
diff --git a/cil/src/cil_fqn.h b/cil/src/cil_fqn.h
new file mode 100644
index 0000000..bbd249a
--- /dev/null
+++ b/cil/src/cil_fqn.h
@@ -0,0 +1,38 @@
+/*
+ * 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);
+
+#endif /* CIL_FQN_H_ */
diff --git a/cil/src/cil_internal.h b/cil/src/cil_internal.h
new file mode 100644
index 0000000..3c92674
--- /dev/null
+++ b/cil/src/cil_internal.h
@@ -0,0 +1,960 @@
+/*
+ * 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 <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <arpa/inet.h>
+
+#include <sepol/policydb/services.h>
+#include <sepol/policydb/policydb.h>
+
+#include <cil/cil.h>
+
+#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,
+ 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_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_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_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_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_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;
+
+/*
+ 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_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
+
+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 *portcon;
+ struct cil_sort *pirqcon;
+ struct cil_sort *iomemcon;
+ struct cil_sort *ioportcon;
+ struct cil_sort *pcidevicecon;
+ struct cil_sort *fsuse;
+ struct cil_list *userprefixes;
+ struct cil_list *selinuxusers;
+ struct cil_list *names;
+ int num_cats;
+ int num_types;
+ int num_roles;
+ struct cil_type **val_to_type;
+ struct cil_role **val_to_role;
+ int disable_dontaudit;
+ int disable_neverallow;
+ int preserve_tunables;
+ int handle_unknown;
+ int mls;
+};
+
+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_blockinherit {
+ char *block_str;
+};
+
+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;
+};
+
+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;
+ struct cil_list *roles;
+ struct cil_level *dftlevel;
+ struct cil_levelrange *range;
+};
+
+struct cil_userrole {
+ char *user_str;
+ struct cil_user *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;
+};
+
+struct cil_typeattribute {
+ struct cil_symtab_datum datum;
+ struct cil_list *expr_list;
+ ebitmap_t *types;
+ int used; // whether or not this typeattribute was used and should be added to the binary
+};
+
+struct cil_typeattributeset {
+ char *attr_str;
+ struct cil_list *str_expr;
+ struct cil_list *datum_expr;
+};
+
+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 {
+ uint32_t rule_kind;
+ char *src_str;
+ void *src; /* type, alias, or attribute */
+ char *tgt_str;
+ void *tgt; /* type, alias, or attribute */
+ struct cil_list *classperms;
+};
+
+#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
+};
+
+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_pirqcon {
+ uint32_t pirq;
+ char *context_str;
+ struct cil_context *context;
+};
+
+struct cil_iomemcon {
+ uint32_t iomem_low;
+ uint32_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;
+};
+
+/* 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;
+};
+
+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, sepol_policydb_t *sepol_db, char **out, size_t *size);
+int cil_selinuxusers_to_string(struct cil_db *db, sepol_policydb_t *sepol_db, char **out, size_t *size);
+int cil_filecons_to_string(struct cil_db *db, sepol_policydb_t *sepol_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_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_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_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_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_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);
+
+#endif
diff --git a/cil/src/cil_lexer.h b/cil/src/cil_lexer.h
new file mode 100644
index 0000000..1537d5e
--- /dev/null
+++ b/cil/src/cil_lexer.h
@@ -0,0 +1,53 @@
+/*
+ * 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 <stdint.h>
+
+#define OPAREN 1
+#define CPAREN 2
+#define SYMBOL 3
+#define QSTRING 4
+#define COMMENT 5
+#define END_OF_FILE 6
+#define UNKNOWN 7
+
+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_ */
diff --git a/cil/src/cil_lexer.l b/cil/src/cil_lexer.l
new file mode 100644
index 0000000..8e4c207
--- /dev/null
+++ b/cil/src/cil_lexer.l
@@ -0,0 +1,93 @@
+/*
+ * 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 <stdint.h>
+ #include <sepol/errcodes.h>
+ #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]*\"
+comment ;[^\n]*
+
+%%
+{newline} line++;
+{comment} value=yytext; return COMMENT;
+"(" value=yytext; return OPAREN;
+")" value=yytext; return CPAREN;
+{symbol} value=yytext; return SYMBOL;
+{white} //cil_log(CIL_INFO, "white, ");
+{qstring} value=yytext; return QSTRING;
+<<EOF>> 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;
+}
+
diff --git a/cil/src/cil_list.c b/cil/src/cil_list.c
new file mode 100644
index 0000000..e1e6ec1
--- /dev/null
+++ b/cil/src/cil_list.c
@@ -0,0 +1,218 @@
+/*
+ * 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 <stdlib.h>
+
+#include "cil_internal.h"
+#include "cil_flavor.h"
+#include "cil_log.h"
+#include "cil_mem.h"
+
+__attribute__((noreturn)) void cil_list_error(const char* msg)
+{
+ cil_log(CIL_ERR, "%s\n",msg);
+ 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;
+}
diff --git a/cil/src/cil_list.h b/cil/src/cil_list.h
new file mode 100644
index 0000000..de927fc
--- /dev/null
+++ b/cil/src/cil_list.h
@@ -0,0 +1,61 @@
+/*
+ * 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);
+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);
+
+#endif
diff --git a/cil/src/cil_log.c b/cil/src/cil_log.c
new file mode 100644
index 0000000..c2c5b6f
--- /dev/null
+++ b/cil/src/cil_log.c
@@ -0,0 +1,67 @@
+/*
+ * 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 <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include <cil/cil.h>
+#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, 3))) void cil_log(enum cil_log_level lvl, const char *msg, ...)
+{
+ if (cil_log_level >= lvl) {
+ char buff[MAX_LOG_SIZE];
+ va_list args;
+ va_start(args, msg);
+ vsnprintf(buff, MAX_LOG_SIZE, msg, args);
+ va_end(args);
+ (*cil_log_handler)(cil_log_level, buff);
+ }
+}
+
+void cil_set_log_level(enum cil_log_level lvl)
+{
+ cil_log_level = lvl;
+}
diff --git a/cil/src/cil_log.h b/cil/src/cil_log.h
new file mode 100644
index 0000000..9c2ff2e
--- /dev/null
+++ b/cil/src/cil_log.h
@@ -0,0 +1,39 @@
+/*
+ * 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 <stdlib.h>
+#include <cil/cil.h>
+
+#define MAX_LOG_SIZE 512
+
+__attribute__ ((format(printf, 2, 3))) void cil_log(enum cil_log_level lvl, const char *msg, ...);
+
+#endif // CIL_LOG_H_
diff --git a/cil/src/cil_mem.c b/cil/src/cil_mem.c
new file mode 100644
index 0000000..e19bc35
--- /dev/null
+++ b/cil/src/cil_mem.c
@@ -0,0 +1,100 @@
+/*
+ * 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 <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#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;
+}
diff --git a/cil/src/cil_mem.h b/cil/src/cil_mem.h
new file mode 100644
index 0000000..3e4263c
--- /dev/null
+++ b/cil/src/cil_mem.h
@@ -0,0 +1,41 @@
+/*
+ * 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);
+void (*cil_mem_error_handler)(void);
+
+#endif /* CIL_MEM_H_ */
+
diff --git a/cil/src/cil_parser.c b/cil/src/cil_parser.c
new file mode 100644
index 0000000..43df1df
--- /dev/null
+++ b/cil/src/cil_parser.c
@@ -0,0 +1,134 @@
+/*
+ * 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 <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <sepol/errcodes.h>
+
+#include "cil_internal.h"
+#include "cil_log.h"
+#include "cil_mem.h"
+#include "cil_tree.h"
+#include "cil_lexer.h"
+#include "cil_strpool.h"
+
+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 *item = NULL;
+ struct cil_tree_node *current = NULL;
+
+ struct token tok;
+
+ cil_lexer_setup(buffer, size);
+
+ tree = *parse_tree;
+ current = tree->root;
+
+ do {
+ cil_lexer_next(&tok);
+ switch (tok.type) {
+ case OPAREN:
+ paren_count++;
+ cil_tree_node_init(&node);
+ node->parent = current;
+ node->flavor = CIL_NODE;
+ node->line = tok.line;
+ node->path = path;
+ if (current->cl_head == NULL) {
+ current->cl_head = node;
+ } else {
+ current->cl_tail->next = node;
+ }
+ current->cl_tail = node;
+ 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);
+ return SEPOL_ERR;
+ }
+ current = current->parent;
+ break;
+ case SYMBOL:
+ case QSTRING:
+ if (paren_count == 0) {
+ cil_log(CIL_ERR, "Symbol not inside parenthesis at line %d of %s\n", tok.line, path);
+ return SEPOL_ERR;
+ }
+ cil_tree_node_init(&item);
+ item->parent = current;
+ if (tok.type == QSTRING) {
+ tok.value[strlen(tok.value) - 1] = '\0';
+ item->data = cil_strpool_add(tok.value + 1);
+ } else {
+ item->data = cil_strpool_add(tok.value);
+ }
+ item->flavor = CIL_NODE;
+ item->line = tok.line;
+ item->path = path;
+ if (current->cl_head == NULL) {
+ current->cl_head = item;
+ } else {
+ current->cl_tail->next = item;
+ }
+ current->cl_tail = item;
+ break;
+ 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);
+ return SEPOL_ERR;
+ }
+ break;
+ case COMMENT:
+ // ignore
+ break;
+ case UNKNOWN:
+ cil_log(CIL_ERR, "Invalid token '%s' at line %d of %s\n", tok.value, tok.line, path);
+ return SEPOL_ERR;
+ default:
+ cil_log(CIL_ERR, "Unknown token type '%d' at line %d of %s\n", tok.type, tok.line, path);
+ return SEPOL_ERR;
+ }
+ }
+ while (tok.type != END_OF_FILE);
+
+ cil_lexer_destroy();
+
+ *parse_tree = tree;
+
+ return SEPOL_OK;
+}
diff --git a/cil/src/cil_parser.h b/cil/src/cil_parser.h
new file mode 100644
index 0000000..02ecb78
--- /dev/null
+++ b/cil/src/cil_parser.h
@@ -0,0 +1,37 @@
+/*
+ * 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_ */
diff --git a/cil/src/cil_policy.c b/cil/src/cil_policy.c
new file mode 100644
index 0000000..d19accb
--- /dev/null
+++ b/cil/src/cil_policy.c
@@ -0,0 +1,1435 @@
+/*
+ * 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 <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <unistd.h>
+
+#include <sepol/policydb/conditional.h>
+#include <sepol/errcodes.h>
+
+#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_policy.h"
+#include "cil_symtab.h"
+#include "cil_strpool.h"
+
+#define SEPOL_DONE 555
+
+#define CLASS_DECL 0
+#define ISIDS 1
+#define COMMONS 2
+#define CLASSES 3
+#define INTERFACES 4
+#define SENS 5
+#define CATS 6
+#define LEVELS 7
+#define CONSTRAINS 8
+#define TYPEATTRTYPES 9
+#define ALIASES 10
+#define ALLOWS 11
+#define CONDS 12
+#define USERROLES 13
+#define SIDS 14
+#define NETIFCONS 15
+
+#define BUFFER 1024
+#define NUM_POLICY_FILES 16
+
+struct cil_args_genpolicy {
+ struct cil_list *users;
+ struct cil_list *sens;
+ struct cil_list *cats;
+ FILE **file_arr;
+};
+
+struct cil_args_booleanif {
+ FILE **file_arr;
+ uint32_t *file_index;
+};
+
+
+int cil_expr_to_policy(FILE **file_arr, uint32_t file_index, struct cil_list *expr);
+
+int cil_combine_policy(FILE **file_arr, FILE *policy_file)
+{
+ char temp[BUFFER];
+ int i, rc, rc_read, rc_write;
+
+ for(i=0; i<NUM_POLICY_FILES; i++) {
+ fseek(file_arr[i], 0, SEEK_SET);
+ while (!feof(file_arr[i])) {
+ rc_read = fread(temp, 1, BUFFER, file_arr[i]);
+ if (rc_read == 0 && ferror(file_arr[i])) {
+ cil_log(CIL_ERR, "Error reading temp policy file\n");
+ return SEPOL_ERR;
+ }
+ rc_write = 0;
+ while (rc_read > rc_write) {
+ rc = fwrite(temp+rc_write, 1, rc_read-rc_write, policy_file);
+ rc_write += rc;
+ if (rc == 0 && ferror(file_arr[i])) {
+ cil_log(CIL_ERR, "Error writing to policy.conf\n");
+ return SEPOL_ERR;
+ }
+ }
+ }
+ }
+
+ return SEPOL_OK;
+}
+
+int cil_portcon_to_policy(FILE **file_arr, struct cil_sort *sort)
+{
+ uint32_t i = 0;
+
+ for (i=0; i<sort->count; i++) {
+ struct cil_portcon *portcon = (struct cil_portcon*)sort->array[i];
+ fprintf(file_arr[NETIFCONS], "portcon ");
+ if (portcon->proto == CIL_PROTOCOL_UDP) {
+ fprintf(file_arr[NETIFCONS], "udp ");
+ } else if (portcon->proto == CIL_PROTOCOL_TCP) {
+ fprintf(file_arr[NETIFCONS], "tcp ");
+ }
+ fprintf(file_arr[NETIFCONS], "%d ", portcon->port_low);
+ fprintf(file_arr[NETIFCONS], "%d ", portcon->port_high);
+ cil_context_to_policy(file_arr, NETIFCONS, portcon->context);
+ fprintf(file_arr[NETIFCONS], ";\n");
+ }
+
+ return SEPOL_OK;
+}
+
+int cil_genfscon_to_policy(FILE **file_arr, struct cil_sort *sort)
+{
+ uint32_t i = 0;
+
+ for (i=0; i<sort->count; i++) {
+ struct cil_genfscon *genfscon = (struct cil_genfscon*)sort->array[i];
+ fprintf(file_arr[NETIFCONS], "genfscon %s ", genfscon->fs_str);
+ fprintf(file_arr[NETIFCONS], "%s ", genfscon->path_str);
+ cil_context_to_policy(file_arr, NETIFCONS, genfscon->context);
+ fprintf(file_arr[NETIFCONS], ";\n");
+ }
+
+ return SEPOL_OK;
+}
+
+int cil_netifcon_to_policy(FILE **file_arr, struct cil_sort *sort)
+{
+ uint32_t i = 0;
+
+ for (i=0; i<sort->count; i++) {
+ struct cil_netifcon *netifcon = (struct cil_netifcon*)sort->array[i];
+ fprintf(file_arr[NETIFCONS], "netifcon %s ", netifcon->interface_str);
+ cil_context_to_policy(file_arr, NETIFCONS, netifcon->if_context);
+ fprintf(file_arr[NETIFCONS], " ");
+ cil_context_to_policy(file_arr, NETIFCONS, netifcon->packet_context);
+ fprintf(file_arr[NETIFCONS], ";\n");
+ }
+
+ return SEPOL_OK;
+}
+
+int cil_nodecon_to_policy(FILE **file_arr, struct cil_sort *sort)
+{
+ uint32_t i = 0;
+ int rc = SEPOL_ERR;
+
+ for (i=0; i<sort->count; i++) {
+ struct cil_nodecon *nodecon = (struct cil_nodecon*)sort->array[i];
+ char *buf = NULL;
+ errno = 0;
+ if (nodecon->addr->family == AF_INET) {
+ buf = cil_malloc(INET_ADDRSTRLEN);
+ inet_ntop(nodecon->addr->family, &nodecon->addr->ip.v4, buf, INET_ADDRSTRLEN);
+ } else if (nodecon->addr->family == AF_INET6) {
+ buf = cil_malloc(INET6_ADDRSTRLEN);
+ inet_ntop(nodecon->addr->family, &nodecon->addr->ip.v6, buf, INET6_ADDRSTRLEN);
+ }
+
+ if (errno != 0) {
+ cil_log(CIL_INFO, "Failed to convert ip address to string\n");
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+
+ fprintf(file_arr[NETIFCONS], "nodecon %s ", buf);
+ free(buf);
+
+ if (nodecon->mask->family == AF_INET) {
+ buf = cil_malloc(INET_ADDRSTRLEN);
+ inet_ntop(nodecon->mask->family, &nodecon->mask->ip.v4, buf, INET_ADDRSTRLEN);
+ } else if (nodecon->mask->family == AF_INET6) {
+ buf = cil_malloc(INET6_ADDRSTRLEN);
+ inet_ntop(nodecon->mask->family, &nodecon->mask->ip.v6, buf, INET6_ADDRSTRLEN);
+ }
+
+ if (errno != 0) {
+ cil_log(CIL_INFO, "Failed to convert mask to string\n");
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+
+ fprintf(file_arr[NETIFCONS], "%s ", buf);
+ free(buf);
+
+ cil_context_to_policy(file_arr, NETIFCONS, nodecon->context);
+ fprintf(file_arr[NETIFCONS], ";\n");
+ }
+
+ return SEPOL_OK;
+
+exit:
+ return rc;
+}
+
+
+int cil_pirqcon_to_policy(FILE **file_arr, struct cil_sort *sort)
+{
+ uint32_t i = 0;
+
+ for (i = 0; i < sort->count; i++) {
+ struct cil_pirqcon *pirqcon = (struct cil_pirqcon*)sort->array[i];
+ fprintf(file_arr[NETIFCONS], "pirqcon %d ", pirqcon->pirq);
+ cil_context_to_policy(file_arr, NETIFCONS, pirqcon->context);
+ fprintf(file_arr[NETIFCONS], ";\n");
+ }
+
+ return SEPOL_OK;
+}
+int cil_iomemcon_to_policy(FILE **file_arr, struct cil_sort *sort)
+{
+ uint32_t i = 0;
+
+ for (i = 0; i < sort->count; i++) {
+ struct cil_iomemcon *iomemcon = (struct cil_iomemcon*)sort->array[i];
+ fprintf(file_arr[NETIFCONS], "iomemcon %d-%d ", iomemcon->iomem_low, iomemcon->iomem_high);
+ cil_context_to_policy(file_arr, NETIFCONS, iomemcon->context);
+ fprintf(file_arr[NETIFCONS], ";\n");
+ }
+
+ return SEPOL_OK;
+}
+
+int cil_ioportcon_to_policy(FILE **file_arr, struct cil_sort *sort)
+{
+ uint32_t i = 0;
+
+ for (i = 0; i < sort->count; i++) {
+ struct cil_ioportcon *ioportcon = (struct cil_ioportcon*)sort->array[i];
+ fprintf(file_arr[NETIFCONS], "ioportcon %d-%d ", ioportcon->ioport_low, ioportcon->ioport_high);
+ cil_context_to_policy(file_arr, NETIFCONS, ioportcon->context);
+ fprintf(file_arr[NETIFCONS], ";\n");
+ }
+
+ return SEPOL_OK;
+}
+
+int cil_pcidevicecon_to_policy(FILE **file_arr, struct cil_sort *sort)
+{
+ uint32_t i = 0;
+
+ for (i = 0; i < sort->count; i++) {
+ struct cil_pcidevicecon *pcidevicecon = (struct cil_pcidevicecon*)sort->array[i];
+ fprintf(file_arr[NETIFCONS], "pcidevicecon %d ", pcidevicecon->dev);
+ cil_context_to_policy(file_arr, NETIFCONS, pcidevicecon->context);
+ fprintf(file_arr[NETIFCONS], ";\n");
+ }
+
+ return SEPOL_OK;
+}
+
+int cil_fsuse_to_policy(FILE **file_arr, struct cil_sort *sort)
+{
+ uint32_t i = 0;
+
+ for (i=0; i<sort->count; i++) {
+ struct cil_fsuse *fsuse = (struct cil_fsuse*)sort->array[i];
+ if (fsuse->type == CIL_FSUSE_XATTR) {
+ fprintf(file_arr[NETIFCONS], "fs_use_xattr ");
+ } else if (fsuse->type == CIL_FSUSE_TASK) {
+ fprintf(file_arr[NETIFCONS], "fs_use_task ");
+ } else if (fsuse->type == CIL_FSUSE_TRANS) {
+ fprintf(file_arr[NETIFCONS], "fs_use_trans ");
+ } else {
+ return SEPOL_ERR;
+ }
+ fprintf(file_arr[NETIFCONS], "%s ", fsuse->fs_str);
+ cil_context_to_policy(file_arr, NETIFCONS, fsuse->context);
+ fprintf(file_arr[NETIFCONS], ";\n");
+ }
+
+ return SEPOL_OK;
+}
+
+int cil_multimap_insert(struct cil_list *list, struct cil_symtab_datum *key, struct cil_symtab_datum *value, uint32_t key_flavor, uint32_t val_flavor)
+{
+ struct cil_list_item *curr_key;
+ struct cil_multimap_item *new_data;
+
+ if (list == NULL || key == NULL) {
+ return SEPOL_ERR;
+ }
+
+ cil_list_for_each(curr_key, list) {
+ struct cil_multimap_item *curr_multimap_item = curr_key->data;
+ if (curr_multimap_item != NULL) {
+ if (curr_multimap_item->key != NULL && curr_multimap_item->key == key) {
+ struct cil_list_item *curr_value;
+ cil_list_for_each(curr_value, curr_multimap_item->values) {
+ if (curr_value == (struct cil_list_item*)value) {
+ return SEPOL_OK;;
+ }
+ }
+ cil_list_append(curr_multimap_item->values, val_flavor, value);
+ }
+ } else {
+ cil_log(CIL_INFO, "No data in list item\n");
+ return SEPOL_ERR;
+ }
+ }
+
+ new_data = cil_malloc(sizeof(*new_data));
+ new_data->key = key;
+ cil_list_init(&new_data->values, CIL_LIST_ITEM);
+ if (value != NULL) {
+ cil_list_append(new_data->values, val_flavor, value);
+ }
+ cil_list_append(list, key_flavor, new_data);
+
+ return SEPOL_OK;
+}
+
+int cil_userrole_to_policy(FILE **file_arr, struct cil_list *userroles)
+{
+ struct cil_list_item *current_user;
+
+ if (userroles == NULL) {
+ return SEPOL_OK;
+ }
+
+ cil_list_for_each(current_user, userroles) {
+ struct cil_multimap_item *user_multimap_item = current_user->data;
+ struct cil_list_item *current_role;
+ if (user_multimap_item->values->head == NULL) {
+ cil_log(CIL_INFO, "No roles associated with user %s\n",
+ user_multimap_item->key->name);
+ return SEPOL_ERR;
+ }
+
+ fprintf(file_arr[USERROLES], "user %s roles {", user_multimap_item->key->name);
+
+ cil_list_for_each(current_role, user_multimap_item->values) {
+ fprintf(file_arr[USERROLES], " %s", ((struct cil_role*)current_role->data)->datum.name);
+ }
+ fprintf(file_arr[USERROLES], " };\n");
+ }
+
+ return SEPOL_OK;
+}
+
+int cil_cat_to_policy(FILE **file_arr, struct cil_list *cats)
+{
+ struct cil_list_item *curr_cat;
+
+ if (cats == NULL) {
+ return SEPOL_OK;
+ }
+
+ cil_list_for_each(curr_cat, cats) {
+ struct cil_multimap_item *cat_multimap_item = curr_cat->data;
+ fprintf(file_arr[CATS], "category %s", cat_multimap_item->key->name);
+ if (cat_multimap_item->values->head == NULL) {
+ fprintf(file_arr[CATS], ";\n");
+ } else {
+ struct cil_list_item *curr_catalias;
+ fprintf(file_arr[CATS], " alias");
+ cil_list_for_each(curr_catalias, cat_multimap_item->values) {
+ fprintf(file_arr[CATS], " %s", ((struct cil_cat*)curr_catalias->data)->datum.name);
+ }
+ fprintf(file_arr[CATS], ";\n");
+ }
+ }
+
+ return SEPOL_OK;
+}
+
+int cil_sens_to_policy(FILE **file_arr, struct cil_list *sens)
+{
+ struct cil_list_item *curr_sens;
+
+ if (sens == NULL) {
+ return SEPOL_OK;
+ }
+
+ cil_list_for_each(curr_sens, sens) {
+ struct cil_multimap_item *sens_multimap_item = curr_sens->data;
+ fprintf(file_arr[SENS], "sensitivity %s", sens_multimap_item->key->name);
+ if (sens_multimap_item->values->head == NULL)
+ fprintf(file_arr[SENS], ";\n");
+ else {
+ struct cil_list_item *curr_sensalias;
+ fprintf(file_arr[SENS], " alias");
+ cil_list_for_each(curr_sensalias, sens_multimap_item->values) {
+ fprintf(file_arr[SENS], " %s", ((struct cil_sens*)curr_sensalias->data)->datum.name);
+ }
+ fprintf(file_arr[SENS], ";\n");
+ }
+ }
+
+ return SEPOL_OK;
+}
+
+void cil_cats_to_policy(FILE **file_arr, uint32_t file_index, struct cil_cats *cats)
+{
+ cil_expr_to_policy(file_arr, file_index, cats->datum_expr);
+}
+
+void cil_level_to_policy(FILE **file_arr, uint32_t file_index, struct cil_level *level)
+{
+ char *sens_str = level->sens->datum.name;
+
+ fprintf(file_arr[file_index], "%s", sens_str);
+ if (level->cats != NULL) {
+ fprintf(file_arr[file_index], ":");
+ cil_cats_to_policy(file_arr, file_index, level->cats);
+ }
+}
+
+void cil_levelrange_to_policy(FILE **file_arr, uint32_t file_index, struct cil_levelrange *lvlrange)
+{
+ struct cil_level *low = lvlrange->low;
+ struct cil_level *high = lvlrange->high;
+
+ cil_level_to_policy(file_arr, file_index, low);
+ fprintf(file_arr[file_index], "-");
+ cil_level_to_policy(file_arr, file_index, high);
+}
+
+void cil_context_to_policy(FILE **file_arr, uint32_t file_index, struct cil_context *context)
+{
+ char *user_str = ((struct cil_symtab_datum*)context->user)->name;
+ char *role_str = ((struct cil_symtab_datum*)context->role)->name;
+ char *type_str = ((struct cil_symtab_datum*)context->type)->name;
+ struct cil_levelrange *lvlrange = context->range;
+
+ fprintf(file_arr[file_index], "%s:%s:%s:", user_str, role_str, type_str);
+ cil_levelrange_to_policy(file_arr, file_index, lvlrange);
+}
+
+void cil_perms_to_policy(FILE **file_arr, uint32_t file_index, struct cil_list *list)
+{
+ struct cil_list_item *curr;
+
+ fprintf(file_arr[file_index], " {");
+ cil_list_for_each(curr, list) {
+ switch (curr->flavor) {
+ case CIL_LIST:
+ cil_perms_to_policy(file_arr, file_index, curr->data);
+ break;
+ case CIL_STRING:
+ fprintf(file_arr[file_index], " %s", (char *)curr->data);
+ break;
+ case CIL_DATUM:
+ fprintf(file_arr[file_index], " %s", ((struct cil_symtab_datum *)curr->data)->name);
+ break;
+ case CIL_OP: {
+ enum cil_flavor op_flavor = *((enum cil_flavor *)curr->data);
+ char *op_str = NULL;
+
+ 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_XOR:
+ op_str = CIL_KEY_XOR;
+ break;
+ default:
+ cil_log(CIL_ERR, "Unknown operator in expression\n");
+ break;
+ }
+ fprintf(file_arr[file_index], " %s", op_str);
+ break;
+ }
+ default:
+ cil_log(CIL_ERR, "Unknown flavor in expression\n");
+ break;
+ }
+ }
+ fprintf(file_arr[file_index], " }");
+}
+
+void cil_constrain_to_policy_helper(FILE **file_arr, char *kind, struct cil_list *classperms, struct cil_list *expr)
+{
+ 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) {
+ fprintf(file_arr[CONSTRAINS], "%s %s", kind, cp->class->datum.name);
+ cil_perms_to_policy(file_arr, CONSTRAINS, cp->perms);
+ fprintf(file_arr[CONSTRAINS], "\n\t");
+ cil_expr_to_policy(file_arr, CONSTRAINS, expr);
+ fprintf(file_arr[CONSTRAINS], ";\n");
+ } else { /* MAP */
+ struct cil_list_item *i = NULL;
+ cil_list_for_each(i, cp->perms) {
+ struct cil_perm *cmp = i->data;
+ cil_constrain_to_policy_helper(file_arr, kind, cmp->classperms, expr);
+ }
+ }
+ } else { /* SET */
+ struct cil_classperms_set *cp_set = curr->data;
+ struct cil_classpermission *cp = cp_set->set;
+ cil_constrain_to_policy_helper(file_arr, kind, cp->classperms, expr);
+ }
+ }
+}
+
+void cil_constrain_to_policy(FILE **file_arr, __attribute__((unused)) uint32_t file_index, struct cil_constrain *cons, enum cil_flavor flavor)
+{
+ char *kind = NULL;
+
+ if (flavor == CIL_CONSTRAIN) {
+ kind = CIL_KEY_CONSTRAIN;
+ } else if (flavor == CIL_MLSCONSTRAIN) {
+ kind = CIL_KEY_MLSCONSTRAIN;
+ }
+
+ cil_constrain_to_policy_helper(file_arr, kind, cons->classperms, cons->datum_expr);
+}
+
+void cil_avrule_to_policy_helper(FILE **file_arr, uint32_t file_index, const char *kind, const char *src, const char *tgt, struct cil_list *classperms)
+{
+ 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) {
+ fprintf(file_arr[file_index], "%s %s %s: %s", kind, src, tgt, cp->class->datum.name);
+ cil_perms_to_policy(file_arr, file_index, cp->perms);
+ fprintf(file_arr[file_index], ";\n");
+ } else { /* MAP */
+ struct cil_list_item *j = NULL;
+ cil_list_for_each(j, cp->perms) {
+ struct cil_perm *cmp = j->data;
+ cil_avrule_to_policy_helper(file_arr, file_index, kind, src, tgt, cmp->classperms);
+ }
+ }
+ } else { /* SET */
+ struct cil_list_item *j;
+ struct cil_classperms_set *cp_set = i->data;
+ struct cil_classpermission *cp = cp_set->set;
+ cil_list_for_each(j, cp->classperms) {
+ cil_avrule_to_policy_helper(file_arr, file_index, kind, src, tgt, j->data);
+ }
+ }
+ }
+}
+
+int cil_avrule_to_policy(FILE **file_arr, uint32_t file_index, struct cil_avrule *rule)
+{
+ const char *kind_str = NULL;
+ const char *src_str = DATUM(rule->src)->name;
+ const char *tgt_str = DATUM(rule->tgt)->name;
+
+
+ switch (rule->rule_kind) {
+ case CIL_AVRULE_ALLOWED:
+ kind_str = "allow";
+ break;
+ case CIL_AVRULE_AUDITALLOW:
+ kind_str = "auditallow";
+ break;
+ case CIL_AVRULE_DONTAUDIT:
+ kind_str = "dontaudit";
+ break;
+ case CIL_AVRULE_NEVERALLOW:
+ kind_str = "neverallow";
+ break;
+ default :
+ cil_log(CIL_INFO, "Unknown avrule with kind=%d src=%s tgt=%s\n",
+ rule->rule_kind, src_str, tgt_str);
+ return SEPOL_ERR;
+ }
+
+ cil_avrule_to_policy_helper(file_arr, file_index, kind_str, src_str, tgt_str, rule->classperms);
+
+ return SEPOL_OK;
+}
+
+int cil_typerule_to_policy(FILE **file_arr, __attribute__((unused)) uint32_t file_index, struct cil_type_rule *rule)
+{
+ char *src_str = ((struct cil_symtab_datum*)rule->src)->name;
+ char *tgt_str = ((struct cil_symtab_datum*)rule->tgt)->name;
+ char *obj_str = ((struct cil_symtab_datum*)rule->obj)->name;
+ char *result_str = ((struct cil_symtab_datum*)rule->result)->name;
+
+ switch (rule->rule_kind) {
+ case CIL_TYPE_TRANSITION:
+ fprintf(file_arr[ALLOWS], "type_transition %s %s : %s %s;\n", src_str, tgt_str, obj_str, result_str);
+ break;
+ case CIL_TYPE_CHANGE:
+ fprintf(file_arr[ALLOWS], "type_change %s %s : %s %s\n;", src_str, tgt_str, obj_str, result_str);
+ break;
+ case CIL_TYPE_MEMBER:
+ fprintf(file_arr[ALLOWS], "type_member %s %s : %s %s;\n", src_str, tgt_str, obj_str, result_str);
+ break;
+ default:
+ cil_log(CIL_INFO, "Unknown type_rule\n");
+ return SEPOL_ERR;
+ }
+
+ return SEPOL_OK;
+}
+
+int cil_nametypetransition_to_policy(FILE **file_arr, uint32_t file_index, struct cil_nametypetransition *nametypetrans)
+{
+ char *src_str = ((struct cil_symtab_datum*)nametypetrans->src)->name;
+ char *tgt_str = ((struct cil_symtab_datum*)nametypetrans->tgt)->name;
+ char *obj_str = ((struct cil_symtab_datum*)nametypetrans->obj)->name;
+ char *result_str = ((struct cil_symtab_datum*)nametypetrans->result)->name;
+
+ fprintf(file_arr[file_index], "type_transition %s %s : %s %s %s;\n", src_str, tgt_str, obj_str, result_str, nametypetrans->name_str);
+ return SEPOL_OK;
+}
+
+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;
+ int i;
+
+ 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_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)", stack[pos-1], op_str, 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:
+ for (i = 0; i < pos; i++) {
+ free(stack[i]);
+ }
+ return rc;
+}
+
+int cil_expr_to_policy(FILE **file_arr, uint32_t file_index, struct cil_list *expr)
+{
+ int rc = SEPOL_ERR;
+ char *str_out;
+
+ rc = cil_expr_to_string(expr, &str_out);
+ if (rc != SEPOL_OK) {
+ goto out;
+ }
+ fprintf(file_arr[file_index], "%s", str_out);
+ free(str_out);
+
+ return SEPOL_OK;
+
+out:
+ return rc;
+}
+
+int __cil_booleanif_node_helper(struct cil_tree_node *node, __attribute__((unused)) uint32_t *finished, void *extra_args)
+{
+ int rc = SEPOL_ERR;
+ struct cil_args_booleanif *args;
+ FILE **file_arr;
+ uint32_t *file_index;
+
+ args = extra_args;
+ file_arr = args->file_arr;
+ file_index = args->file_index;
+
+ switch (node->flavor) {
+ case CIL_AVRULE:
+ rc = cil_avrule_to_policy(file_arr, *file_index, (struct cil_avrule*)node->data);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_INFO, "cil_avrule_to_policy failed, rc: %d\n", rc);
+ return rc;
+ }
+ break;
+ case CIL_TYPE_RULE:
+ rc = cil_typerule_to_policy(file_arr, *file_index, (struct cil_type_rule*)node->data);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_INFO, "cil_typerule_to_policy failed, rc: %d\n", rc);
+ return rc;
+ }
+ break;
+ case CIL_FALSE:
+ fprintf(file_arr[*file_index], "else {\n");
+ break;
+ case CIL_TRUE:
+ break;
+ default:
+ return SEPOL_ERR;
+ }
+
+ return SEPOL_OK;
+}
+
+int __cil_booleanif_last_child_helper(struct cil_tree_node *node, void *extra_args)
+{
+ struct cil_args_booleanif *args;
+ FILE **file_arr;
+ uint32_t *file_index;
+
+ args = extra_args;
+ file_arr = args->file_arr;
+ file_index = args->file_index;
+
+ if (node->parent->flavor == CIL_FALSE) {
+ fprintf(file_arr[*file_index], "}\n");
+ }
+
+ return SEPOL_OK;
+}
+
+int cil_booleanif_to_policy(FILE **file_arr, uint32_t file_index, struct cil_tree_node *node)
+{
+ int rc = SEPOL_ERR;
+ struct cil_booleanif *bif = node->data;
+ struct cil_list *expr = bif->datum_expr;
+ struct cil_args_booleanif extra_args;
+ struct cil_tree_node *true_node = NULL;
+ struct cil_tree_node *false_node = NULL;
+ struct cil_condblock *cb = NULL;
+
+ extra_args.file_arr = file_arr;
+ extra_args.file_index = &file_index;;
+
+ fprintf(file_arr[file_index], "if ");
+
+ rc = cil_expr_to_policy(file_arr, file_index, expr);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_ERR, "Failed to write expression\n");
+ return rc;
+ }
+
+ if (node->cl_head != NULL && node->cl_head->flavor == CIL_CONDBLOCK) {
+ cb = node->cl_head->data;
+ if (cb->flavor == CIL_CONDTRUE) {
+ true_node = node->cl_head;
+ } else if (cb->flavor == CIL_CONDFALSE) {
+ false_node = node->cl_head;
+ }
+ }
+
+ if (node->cl_head != NULL && node->cl_head->next != NULL && node->cl_head->next->flavor == CIL_CONDBLOCK) {
+ cb = node->cl_head->next->data;
+ if (cb->flavor == CIL_CONDTRUE) {
+ true_node = node->cl_head->next;
+ } else if (cb->flavor == CIL_CONDFALSE) {
+ false_node = node->cl_head->next;
+ }
+ }
+
+ fprintf(file_arr[file_index], "{\n");
+ if (true_node != NULL) {
+ rc = cil_tree_walk(true_node, __cil_booleanif_node_helper, __cil_booleanif_last_child_helper, NULL, &extra_args);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_INFO, "Failed to write booleanif content to file, rc: %d\n", rc);
+ return rc;
+ }
+ }
+ fprintf(file_arr[file_index], "}\n");
+
+ if (false_node != NULL) {
+ fprintf(file_arr[file_index], "else {\n");
+ rc = cil_tree_walk(false_node, __cil_booleanif_node_helper, __cil_booleanif_last_child_helper, NULL, &extra_args);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_INFO, "Failed to write booleanif false content to file, rc: %d\n", rc);
+ return rc;
+ }
+ fprintf(file_arr[file_index], "}\n");
+ }
+
+ return SEPOL_OK;
+}
+
+int cil_name_to_policy(FILE **file_arr, struct cil_tree_node *current)
+{
+ uint32_t flavor = current->flavor;
+ int rc = SEPOL_ERR;
+
+ switch(flavor) {
+ case CIL_TYPEATTRIBUTE:
+ fprintf(file_arr[TYPEATTRTYPES], "attribute %s;\n", ((struct cil_symtab_datum*)current->data)->name);
+ break;
+ case CIL_TYPE:
+ fprintf(file_arr[TYPEATTRTYPES], "type %s;\n", ((struct cil_symtab_datum*)current->data)->name);
+ break;
+ case CIL_TYPEALIAS: {
+ struct cil_alias *alias = current->data;
+ fprintf(file_arr[ALIASES], "typealias %s alias %s;\n", ((struct cil_symtab_datum*)alias->actual)->name, ((struct cil_symtab_datum*)current->data)->name);
+ break;
+ }
+ case CIL_TYPEBOUNDS: {
+ struct cil_bounds *bnds = current->data;
+ fprintf(file_arr[ALLOWS], "typebounds %s %s;\n", bnds->parent_str, bnds->child_str);
+ break;
+ }
+ case CIL_TYPEPERMISSIVE: {
+ struct cil_typepermissive *typeperm = (struct cil_typepermissive*)current->data;
+ fprintf(file_arr[TYPEATTRTYPES], "permissive %s;\n", ((struct cil_symtab_datum*)typeperm->type)->name);
+ break;
+ }
+ case CIL_ROLE:
+ fprintf(file_arr[TYPEATTRTYPES], "role %s;\n", ((struct cil_symtab_datum*)current->data)->name);
+ break;
+ case CIL_BOOL: {
+ const char *boolean = ((struct cil_bool*)current->data)->value ? "true" : "false";
+ fprintf(file_arr[TYPEATTRTYPES], "bool %s %s;\n", ((struct cil_symtab_datum*)current->data)->name, boolean);
+ break;
+ }
+ case CIL_COMMON:
+ fprintf(file_arr[COMMONS], "common %s", ((struct cil_symtab_datum*)current->data)->name);
+
+ if (current->cl_head != NULL) {
+ current = current->cl_head;
+ fprintf(file_arr[COMMONS], " {");
+ } else {
+ cil_log(CIL_INFO, "No permissions given\n");
+ return SEPOL_ERR;
+ }
+
+ while (current != NULL) {
+ if (current->flavor == CIL_PERM) {
+ fprintf(file_arr[COMMONS], "%s ", ((struct cil_symtab_datum*)current->data)->name);
+ } else {
+ cil_log(CIL_INFO, "Improper data type found in common permissions: %d\n", current->flavor);
+ return SEPOL_ERR;
+ }
+ current = current->next;
+ }
+ fprintf(file_arr[COMMONS], "}\n");
+
+ return SEPOL_DONE;
+ case CIL_AVRULE: {
+ struct cil_avrule *avrule = (struct cil_avrule*)current->data;
+ rc = cil_avrule_to_policy(file_arr, ALLOWS, avrule);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_INFO, "Failed to write avrule to policy\n");
+ return rc;
+ }
+ break;
+ }
+ case CIL_TYPE_RULE: {
+ struct cil_type_rule *rule = (struct cil_type_rule*)current->data;
+ rc = cil_typerule_to_policy(file_arr, ALLOWS, rule);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_INFO, "Failed to write type rule to policy\n");
+ return rc;
+ }
+ break;
+ }
+ case CIL_NAMETYPETRANSITION: {
+ struct cil_nametypetransition *nametypetrans = (struct cil_nametypetransition*)current->data;
+ rc = cil_nametypetransition_to_policy(file_arr, ALLOWS, nametypetrans);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_INFO, "Failed to write nametypetransition to policy\n");
+ return rc;
+ }
+ }
+ case CIL_ROLETRANSITION: {
+ struct cil_roletransition *roletrans = (struct cil_roletransition*)current->data;
+ char *src_str = ((struct cil_symtab_datum*)roletrans->src)->name;
+ char *tgt_str = ((struct cil_symtab_datum*)roletrans->tgt)->name;
+ char *obj_str = ((struct cil_symtab_datum*)roletrans->obj)->name;
+ char *result_str = ((struct cil_symtab_datum*)roletrans->result)->name;
+
+ fprintf(file_arr[ALLOWS], "role_transition %s %s:%s %s;\n", src_str, tgt_str, obj_str, result_str);
+ break;
+ }
+ case CIL_ROLEALLOW: {
+ struct cil_roleallow *roleallow = (struct cil_roleallow*)current->data;
+ char *src_str = ((struct cil_symtab_datum*)roleallow->src)->name;
+ char *tgt_str = ((struct cil_symtab_datum*)roleallow->tgt)->name;
+
+ fprintf(file_arr[ALLOWS], "roleallow %s %s;\n", src_str, tgt_str);
+ break;
+ }
+ case CIL_ROLETYPE: {
+ struct cil_roletype *roletype = (struct cil_roletype*)current->data;
+ char *role_str = ((struct cil_symtab_datum*)roletype->role)->name;
+ char *type_str = ((struct cil_symtab_datum*)roletype->type)->name;
+
+ fprintf(file_arr[ALIASES], "role %s types %s\n", role_str, type_str);
+ break;
+ }
+ case CIL_LEVEL:
+ fprintf(file_arr[LEVELS], "level ");
+ cil_level_to_policy(file_arr, LEVELS, (struct cil_level*)current->data);
+ fprintf(file_arr[LEVELS], ";\n");
+ break;
+ case CIL_CONSTRAIN:
+ cil_constrain_to_policy(file_arr, CONSTRAINS, (struct cil_constrain*)current->data, flavor);
+ break;
+ case CIL_MLSCONSTRAIN:
+ cil_constrain_to_policy(file_arr, CONSTRAINS, (struct cil_constrain*)current->data, flavor);
+ break;
+ case CIL_VALIDATETRANS: {
+ struct cil_validatetrans *vt = current->data;
+ fprintf(file_arr[CONSTRAINS], "validatetrans");
+ fprintf(file_arr[CONSTRAINS], " %s ", ((struct cil_class*)vt->class)->datum.name);
+ cil_expr_to_policy(file_arr, CONSTRAINS, vt->datum_expr);
+ fprintf(file_arr[CONSTRAINS], ";\n");
+ break;
+ }
+ case CIL_MLSVALIDATETRANS: {
+ struct cil_validatetrans *vt = current->data;
+ fprintf(file_arr[CONSTRAINS], "mlsvalidatetrans");
+ fprintf(file_arr[CONSTRAINS], " %s " , ((struct cil_class*)vt->class)->datum.name);
+ cil_expr_to_policy(file_arr, CONSTRAINS, vt->datum_expr);
+ fprintf(file_arr[CONSTRAINS], ";\n");
+ break;
+ }
+ case CIL_SID:
+ fprintf(file_arr[ISIDS], "sid %s\n", ((struct cil_symtab_datum*)current->data)->name);
+ break;
+ case CIL_SIDCONTEXT: {
+ struct cil_sidcontext *sidcon = (struct cil_sidcontext*)current->data;
+ fprintf(file_arr[SIDS], "sid %s ", sidcon->sid_str);
+ cil_context_to_policy(file_arr, SIDS, sidcon->context);
+ fprintf(file_arr[SIDS], "\n");
+ break;
+ }
+ case CIL_POLICYCAP:
+ fprintf(file_arr[TYPEATTRTYPES], "policycap %s;\n", ((struct cil_symtab_datum*)current->data)->name);
+ break;
+ default:
+ break;
+ }
+
+ return SEPOL_OK;
+}
+
+int __cil_gen_policy_node_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args)
+{
+ int rc = SEPOL_ERR;
+ struct cil_args_genpolicy *args = NULL;
+ struct cil_list *users = NULL;
+ struct cil_list *sens = NULL;
+ struct cil_list *cats = NULL;
+ FILE **file_arr = NULL;
+
+ if (extra_args == NULL) {
+ return SEPOL_ERR;
+ }
+
+ *finished = CIL_TREE_SKIP_NOTHING;
+
+ args = extra_args;
+ users = args->users;
+ sens = args->sens;
+ cats = args->cats;
+ file_arr = args->file_arr;
+
+ if (node->cl_head != NULL) {
+ if (node->flavor == CIL_MACRO) {
+ *finished = CIL_TREE_SKIP_HEAD;
+ return SEPOL_OK;
+ }
+
+ if (node->flavor == CIL_BOOLEANIF) {
+ rc = cil_booleanif_to_policy(file_arr, CONDS, node);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_INFO, "Failed to write booleanif contents to file\n");
+ return rc;
+ }
+ *finished = CIL_TREE_SKIP_HEAD;
+ return SEPOL_OK;
+ }
+
+ if (node->flavor == CIL_OPTIONAL) {
+ if (((struct cil_symtab_datum *)node->data)->state != CIL_STATE_ENABLED) {
+ *finished = CIL_TREE_SKIP_HEAD;
+ }
+ return SEPOL_OK;
+ }
+
+ if (node->flavor == CIL_BLOCK && ((struct cil_block*)node->data)->is_abstract == CIL_TRUE) {
+ *finished = CIL_TREE_SKIP_HEAD;
+ return SEPOL_OK;
+ }
+
+ if (node->flavor != CIL_ROOT) {
+ rc = cil_name_to_policy(file_arr, node);
+ if (rc != SEPOL_OK && rc != SEPOL_DONE) {
+ cil_log(CIL_ERR, "Error converting node to policy %d\n", node->flavor);
+ return SEPOL_ERR;
+ }
+ }
+ } else {
+ switch (node->flavor) {
+ case CIL_USER:
+ cil_multimap_insert(users, node->data, NULL, CIL_USERROLE, CIL_NONE);
+ break;
+ case CIL_USERROLE: {
+ struct cil_userrole *userrole = node->data;
+ cil_multimap_insert(users, &userrole->user->datum, (struct cil_symtab_datum *)userrole->role, CIL_USERROLE, CIL_ROLE);
+ }
+ break;
+ case CIL_CATALIAS: {
+ struct cil_alias *alias = node->data;
+ struct cil_symtab_datum *datum = alias->actual;
+ cil_multimap_insert(cats, datum, node->data, CIL_CAT, CIL_CATALIAS);
+ }
+ break;
+ case CIL_SENSALIAS: {
+ struct cil_alias *alias = node->data;
+ struct cil_symtab_datum *datum = alias->actual;
+ cil_multimap_insert(sens, datum, node->data, CIL_SENS, CIL_SENSALIAS);
+ }
+ break;
+ default:
+ rc = cil_name_to_policy(file_arr, node);
+ if (rc != SEPOL_OK && rc != SEPOL_DONE) {
+ cil_log(CIL_ERR, "Error converting node to policy %d\n", rc);
+ return SEPOL_ERR;
+ }
+ break;
+ }
+ }
+
+ return SEPOL_OK;
+}
+
+int cil_gen_policy(struct cil_db *db)
+{
+ struct cil_tree_node *curr = db->ast->root;
+ struct cil_list_item *item;
+ int rc = SEPOL_ERR;
+ FILE *policy_file;
+ FILE **file_arr = cil_malloc(sizeof(FILE*) * NUM_POLICY_FILES);
+ char *file_path_arr[NUM_POLICY_FILES];
+ char temp[32];
+
+ struct cil_list *users = NULL;
+ struct cil_list *cats = NULL;
+ struct cil_list *sens = NULL;
+ struct cil_args_genpolicy extra_args;
+
+ cil_list_init(&users, CIL_LIST_ITEM);
+ cil_list_init(&cats, CIL_LIST_ITEM);
+ cil_list_init(&sens, CIL_LIST_ITEM);
+
+ strcpy(temp, "/tmp/cil_classdecl-XXXXXX");
+ file_arr[CLASS_DECL] = fdopen(mkstemp(temp), "w+");
+ file_path_arr[CLASS_DECL] = cil_strpool_add(temp);
+
+ strcpy(temp, "/tmp/cil_isids-XXXXXX");
+ file_arr[ISIDS] = fdopen(mkstemp(temp), "w+");
+ file_path_arr[ISIDS] = cil_strpool_add(temp);
+
+ strcpy(temp,"/tmp/cil_common-XXXXXX");
+ file_arr[COMMONS] = fdopen(mkstemp(temp), "w+");
+ file_path_arr[COMMONS] = cil_strpool_add(temp);
+
+ strcpy(temp, "/tmp/cil_class-XXXXXX");
+ file_arr[CLASSES] = fdopen(mkstemp(temp), "w+");
+ file_path_arr[CLASSES] = cil_strpool_add(temp);
+
+ strcpy(temp, "/tmp/cil_interf-XXXXXX");
+ file_arr[INTERFACES] = fdopen(mkstemp(temp), "w+");
+ file_path_arr[INTERFACES] = cil_strpool_add(temp);
+
+ strcpy(temp, "/tmp/cil_sens-XXXXXX");
+ file_arr[SENS] = fdopen(mkstemp(temp), "w+");
+ file_path_arr[SENS] = cil_strpool_add(temp);
+
+ strcpy(temp, "/tmp/cil_cats-XXXXXX");
+ file_arr[CATS] = fdopen(mkstemp(temp), "w+");
+ file_path_arr[CATS] = cil_strpool_add(temp);
+
+ strcpy(temp, "/tmp/cil_levels-XXXXXX");
+ file_arr[LEVELS] = fdopen(mkstemp(temp), "w+");
+ file_path_arr[LEVELS] = cil_strpool_add(temp);
+
+ strcpy(temp, "/tmp/cil_mlscon-XXXXXX");
+ file_arr[CONSTRAINS] = fdopen(mkstemp(temp), "w+");
+ file_path_arr[CONSTRAINS] = cil_strpool_add(temp);
+
+ strcpy(temp, "/tmp/cil_attrtypes-XXXXXX");
+ file_arr[TYPEATTRTYPES] = fdopen(mkstemp(temp), "w+");
+ file_path_arr[TYPEATTRTYPES] = cil_strpool_add(temp);
+
+ strcpy(temp, "/tmp/cil_aliases-XXXXXX");
+ file_arr[ALIASES] = fdopen(mkstemp(temp), "w+");
+ file_path_arr[ALIASES] = cil_strpool_add(temp);
+
+ strcpy(temp, "/tmp/cil_allows-XXXXXX");
+ file_arr[ALLOWS] = fdopen(mkstemp(temp), "w+");
+ file_path_arr[ALLOWS] = cil_strpool_add(temp);
+
+ strcpy(temp, "/tmp/cil_conds-XXXXXX");
+ file_arr[CONDS] = fdopen(mkstemp(temp), "w+");
+ file_path_arr[CONDS] = cil_strpool_add(temp);
+
+ strcpy(temp, "/tmp/cil_userroles-XXXXXX");
+ file_arr[USERROLES] = fdopen(mkstemp(temp), "w+");
+ file_path_arr[USERROLES] = cil_strpool_add(temp);
+
+ strcpy(temp, "/tmp/cil_sids-XXXXXX");
+ file_arr[SIDS] = fdopen(mkstemp(temp), "w+");
+ file_path_arr[SIDS] = cil_strpool_add(temp);
+
+ strcpy(temp, "/tmp/cil_netifcons-XXXXXX");
+ file_arr[NETIFCONS] = fdopen(mkstemp(temp), "w+");
+ file_path_arr[NETIFCONS] = cil_strpool_add(temp);
+
+ policy_file = fopen("policy.conf", "w+");
+
+ cil_list_for_each(item, db->sidorder) {
+ fprintf(file_arr[ISIDS], "sid %s ", ((struct cil_sid*)item->data)->datum.name);
+ }
+
+ cil_list_for_each(item, db->classorder) {
+ struct cil_class *class = item->data;
+ struct cil_tree_node *node = class->datum.nodes->head->data;
+
+ fprintf(file_arr[CLASS_DECL], "class %s\n", class->datum.name);
+
+ fprintf(file_arr[CLASSES], "class %s ", class->datum.name);
+ if (class->common != NULL) {
+ fprintf(file_arr[CLASSES], "inherits %s ", class->common->datum.name);
+ }
+ if (node->cl_head != NULL) {
+ struct cil_tree_node *curr_perm = node->cl_head;
+ fprintf(file_arr[CLASSES], "{ ");
+ while (curr_perm != NULL) {
+ fprintf(file_arr[CLASSES], "%s ", ((struct cil_symtab_datum*)curr_perm->data)->name);
+ curr_perm = curr_perm->next;
+ }
+ fprintf(file_arr[CLASSES], "}");
+ }
+ fprintf(file_arr[CLASSES], "\n");
+ }
+
+ if (db->catorder->head != NULL) {
+ cil_list_for_each(item, db->catorder) {
+ cil_multimap_insert(cats, item->data, NULL, CIL_CAT, 0);
+ }
+ }
+
+ if (db->sensitivityorder->head != NULL) {
+ fprintf(file_arr[SENS], "sensitivityorder { ");
+ cil_list_for_each(item, db->sensitivityorder) {
+ fprintf(file_arr[SENS], "%s ", ((struct cil_sens*)item->data)->datum.name);
+ }
+ fprintf(file_arr[SENS], "};\n");
+ }
+
+ extra_args.users = users;
+ extra_args.sens = sens;
+ extra_args.cats = cats;
+ extra_args.file_arr= file_arr;
+
+ rc = cil_tree_walk(curr, __cil_gen_policy_node_helper, NULL, NULL, &extra_args);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_ERR, "Error walking tree\n");
+ return rc;
+ }
+
+ rc = cil_netifcon_to_policy(file_arr, db->netifcon);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_ERR, "Error creating policy.conf\n");
+ return rc;
+ }
+
+ rc = cil_genfscon_to_policy(file_arr, db->genfscon);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_ERR, "Error creating policy.conf\n");
+ return rc;
+ }
+
+ rc = cil_portcon_to_policy(file_arr, db->portcon);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_ERR, "Error creating policy.conf\n");
+ return rc;
+ }
+
+ rc = cil_nodecon_to_policy(file_arr, db->nodecon);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_ERR, "Error creating policy.conf\n");
+ return rc;
+ }
+
+ rc = cil_fsuse_to_policy(file_arr, db->fsuse);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_ERR, "Error creating policy.conf\n");
+ return rc;
+ }
+
+ rc = cil_pirqcon_to_policy(file_arr, db->pirqcon);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_ERR, "Error creating policy.conf\n");
+ return rc;
+ }
+
+ rc = cil_iomemcon_to_policy(file_arr, db->iomemcon);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_ERR, "Error creating policy.conf\n");
+ return rc;
+ }
+
+ rc = cil_ioportcon_to_policy(file_arr, db->ioportcon);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_ERR, "Error creating policy.conf\n");
+ return rc;
+ }
+
+ rc = cil_pcidevicecon_to_policy(file_arr, db->pcidevicecon);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_ERR, "Error creating policy.conf\n");
+ return rc;
+ }
+
+ rc = cil_userrole_to_policy(file_arr, users);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_ERR, "Error creating policy.conf\n");
+ return SEPOL_ERR;
+ }
+
+ rc = cil_sens_to_policy(file_arr, sens);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_ERR, "Error creating policy.conf\n");
+ return SEPOL_ERR;
+ }
+
+ rc = cil_cat_to_policy(file_arr, cats);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_ERR, "Error creating policy.conf\n");
+ return SEPOL_ERR;
+ }
+
+ rc = cil_combine_policy(file_arr, policy_file);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_ERR, "Error creating policy.conf\n");
+ return SEPOL_ERR;
+ }
+
+ // Remove temp files
+ int i;
+ for (i=0; i<NUM_POLICY_FILES; i++) {
+ rc = fclose(file_arr[i]);
+ if (rc != 0) {
+ cil_log(CIL_ERR, "Error closing temporary file\n");
+ return SEPOL_ERR;
+ }
+ rc = unlink(file_path_arr[i]);
+ if (rc != 0) {
+ cil_log(CIL_ERR, "Error unlinking temporary files\n");
+ return SEPOL_ERR;
+ }
+ }
+
+ rc = fclose(policy_file);
+ if (rc != 0) {
+ cil_log(CIL_ERR, "Error closing policy.conf\n");
+ return SEPOL_ERR;
+ }
+ free(file_arr);
+
+ cil_list_destroy(&users, CIL_FALSE);
+ cil_list_destroy(&cats, CIL_FALSE);
+ cil_list_destroy(&sens, CIL_FALSE);
+
+ return SEPOL_OK;
+}
diff --git a/cil/src/cil_policy.h b/cil/src/cil_policy.h
new file mode 100644
index 0000000..72cf162
--- /dev/null
+++ b/cil/src/cil_policy.h
@@ -0,0 +1,47 @@
+/*
+ * 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_POLICY_H_
+#define CIL_POLICY_H_
+
+#include "cil_tree.h"
+#include "cil_list.h"
+#include "cil_internal.h"
+
+struct cil_multimap_item {
+ struct cil_symtab_datum *key;
+ struct cil_list *values;
+};
+
+int cil_combine_policy(FILE **file_arr, FILE *policy_file);
+void cil_context_to_policy(FILE **, uint32_t, struct cil_context *);
+int cil_name_to_policy(FILE **, struct cil_tree_node *);
+int cil_gen_policy(struct cil_db *);
+
+#endif
diff --git a/cil/src/cil_post.c b/cil/src/cil_post.c
new file mode 100644
index 0000000..71f8c73
--- /dev/null
+++ b/cil/src/cil_post.c
@@ -0,0 +1,1726 @@
+/*
+ * 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 <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <unistd.h>
+
+#include <sepol/policydb/conditional.h>
+#include <sepol/errcodes.h>
+
+#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"
+
+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 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++;
+ 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;
+ }
+
+ free(a_path);
+ free(b_path);
+ free(a_data);
+ free(b_data);
+
+ 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;
+ }
+ }
+
+ 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_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_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;
+}
+
+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_OPTIONAL: {
+ struct cil_optional *opt = node->data;
+ if (opt->datum.state != CIL_STATE_ENABLED) {
+ *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 (type->datum.nodes->head->data == node) {
+ // multiple AST nodes can point to the same cil_type data (like if
+ // copied from a macro). This check ensures we only count the
+ // duplicates once
+ type->value = db->num_types;
+ db->num_types++;
+ }
+ break;
+ }
+ case CIL_ROLE: {
+ struct cil_role *role = node->data;
+ if (role->datum.nodes->head->data == node) {
+ // multiple AST nodes can point to the same cil_role data (like if
+ // copied from a macro). This check ensures we only count the
+ // duplicates once
+ role->value = db->num_roles;
+ db->num_roles++;
+ }
+ 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_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_FSUSE:
+ db->fsuse->count++;
+ break;
+ default:
+ break;
+ }
+
+ return SEPOL_OK;
+}
+
+static int __cil_post_db_array_helper(struct cil_tree_node *node, __attribute__((unused)) 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_OPTIONAL: {
+ struct cil_optional *opt = node->data;
+ if (opt->datum.state != CIL_STATE_ENABLED) {
+ *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_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_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_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;
+ }
+ 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_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 __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);
+ if (new->head != NULL) {
+ cats->datum_expr = new;
+ } else {
+ /* empty list */
+ cil_list_destroy(&new, CIL_FALSE);
+ cats->datum_expr = NULL;
+ }
+
+ 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_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;
+ }
+
+ 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_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_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);
+ }
+ }
+
+ 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) {
+ cil_log(CIL_INFO, "Range operation only supported for categories\n");
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+ ebitmap_init(&tmp);
+ rc = __cil_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 {
+ 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");
+ 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_post_db_attr_helper(struct cil_tree_node *node, __attribute__((unused)) 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_OPTIONAL: {
+ struct cil_optional *opt = node->data;
+ if (opt->datum.state != CIL_STATE_ENABLED) {
+ *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;
+ }
+ 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;
+ }
+ 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, __attribute__((unused)) 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_OPTIONAL: {
+ struct cil_optional *opt = node->data;
+ if (opt->datum.state != CIL_STATE_ENABLED) {
+ *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 __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_OPTIONAL: {
+ struct cil_optional *opt = node->data;
+ if (opt->datum.state != CIL_STATE_ENABLED) {
+ *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_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_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_OPTIONAL: {
+ struct cil_optional *opt = node->data;
+ if (opt->datum.state != CIL_STATE_ENABLED) {
+ *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->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_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_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_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;
+ }
+
+ qsort(db->netifcon->array, db->netifcon->count, sizeof(db->netifcon->array), cil_post_netifcon_compare);
+ qsort(db->genfscon->array, db->genfscon->count, sizeof(db->genfscon->array), cil_post_genfscon_compare);
+ qsort(db->portcon->array, db->portcon->count, sizeof(db->portcon->array), cil_post_portcon_compare);
+ qsort(db->nodecon->array, db->nodecon->count, sizeof(db->nodecon->array), cil_post_nodecon_compare);
+ qsort(db->fsuse->array, db->fsuse->count, sizeof(db->fsuse->array), cil_post_fsuse_compare);
+ qsort(db->filecon->array, db->filecon->count, sizeof(db->filecon->array), cil_post_filecon_compare);
+ qsort(db->pirqcon->array, db->pirqcon->count, sizeof(db->pirqcon->array), cil_post_pirqcon_compare);
+ qsort(db->iomemcon->array, db->iomemcon->count, sizeof(db->iomemcon->array), cil_post_iomemcon_compare);
+ qsort(db->ioportcon->array, db->ioportcon->count, sizeof(db->ioportcon->array), cil_post_ioportcon_compare);
+ qsort(db->pcidevicecon->array, db->pcidevicecon->count, sizeof(db->pcidevicecon->array), cil_post_pcidevicecon_compare);
+
+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;
+}
+
+int cil_post_process(struct cil_db *db)
+{
+ int rc = SEPOL_ERR;
+
+ rc = cil_verify_no_classperms_loop(db);
+ if (rc != SEPOL_OK) {
+ 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;
+
+}
diff --git a/cil/src/cil_post.h b/cil/src/cil_post.h
new file mode 100644
index 0000000..74393cc
--- /dev/null
+++ b/cil/src/cil_post.h
@@ -0,0 +1,51 @@
+/*
+ * 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_portcon_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
diff --git a/cil/src/cil_reset_ast.c b/cil/src/cil_reset_ast.c
new file mode 100644
index 0000000..aafbd94
--- /dev/null
+++ b/cil/src/cil_reset_ast.c
@@ -0,0 +1,519 @@
+
+#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(&common->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 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, but not SET */
+ cil_reset_classperms(curr->data);
+ }
+ }
+}
+
+static void cil_reset_classpermission(struct cil_classpermission *cp)
+{
+ cil_reset_classperms_list(cp->classperms);
+}
+
+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;
+ cil_list_destroy(&user->roles, 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;
+}
+
+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->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_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_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_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_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_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_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:
+ 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;
+}
diff --git a/cil/src/cil_reset_ast.h b/cil/src/cil_reset_ast.h
new file mode 100644
index 0000000..393ff9e
--- /dev/null
+++ b/cil/src/cil_reset_ast.h
@@ -0,0 +1,8 @@
+#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_ */
diff --git a/cil/src/cil_resolve_ast.c b/cil/src/cil_resolve_ast.c
new file mode 100644
index 0000000..2250016
--- /dev/null
+++ b/cil/src/cil_resolve_ast.c
@@ -0,0 +1,3798 @@
+/*
+ * 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 <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <sepol/policydb/conditional.h>
+
+#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"
+
+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 *boolif;
+ struct cil_tree_node *macro;
+ struct cil_list *sidorder_lists;
+ struct cil_list *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)
+{
+ 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);
+ 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) {
+ cil_log(CIL_ERR, "Failed to resolve permission %s\n", (char*)curr->data);
+ goto exit;
+ }
+ 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);
+ 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;
+}
+
+int cil_type_used(struct cil_symtab_datum *datum)
+{
+ struct cil_typeattribute *attr = NULL;
+
+ if (FLAVOR(datum) == CIL_TYPEATTRIBUTE) {
+ attr = (struct cil_typeattribute*)datum;
+ attr->used = CIL_TRUE;
+ }
+
+ return 0;
+}
+
+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;
+ 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->rule_kind != CIL_AVRULE_NEVERALLOW) {
+ cil_type_used(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;
+ if (rule->rule_kind != CIL_AVRULE_NEVERALLOW) {
+ cil_type_used(tgt_datum);
+ }
+ }
+
+ rc = cil_resolve_classperms_list(current, rule->classperms, 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;
+ cil_type_used(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;
+ cil_type_used(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_aliasactual(struct cil_tree_node *current, void *extra_args, enum cil_flavor 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(current, aliasactual->alias_str, sym_index, extra_args, &alias_datum);
+ if (rc != SEPOL_OK) {
+ goto exit;
+ }
+
+ rc = cil_resolve_name(current, aliasactual->actual_str, sym_index, extra_args, &actual_datum);
+ if (rc != SEPOL_OK) {
+ goto exit;
+ }
+
+ alias = (struct cil_alias *)alias_datum;
+
+ if (alias->actual != NULL) {
+ cil_log(CIL_ERR, "Alias cannot bind more than one value\n");
+ 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_log(CIL_ERR, "Alias declared but not used at line %d of %s\n",current->line, current->path);
+ 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;
+ cil_type_used(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;
+ cil_type_used(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;
+ cil_type_used(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;
+ cil_type_used(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;
+
+ 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;
+
+ if (userrole->user->roles == NULL) {
+ cil_list_init(&userrole->user->roles, CIL_LIST_ITEM);
+ }
+
+ cil_list_append(userrole->user->roles, CIL_ROLE, userrole->role);
+
+ 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;
+ 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 = (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;
+ 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 = (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;
+ 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;
+ }
+ 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;
+ 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;
+ }
+ 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) {
+ cil_log(CIL_ERR, "Unable to resolve name: %s\n", selinuxuser->range_str);
+ 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;
+ cil_type_used(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;
+ cil_type_used(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) {
+ 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;
+}
+
+struct cil_list *__cil_ordered_lists_merge_all(struct cil_list **ordered_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_log(CIL_ERR, "Unable to merge ordered list at line %d of %s\n",ordered_list->node->line, ordered_list->node->path);
+ }
+ }
+ goto exit;
+ }
+ }
+
+ __cil_ordered_lists_destroy(ordered_lists);
+
+ return composite;
+
+exit:
+ 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_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 *ordered = NULL;
+ int rc = SEPOL_ERR;
+
+ cil_list_init(&new, CIL_CLASSORDER);
+
+ cil_list_for_each(curr, classorder->class_list_str) {
+ 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(&ordered);
+ ordered->list = new;
+ ordered->node = current;
+ cil_list_append(classorder_list, CIL_CLASSORDER, ordered);
+
+ return SEPOL_OK;
+
+exit:
+ 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:
+ 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:
+ 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:
+ 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) {
+ cil_log(CIL_ERR,"Unable to resolve categories\n");
+ 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 *type_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) {
+ cil_log(CIL_ERR, "Unable to resolve name: %s\n", context->user_str);
+ 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) {
+ cil_log(CIL_ERR, "Unable to resolve name: %s\n", context->role_str);
+ 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) {
+ cil_log(CIL_ERR, "Unable to resolve name: %s\n", context->type_str);
+ goto exit;
+ }
+
+ type_node = type_datum->nodes->head->data;
+
+ if (type_node->flavor != CIL_TYPE && 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) {
+ cil_log(CIL_ERR, "Unable to resolve name: %s\n", context->range_str);
+ 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_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_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_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(struct cil_tree_node *current, void *extra_args)
+{
+ struct cil_blockinherit *inherit = 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, inherit->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, block_node, current);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_ERR, "Failed to copy block, rc: %d\n", rc);
+ 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_log(CIL_ERR, "Failed to resolve in-statement on line %d of %s\n", last_failed_node->line, last_failed_node->path);
+ 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)
+{
+ 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;
+ }
+
+ rc = cil_resolve_name(current, bounds->child_str, index, extra_args, &child_datum);
+ if (rc != SEPOL_OK) {
+ goto exit;
+ }
+
+ switch (flavor) {
+ case CIL_USER: {
+ struct cil_user *user = (struct cil_user *)child_datum;
+
+ if (user->bounds != NULL) {
+ struct cil_tree_node *node = user->bounds->datum.nodes->head->data;
+ cil_log(CIL_ERR, "User %s already bound by parent at line %u of %s\n", bounds->child_str, node->line, node->path);
+ 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) {
+ struct cil_tree_node *node = role->bounds->datum.nodes->head->data;
+ cil_log(CIL_ERR, "Role %s already bound by parent at line %u of %s\n", bounds->child_str, node->line, node->path);
+ 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;
+ struct cil_tree_node *node = NULL;
+
+ if (type->bounds != NULL) {
+ node = ((struct cil_symtab_datum *)type->bounds)->nodes->head->data;
+ cil_log(CIL_ERR, "Type %s already bound by parent at line %u of %s\n", bounds->child_str, node->line, node->path);
+ cil_log(CIL_ERR, "Now being bound to parent %s at line %u of %s\n", bounds->parent_str, current->line, current->path);
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+
+ node = parent_datum->nodes->head->data;
+ if (node->flavor == CIL_TYPEATTRIBUTE) {
+ cil_log(CIL_ERR, "Bounds parent %s is an attribute\n", bounds->parent_str);
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+
+ node = child_datum->nodes->head->data;
+ if (node->flavor == CIL_TYPEATTRIBUTE) {
+ cil_log(CIL_ERR, "Bounds child %s is an attribute\n", bounds->child_str);
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+
+ type->bounds = (struct cil_type *)parent_datum;
+ break;
+ }
+ default:
+ break;
+ }
+
+ return SEPOL_OK;
+
+exit:
+ cil_log(CIL_ERR, "Bad bounds statement at line %u of %s\n", current->line, current->path);
+ 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) {
+ cil_log(CIL_ERR, "Failed to resolve class %s in %s\n", (char *)curr->data, cil_node_to_string(current));
+ 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) {
+ cil_log(CIL_ERR, "Failed to resolve class %s in defaultrange\n", (char *)curr->data);
+ goto exit;
+ }
+ cil_list_append(def->class_datums, CIL_CLASS, datum);
+ }
+
+ return 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, &macro_datum);
+ if (rc != SEPOL_OK) {
+ goto exit;
+ }
+
+ macro_node = macro_datum->nodes->head->data;
+
+ if (macro_node->flavor != CIL_MACRO) {
+ printf("Failed to resolve macro %s\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_log(CIL_ERR, "Missing arguments (%s, line: %d)\n", current->path, current->line);
+ 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_log(CIL_ERR, "Missing arguments (%s, line: %d)\n", current->path, current->line);
+ 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);
+ 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);
+ 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);
+ 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);
+ 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);
+ 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));
+ 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_log(CIL_ERR, "Unexpected arguments (%s, line: %d)\n", current->path, current->line);
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+ } else if (new_call->args_tree != NULL) {
+ cil_log(CIL_ERR, "Unexpected arguments (%s, line: %d)\n", current->path, current->line);
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+
+ if (new_call->copied == 0) {
+ new_call->copied = 1;
+ 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, &param_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_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_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 = args->in_list;
+
+ if (node == NULL || args == NULL) {
+ goto exit;
+ }
+
+ 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:
+ if (node->flavor == CIL_BLOCKINHERIT) {
+ rc = cil_resolve_blockinherit(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);
+ break;
+ case CIL_SENSALIASACTUAL:
+ rc = cil_resolve_aliasactual(node, args, CIL_SENS);
+ break;
+ case CIL_CATALIASACTUAL:
+ rc = cil_resolve_aliasactual(node, args, CIL_CAT);
+ 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_TYPEBOUNDS:
+ rc = cil_resolve_bounds(node, args, CIL_TYPE);
+ 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:
+ rc = cil_resolve_avrule(node, 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);
+ 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);
+ 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_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_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_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;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return rc;
+
+exit:
+ return rc;
+}
+
+int __cil_resolve_ast_node_helper(struct cil_tree_node *node, __attribute__((unused)) 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;
+
+ 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_log(CIL_ERR, "%s statement is not allowed in optionals (%s:%d)\n", cil_node_to_string(node), node->path, node->line);
+ 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_log(CIL_ERR, "%s statement is not allowed in booleanifs (tunableif treated as a booleanif) (%s:%d)\n", cil_node_to_string(node), node->path, node->line);
+ } else {
+ cil_log(CIL_ERR, "%s statement is not allowed in booleanifs (%s:%d)\n", cil_node_to_string(node), node->path, node->line);
+ }
+ 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_OPTIONAL && ((struct cil_symtab_datum *)node->data)->state == CIL_STATE_DISABLED) {
+ /* don't try to resolve children of a disabled optional */
+ *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 && optstack != NULL) {
+ struct cil_optional *opt = (struct cil_optional *)optstack->data;
+ cil_log(CIL_WARN, "Disabling optional %s at %d of %s\n", opt->datum.name, node->parent->line, node->parent->path);
+ /* disable an optional if something failed to resolve */
+ opt->datum.state = CIL_STATE_DISABLING;
+ rc = SEPOL_OK;
+ } else if (rc != SEPOL_OK) {
+ cil_log(CIL_ERR, "Failed to resolve %s statement at %d of %s\n", cil_node_to_string(node), node->line, node->path);
+ goto exit;
+ }
+
+ return rc;
+
+exit:
+ return rc;
+}
+
+int __cil_disable_children_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args)
+{
+ int rc = SEPOL_ERR;
+ struct cil_args_resolve *args = extra_args;
+ uint32_t *changed = args->changed;
+
+ if (node == NULL || finished == NULL) {
+ goto exit;
+ }
+
+ if (node->flavor < CIL_MIN_DECLARATIVE) {
+ /* only declarative statements need to be disabled */
+ rc = SEPOL_OK;
+ goto exit;
+ }
+
+ if (node->flavor == CIL_OPTIONAL) {
+ if (((struct cil_symtab_datum *)node->data)->state == CIL_STATE_DISABLED) {
+ /* don't bother going into an optional that isn't enabled */
+ *finished = CIL_TREE_SKIP_HEAD;
+ rc = SEPOL_OK;
+ goto exit;
+ }
+ } else {
+ /* Do we need to reset for a block? */
+ *changed = 1;
+ }
+
+ ((struct cil_symtab_datum *)node->data)->state = CIL_STATE_DISABLED;
+
+ return SEPOL_OK;
+
+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 *callstack = NULL;
+ struct cil_tree_node *optstack = NULL;
+ struct cil_tree_node *parent = NULL;
+
+ if (current == NULL || extra_args == NULL) {
+ goto exit;
+ }
+
+ callstack = args->callstack;
+ optstack = args->optstack;
+ parent = current->parent;
+
+ if (parent->flavor == CIL_CALL || parent->flavor == CIL_OPTIONAL) {
+ /* push this node onto a stack */
+ struct cil_tree_node *new;
+ cil_tree_node_init(&new);
+
+ new->data = parent->data;
+ new->flavor = parent->flavor;
+
+ if (parent->flavor == CIL_CALL) {
+ if (callstack != NULL) {
+ struct cil_tree_node *curr = NULL;
+ struct cil_call *new_call = new->data;
+ for (curr = callstack->cl_head; curr != NULL;
+ curr = curr->cl_head) {
+ struct cil_call *curr_call = curr->data;
+ if (curr_call->macro == new_call->macro) {
+ cil_log(CIL_ERR, "Recursive macro call found\n");
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+ }
+ callstack->parent = new;
+ new->cl_head = callstack;
+ }
+ args->callstack = new;
+ } else if (parent->flavor == CIL_OPTIONAL) {
+ if (optstack != NULL) {
+ optstack->parent = new;
+ new->cl_head = optstack;
+ }
+ args->optstack = 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;
+
+ if (current == NULL || extra_args == NULL) {
+ goto exit;
+ }
+
+ parent = current->parent;
+
+ if (parent->flavor == CIL_CALL) {
+ /* pop off the stack */
+ struct cil_tree_node *callstack = args->callstack;
+ args->callstack = callstack->cl_head;
+ if (callstack->cl_head) {
+ callstack->cl_head->parent = NULL;
+ }
+ free(callstack);
+ } else 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)->datum.state == CIL_STATE_DISABLING) {
+ /* go into the optional, removing everything that it added */
+ if (args->pass >= CIL_PASS_CALL1) {
+ rc = cil_tree_walk(parent, __cil_disable_children_helper, NULL, NULL, extra_args);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_ERR, "Failed to disable declarations in optional\n");
+ goto exit;
+ }
+ }
+ ((struct cil_optional *)parent->data)->datum.state = CIL_STATE_DISABLED;
+ }
+
+ /* 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;
+ }
+
+ return SEPOL_OK;
+
+exit:
+ return rc;
+}
+
+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) {
+ goto exit;
+ }
+
+ extra_args.db = db;
+ extra_args.pass = pass;
+ extra_args.changed = &changed;
+ extra_args.callstack = 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.catorder_lists = NULL;
+ extra_args.sensitivityorder_lists = NULL;
+ extra_args.in_list = 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.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);
+ db->classorder = __cil_ordered_lists_merge_all(&extra_args.classorder_lists);
+ db->catorder = __cil_ordered_lists_merge_all(&extra_args.catorder_lists);
+ cil_set_cat_values(db->catorder, db);
+ db->sensitivityorder = __cil_ordered_lists_merge_all(&extra_args.sensitivityorder_lists);
+
+ 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.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.callstack != NULL) {
+ struct cil_tree_node *curr = extra_args.callstack;
+ struct cil_tree_node *next = curr->cl_head;
+ free(curr);
+ extra_args.callstack = next;
+ }
+ while (extra_args.optstack != NULL) {
+ struct cil_tree_node *curr = extra_args.optstack;
+ struct cil_tree_node *next = curr->cl_head;
+ free(curr);
+ extra_args.optstack = next;
+ }
+ }
+
+ rc = __cil_verify_initsids(db->sidorder);
+ if (rc != SEPOL_OK) {
+ goto exit;
+ }
+
+ rc = SEPOL_OK;
+exit:
+ return rc;
+}
+
+static int __cil_resolve_name_helper(struct cil_tree_node *ast_node, char *name, enum cil_sym_index sym_index, void *extra_args, struct cil_symtab_datum **datum)
+{
+ struct cil_args_resolve *args = extra_args;
+ struct cil_call *call = NULL;
+ struct cil_tree_node *macro = NULL;
+ enum cil_pass pass = CIL_PASS_INIT;
+
+ int rc = SEPOL_ERR;
+ char* name_dup = cil_strdup(name);
+ char *tok_current = strtok(name_dup, ".");
+ char *tok_next = strtok(NULL, ".");
+ symtab_t *symtab = NULL;
+ struct cil_symtab_datum *tmp_datum = NULL;
+ enum cil_flavor flavor = CIL_NONE;
+
+ if (args != NULL) {
+ if (args->callstack != NULL) {
+ call = args->callstack->data;
+ }
+ pass = args->pass;
+ macro = args->macro;
+ }
+
+ if (ast_node->flavor == CIL_ROOT) {
+ symtab = &((struct cil_root *)ast_node->data)->symtab[CIL_SYM_BLOCKS];
+ } else {
+ if (call != NULL) {
+ // check macro symtab
+ symtab = &call->macro->symtab[CIL_SYM_BLOCKS];
+ rc = cil_symtab_get_datum(symtab, tok_current, datum);
+ if (rc == SEPOL_OK) {
+ flavor = ((struct cil_tree_node*)(*datum)->nodes->head->data)->flavor;
+ if (flavor != CIL_BLOCK) {
+ printf("Failed to get block from symtab\n");
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+ // if in macro, check call parent to verify successful copy to call
+ rc = cil_get_symtab(ast_node->parent->parent, &symtab, CIL_SYM_BLOCKS);
+ if (rc == SEPOL_OK) {
+ rc = cil_symtab_get_datum(symtab, tok_current, datum);
+ flavor = ((struct cil_tree_node*)(*datum)->nodes->head->data)->flavor;
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_ERR, "Failed to get datum from parent symtab of call\n");
+ goto exit;
+ } else if (flavor != CIL_BLOCK) {
+ printf("Failed to get block from symtab\n");
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+ } else {
+ cil_log(CIL_ERR, "Failed to get symtab from call parent\n");
+ goto exit;
+ }
+ } else if (rc == SEPOL_ENOENT) {
+ rc = cil_get_symtab(((struct cil_tree_node*)call->macro->datum.nodes->head->data)->parent, &symtab, CIL_SYM_BLOCKS);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_ERR, "Failed to get datum from parent symtab of macro\n");
+ goto exit;
+ }
+ } else {
+ goto exit;
+ }
+
+ } else {
+ if (ast_node->flavor == CIL_TUNABLEIF && macro != NULL) {
+ rc = cil_get_symtab(macro->parent, &symtab, CIL_SYM_BLOCKS);
+ } else {
+ rc = cil_get_symtab(ast_node->parent, &symtab, CIL_SYM_BLOCKS);
+ }
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_ERR, "Failed to get parent symtab, rc: %d\n", rc);
+ goto exit;
+ }
+ }
+ }
+
+ if (tok_next == NULL) {
+ /*TODO: Should this set rc to SEPOL_ERR? */
+ /* Cant this be done earlier */
+ goto exit;
+ }
+
+ while (tok_current != NULL) {
+ if (tok_next != NULL) {
+ rc = cil_symtab_get_datum(symtab, tok_current, &tmp_datum);
+ if (rc == SEPOL_OK) {
+ flavor = ((struct cil_tree_node*)tmp_datum->nodes->head->data)->flavor;
+ } else {
+ goto exit;
+ }
+
+ if ((flavor != CIL_BLOCK && ast_node->flavor != CIL_IN) ||
+ (flavor == CIL_BLOCK && (((struct cil_block*)tmp_datum)->is_abstract == CIL_TRUE && pass > CIL_PASS_BLKABS ))) {
+ printf("Failed to resolve block: %s\n", tok_current);
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+ symtab = &(((struct cil_block*)tmp_datum)->symtab[CIL_SYM_BLOCKS]);
+ } else {
+ //cil_log(CIL_ERR, "type key: %s\n", tok_current);
+ symtab = &(((struct cil_block*)tmp_datum)->symtab[sym_index]);
+ rc = cil_symtab_get_datum(symtab, tok_current, &tmp_datum);
+ if (rc != SEPOL_OK) {
+ goto exit;
+ }
+ }
+ tok_current = tok_next;
+ tok_next = strtok(NULL, ".");
+ }
+ *datum = tmp_datum;
+ free(name_dup);
+
+ return SEPOL_OK;
+
+exit:
+ free(name_dup);
+ 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)
+{
+ struct cil_args_resolve *args = extra_args;
+ struct cil_db *db = NULL;
+ struct cil_call *call = NULL;
+ struct cil_tree_node *node = NULL;
+ struct cil_tree_node *macro = NULL;
+ struct cil_tree_node *namespace = NULL;
+ int rc = SEPOL_ERR;
+ char *global_symtab_name = NULL;
+ char first;
+
+ if (args != NULL) {
+ db = args->db;
+ if (args->callstack != NULL) {
+ call = args->callstack->data;
+ }
+ macro = args->macro;
+ }
+
+ if (db == NULL || ast_node == NULL || name == NULL) {
+ cil_log(CIL_ERR, "Invalid call to cil_resolve_name\n");
+ goto exit;
+ }
+
+ global_symtab_name = name;
+ first = *name;
+
+ if (first != '.') {
+ if (strrchr(name, '.') == NULL) {
+ symtab_t *symtab = NULL;
+ if (call != NULL) {
+ namespace = ast_node;
+ while (namespace->flavor != CIL_BLOCK && namespace->flavor != CIL_CALL) {
+ namespace = namespace->parent;
+ }
+ if (namespace->flavor == CIL_BLOCK) {
+ rc = cil_get_symtab(namespace, &symtab, sym_index);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_ERR, "Failed to get parent symtab\n");
+ goto exit;
+ }
+ } else {
+ symtab = &call->macro->symtab[sym_index];
+ rc = cil_symtab_get_datum(symtab, name, datum);
+ if (rc == SEPOL_OK) {
+ rc = cil_get_symtab(namespace, &symtab, sym_index);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_ERR, "Failed to get parent symtab from call\n");
+ goto exit;
+ }
+ }
+ }
+
+ rc = cil_symtab_get_datum(symtab, name, datum);
+ if (rc != SEPOL_OK) {
+ rc = cil_resolve_name_call_args(call, name, sym_index, datum);
+ if (rc == SEPOL_OK) {
+ goto exit;
+ }
+
+ rc = cil_get_symtab(((struct cil_tree_node*)call->macro->datum.nodes->head->data)->parent, &symtab, sym_index);
+ if (rc != SEPOL_OK) {
+ goto exit;
+ }
+
+ rc = cil_symtab_get_datum(symtab, name, datum);
+ if (rc == SEPOL_OK) {
+ goto exit;
+ }
+
+ global_symtab_name = cil_malloc(strlen(name)+2);
+ strcpy(global_symtab_name, ".");
+ strncat(global_symtab_name, name, strlen(name));
+ }
+ } else {
+ if (ast_node->flavor == CIL_TUNABLEIF && macro != NULL) {
+ rc = cil_get_symtab(macro->parent, &symtab, sym_index);
+ } else {
+ rc = cil_get_symtab(ast_node->parent, &symtab, sym_index);
+ }
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_ERR, "Failed to get parent symtab, rc: %d\n", rc);
+ goto exit;
+ }
+ rc = cil_symtab_get_datum(symtab, name, datum);
+ if (rc != SEPOL_OK) {
+ global_symtab_name = cil_malloc(strlen(name)+2);
+ strcpy(global_symtab_name, ".");
+ strncat(global_symtab_name, name, strlen(name));
+ }
+ }
+ } else {
+ rc = __cil_resolve_name_helper(ast_node, name, sym_index, args, datum);
+ if (rc != SEPOL_OK) {
+ global_symtab_name = cil_malloc(strlen(name)+2);
+ strcpy(global_symtab_name, ".");
+ strncat(global_symtab_name, name, strlen(name));
+ }
+ }
+ }
+
+ first = *global_symtab_name;
+
+ if (first == '.') {
+ if (strrchr(global_symtab_name, '.') == global_symtab_name) { //Only one dot in name, check global symtabs
+ symtab_t *symtab = &((struct cil_root *)db->ast->root->data)->symtab[sym_index];
+ rc = cil_symtab_get_datum(symtab, global_symtab_name+1, datum);
+ if (rc != SEPOL_OK) {
+ free(global_symtab_name);
+ goto exit;
+ }
+ } else {
+ rc = __cil_resolve_name_helper(db->ast->root, global_symtab_name, sym_index, args, datum);
+ if (rc != SEPOL_OK) {
+ free(global_symtab_name);
+ goto exit;
+ }
+ }
+ }
+
+ if (global_symtab_name != name) {
+ free(global_symtab_name);
+ }
+
+ rc = SEPOL_OK;
+
+exit:
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_WARN, "Failed to resolve %s in %s statement on line %d of %s\n",
+ name, cil_node_to_string(ast_node), ast_node->line, ast_node->path);
+ }
+
+ if (*datum != NULL) {
+ /* If this datum is an alias, then return the actual node
+ * This depends on aliases already being processed
+ */
+ node = (*datum)->nodes->head->data;
+ 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;
+ }
+ }
+ }
+
+ return rc;
+}
diff --git a/cil/src/cil_resolve_ast.h b/cil/src/cil_resolve_ast.h
new file mode 100644
index 0000000..e99f0a4
--- /dev/null
+++ b/cil/src/cil_resolve_ast.h
@@ -0,0 +1,100 @@
+/*
+ * 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 <stdint.h>
+
+#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_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_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);
+
+#endif /* CIL_RESOLVE_AST_H_ */
diff --git a/cil/src/cil_stack.c b/cil/src/cil_stack.c
new file mode 100644
index 0000000..bbfb961
--- /dev/null
+++ b/cil/src/cil_stack.c
@@ -0,0 +1,111 @@
+/*
+ * 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 <stdlib.h>
+
+#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];
+}
diff --git a/cil/src/cil_stack.h b/cil/src/cil_stack.h
new file mode 100644
index 0000000..b78535a
--- /dev/null
+++ b/cil/src/cil_stack.h
@@ -0,0 +1,62 @@
+/*
+ * 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
diff --git a/cil/src/cil_strpool.c b/cil/src/cil_strpool.c
new file mode 100644
index 0000000..ad2a334
--- /dev/null
+++ b/cil/src/cil_strpool.c
@@ -0,0 +1,104 @@
+/*
+ * 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 <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#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 hashtab_t cil_strpool_tab = NULL;
+
+static unsigned int cil_strpool_hash(hashtab_t h, 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 cil_strpool_compare(hashtab_t h __attribute__ ((unused)), hashtab_key_t key1, hashtab_key_t key2)
+{
+ char *keyp1 = (char*)key1;
+ char *keyp2 = (char*)key2;
+ return strcmp(keyp1, keyp2);
+}
+
+char *cil_strpool_add(const char *str)
+{
+ struct cil_strpool_entry *strpool_ref = NULL;
+
+ 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) {
+ (*cil_mem_error_handler)();
+ }
+ }
+
+ 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)
+{
+ cil_strpool_tab = hashtab_create(cil_strpool_hash, cil_strpool_compare, CIL_STRPOOL_TABLE_SIZE);
+ if (cil_strpool_tab == NULL) {
+ (*cil_mem_error_handler)();
+ }
+}
+
+void cil_strpool_destroy(void)
+{
+ hashtab_map(cil_strpool_tab, cil_strpool_entry_destroy, NULL);
+ hashtab_destroy(cil_strpool_tab);
+}
diff --git a/cil/src/cil_strpool.h b/cil/src/cil_strpool.h
new file mode 100644
index 0000000..a61a2d9
--- /dev/null
+++ b/cil/src/cil_strpool.h
@@ -0,0 +1,38 @@
+/*
+ * 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 <sepol/policydb/hashtab.h>
+
+char *cil_strpool_add(const char *str);
+void cil_strpool_init(void);
+void cil_strpool_destroy(void);
+#endif /* CIL_STRPOOL_H_ */
diff --git a/cil/src/cil_symtab.c b/cil/src/cil_symtab.c
new file mode 100644
index 0000000..f909357
--- /dev/null
+++ b/cil/src/cil_symtab.c
@@ -0,0 +1,273 @@
+/*
+ * 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 <stdlib.h>
+#include <string.h>
+
+#include <sepol/errcodes.h>
+#include <sepol/policydb/hashtab.h>
+#include <sepol/policydb/symtab.h>
+
+#include "cil_internal.h"
+#include "cil_tree.h"
+#include "cil_symtab.h"
+#include "cil_mem.h"
+#include "cil_strpool.h"
+
+__attribute__((noreturn)) void cil_symtab_error(const char* msg)
+{
+ cil_log(CIL_ERR, "%s\n",msg);
+ 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;
+ cil_list_init(&datum->nodes, CIL_LIST_ITEM);
+ datum->state = CIL_STATE_ENABLED;
+}
+
+void cil_symtab_datum_destroy(struct cil_symtab_datum *datum)
+{
+ cil_list_destroy(&datum->nodes, 0);
+}
+
+/* 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;
+ 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_destroy(__attribute__((unused))hashtab_key_t key, hashtab_datum_t datum, __attribute__((unused))void *args)
+{
+ cil_symtab_datum_destroy((struct cil_symtab_datum *)datum);
+ free(datum);
+}
+
+void cil_symtab_datum_remove(struct cil_symtab_datum *datum, struct cil_tree_node *node)
+{
+ if (datum->nodes != NULL) {
+ struct cil_list_item *item;
+ struct cil_list_item *previous = NULL;
+ cil_list_for_each(item, datum->nodes) {
+ if (item->data == node) {
+ if (previous == NULL) {
+ datum->nodes->head = item->next;
+ } else {
+ previous->next = item->next;
+ }
+ cil_list_item_destroy(&item, 0);
+ break;
+ }
+ previous = item;
+ }
+ }
+}
+
+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 || (*datum)->state != CIL_STATE_ENABLED) {
+ 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);
+}
+
+void cil_symtab_destroy(symtab_t *symtab)
+{
+ if (symtab->table != 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) {
+ 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;
+}
diff --git a/cil/src/cil_symtab.h b/cil/src/cil_symtab.h
new file mode 100644
index 0000000..25b0f8b
--- /dev/null
+++ b/cil/src/cil_symtab.h
@@ -0,0 +1,90 @@
+/*
+ * 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 <sepol/policydb/symtab.h>
+#include <sepol/policydb/hashtab.h>
+
+#include "cil_tree.h"
+
+#define CIL_STATE_ENABLED 1
+#define CIL_STATE_DISABLED 2
+#define CIL_STATE_DISABLING 3
+struct cil_symtab_datum {
+ struct cil_list *nodes;
+ char *name;
+ int state;
+};
+
+#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);
+int cil_symtab_insert(symtab_t *symtab, hashtab_key_t key, struct cil_symtab_datum *datum, struct cil_tree_node *node);
+void cil_symtab_datum_remove(struct cil_symtab_datum *datum, struct cil_tree_node *node);
+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
diff --git a/cil/src/cil_tree.c b/cil/src/cil_tree.c
new file mode 100644
index 0000000..7777bb9
--- /dev/null
+++ b/cil/src/cil_tree.c
@@ -0,0 +1,1620 @@
+/*
+ * 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 <stdio.h>
+
+#include <sepol/policydb/conditional.h>
+
+#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);
+
+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);
+ cil_root_init((struct cil_root **)&new_tree->root->data);
+
+ *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->path = NULL;
+
+ *node = new_node;
+}
+
+void cil_tree_node_destroy(struct cil_tree_node **node)
+{
+ if (node == NULL || *node == NULL) {
+ return;
+ }
+
+ if ((*node)->flavor >= CIL_MIN_DECLARATIVE) {
+ cil_symtab_datum_remove((*node)->data, *node);
+ struct cil_symtab_datum *datum = (*node)->data;
+ if (datum->nodes != NULL && datum->nodes->head == 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_log(CIL_INFO, "Problem at line %d of %s\n", node->line, node->path);
+ 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_log(CIL_INFO, "Problem at line %d of %s\n", node->line, node->path);
+ 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_log(CIL_INFO, "Problem at line %d of %s\n",node->line, node->path);
+ 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;
+
+ cil_log(CIL_INFO, "(");
+
+ if (datum_expr != NULL) {
+ cil_expr_to_string(datum_expr, &expr_str);
+ } else {
+ cil_expr_to_string(str_expr, &expr_str);
+ }
+
+ 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_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:");
+
+ if (userrole->user != NULL) {
+ cil_log(CIL_INFO, " %s", userrole->user->datum.name);
+ } else if (userrole->user_str != NULL) {
+ cil_log(CIL_INFO, " %s", userrole->user_str);
+ }
+
+ if (userrole->role != NULL) {
+ cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum *)userrole->role)->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_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->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_str != NULL) {
+ cil_log(CIL_INFO, " %s", filecon->context_str);
+ } else 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_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");
+ }
+ 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_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 ( %d %d )", 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_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; x<depth; x++) {
+ cil_log(CIL_INFO, "\t");
+ }
+ cil_tree_print_node(current);
+ }
+ } else {
+ if (current->parent != NULL) {
+ cil_log(CIL_INFO, "\n");
+ for (x = 0; x<depth; x++) {
+ cil_log(CIL_INFO, "\t");
+ }
+ cil_log(CIL_INFO, "(");
+
+ if (current->flavor != 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; x<depth-1; x++) {
+ cil_log(CIL_INFO, "\t");
+ }
+ cil_log(CIL_INFO, ")\n");
+ } else {
+ cil_log(CIL_INFO, ")");
+ }
+ }
+
+ if ((current->parent != 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");
+ }
+}
diff --git a/cil/src/cil_tree.h b/cil/src/cil_tree.h
new file mode 100644
index 0000000..9bb602f
--- /dev/null
+++ b/cil/src/cil_tree.h
@@ -0,0 +1,71 @@
+/*
+ * 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 <stdint.h>
+
+#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;
+ char *path;
+ void *data;
+};
+
+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_ */
+
diff --git a/cil/src/cil_verify.c b/cil/src/cil_verify.c
new file mode 100644
index 0000000..a1576e7
--- /dev/null
+++ b/cil/src/cil_verify.c
@@ -0,0 +1,1570 @@
+/*
+ * 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 <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <ctype.h>
+
+#include <sepol/policydb/polcaps.h>
+#include <sepol/errcodes.h>
+
+#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_verify.h"
+
+int __cil_verify_name(const char *name)
+{
+ int rc = SEPOL_ERR;
+ int len = strlen(name);
+ int i = 0;
+
+ 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) {
+ cil_log(CIL_ERR,"Operator (%s) only valid for catset 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_log(CIL_ERR, "SID %s not in sidorder statement at line %d of %s\n", sid->datum.name, node->line, node->path);
+ return SEPOL_ERR;
+ }
+ } else if (node->flavor == CIL_CLASS) {
+ struct cil_class *class = node->data;
+ if (class->ordered == CIL_FALSE) {
+ cil_log(CIL_ERR, "Class %s not in classorder statement at line %d of %s\n", class->datum.name, node->line, node->path);
+ return SEPOL_ERR;
+ }
+ } else if (node->flavor == CIL_CAT) {
+ struct cil_cat *cat = node->data;
+ if (cat->ordered == CIL_FALSE) {
+ cil_log(CIL_ERR, "Category %s not in categoryorder statement at line %d of %s\n", cat->datum.name, node->line, node->path);
+ return SEPOL_ERR;
+ }
+ } else if (node->flavor == CIL_SENS) {
+ struct cil_sens *sens = node->data;
+ if (sens->ordered == CIL_FALSE) {
+ cil_log(CIL_ERR, "Sensitivity %s not in sensitivityorder statement at line %d of %s\n", sens->datum.name, node->line, node->path);
+ 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_log(CIL_ERR, "No context assigned to SID %s declared at line %d in %s\n",sid->datum.name, node->line, node->path);
+ 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_log(CIL_ERR, "Invalid named range at line %d of %s\n", node->line, node->path);
+ return rc;
+}
+
+int __cil_verify_user(struct cil_db *db, 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++;
+ }
+ }
+
+ /* 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_log(CIL_ERR, "Invalid user at line %d of %s\n", node->line, node->path);
+ 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_log(CIL_ERR, "Invalid role at line %d of %s\n", node->line, node->path);
+ 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_log(CIL_ERR, "Invalid type at line %d of %s\n", node->line, node->path);
+ 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) {
+ cil_list_for_each(curr, user->roles) {
+ struct cil_role *userrole = curr->data;
+ if (userrole == role) {
+ break;
+ }
+ }
+
+ if (curr == NULL) {
+ 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_log(CIL_ERR, "Invalid named context at line %d of %s\n", node->line, node->path);
+ 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_log(CIL_ERR, "Duplicate rule defined on line %d of %s\n",
+ node->line, node->path);
+ rc = SEPOL_ERR;
+ goto exit;
+ }
+ }
+
+ return SEPOL_OK;
+exit:
+ cil_log(CIL_ERR, "Invalid rule at line %d of %s\n", node->line, node->path);
+ 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_log(CIL_ERR, "Neverallow found in tunableif block (treated as a booleanif due to preserve-tunables) at line %d or %s\n",
+ node->line, node->path);
+ } else {
+ cil_log(CIL_ERR, "Neverallow found in booleanif block at line %d or %s\n",
+ node->line, node->path);
+ }
+ 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_log(CIL_ERR, "Invalid %s statement in tunableif (treated as a booleanif due to preserve-tunables) at line %d of %s\n",
+ flavor, node->line, node->path);
+ } else {
+ cil_log(CIL_ERR, "Invalid %s statement in booleanif at line %d of %s\n",
+ flavor, node->line, node->path);
+ }
+ 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_log(CIL_ERR, "Invalid tunableif (treated as a booleanif due to preserve-tunables) at line %d of %s\n", node->line, node->path);
+ } else {
+ cil_log(CIL_ERR, "Invalid booleanif at line %d of %s\n", node->line, node->path);
+ }
+ 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_log(CIL_ERR, "Invalid netifcon at line %d of %s\n", node->line, node->path);
+ 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_log(CIL_ERR, "Invalid genfscon at line %d of %s\n", node->line, node->path);
+ 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_log(CIL_ERR, "Invalid filecon at line %d of %s\n",
+ node->line, node->path);
+ 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_log(CIL_ERR, "Invalid nodecon at line %d of %s\n", node->line, node->path);
+ 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_log(CIL_ERR, "Invalid portcon at line %d of %s\n", node->line, node->path);
+ 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_log(CIL_ERR, "Invalid pirqcon at line %d of %s\n", node->line, node->path);
+ 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_log(CIL_ERR, "Invalid iomemcon at line %d of %s\n", node->line, node->path);
+ 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_log(CIL_ERR, "Invalid ioportcon at line %d of %s\n", node->line, node->path);
+ 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_log(CIL_ERR, "Invalid pcidevicecon at line %d of %s\n", node->line, node->path);
+ 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_log(CIL_ERR, "Invalid fsuse at line %d of %s\n", node->line, node->path);
+ return rc;
+}
+
+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_log(CIL_ERR, "Invalid class at line %d of %s\n", node->line, node->path);
+ 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_log(CIL_ERR, "Invalid policycap (%s) at line %d of %s\n",
+ (const char*)polcap->datum.name, node->line, node->path);
+ 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 state = 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_OPTIONAL) {
+ state = ((struct cil_symtab_datum *)node->data)->state;
+ if (state == CIL_STATE_DISABLED) {
+ *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_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(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_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_FSUSE:
+ rc = __cil_verify_fsuse(db, 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;
+
+ rc = __cil_verify_classperms(cp->classperms, &cp->datum);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_ERR, "Found circular class permissions involving the set %s at line %d of %s\n",cp->datum.name, node->line, node->path);
+ return rc;
+ }
+
+ return SEPOL_OK;
+}
+
+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;
+
+ rc = __cil_verify_classperms(cmp->classperms, &cmp->datum);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_ERR, "Found circular class permissions involving the map class %s and permission %s at line %d of %s\n", map_args->class->datum.name, cmp->datum.name, map_args->node->line, map_args->node->path);
+ map_args->rc = SEPOL_ERR;
+ }
+
+ 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;
+}
+
+static int __cil_verify_no_classperms_loop_helper(struct cil_tree_node *node, uint32_t *finished, __attribute__((unused)) void *extra_args)
+{
+ int rc = SEPOL_ERR;
+
+ if (node->flavor == CIL_OPTIONAL) {
+ int state = ((struct cil_symtab_datum *)node->data)->state;
+ if (state == CIL_STATE_DISABLED) {
+ *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_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_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;
+}
+
+int cil_verify_no_classperms_loop(struct cil_db *db)
+{
+ int rc = SEPOL_ERR;
+
+ rc = cil_tree_walk(db->ast->root, __cil_verify_no_classperms_loop_helper, NULL, NULL, NULL);
+ if (rc != SEPOL_OK) {
+ cil_log(CIL_ERR, "Failed to verify no loops in class permissions\n");
+ goto exit;
+ }
+
+exit:
+ return rc;
+}
diff --git a/cil/src/cil_verify.h b/cil/src/cil_verify.h
new file mode 100644
index 0000000..1f47641
--- /dev/null
+++ b/cil/src/cil_verify.h
@@ -0,0 +1,73 @@
+/*
+ * 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 <stdint.h>
+
+#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_verify_no_classperms_loop(struct cil_db *db);
+
+#endif
diff --git a/cil/test/integration.cil b/cil/test/integration.cil
new file mode 100644
index 0000000..2d3ac96
--- /dev/null
+++ b/cil/test/integration.cil
@@ -0,0 +1,223 @@
+(type bin_t)
+(type kernel_t)
+(type security_t)
+(type unlabeled_t)
+
+(policycap open_perms)
+(sensitivity s0)
+(sensitivity s1)
+(sensitivityalias s0 sens0)
+(dominance (s0 s1))
+
+(category c0)
+(category c1)
+(category c2)
+(categoryalias c0 cat0)
+(categoryset cats01 (c0 c1))
+(categoryorder (c0 c1 c2))
+(categoryrange catrng02 (c0 c2))
+
+(sensitivitycategory s0 (catrng02))
+(sensitivitycategory s1 cats01)
+(sensitivitycategory s1 (c2))
+
+(level low (s0 (c0)))
+(level high (s1 (c0 c1)))
+(levelrange low_high (low high))
+
+(permissionset file_perms (execute_no_trans entrypoint execmod open
+ audit_access))
+(class file (execute_no_trans entrypoint execmod open audit_access))
+(class process (open))
+(common file (ioctl read write create getattr setattr lock relabelfrom
+ relabelto append unlink link rename execute swapon
+ quotaon mounton))
+(classcommon file file)
+
+(classpermissionset file_rw (file (read write getattr setattr lock append)))
+
+(class char (foo transition))
+(classcommon char file)
+
+(classpermissionset char_w (char (write setattr)))
+
+(classmap files (read))
+(classmapping files read
+ (file (open read getattr))
+ char_w)
+
+(type auditadm_t)
+(type console_t)
+(type console_device_t)
+(type user_tty_device_t)
+(type device_t)
+(type getty_t)
+(type exec_t)
+
+(allow console_t console_device_t file_rw)
+(allow console_t console_device_t (files (read)))
+
+(boolean secure_mode false)
+(boolean console_login true)
+
+
+(sid kernel)
+(sid security)
+(sid unlabeled)
+
+(typeattribute exec_type)
+(typeattribute foo_type)
+(typeattribute bar_type)
+(typeattribute baz_type)
+(typeattributeset exec_type (or bin_t kernel_t))
+(typeattributeset foo_type (and exec_type kernel_t))
+(typeattributeset bar_type (xor exec_type foo_type))
+(typeattributeset baz_type (not bin_t))
+(typealias bin_t sbin_t)
+(typepermissive device_t)
+(typebounds device_t bin_t)
+(typemember device_t bin_t file exec_t)
+(typetransition device_t console_t file console_device_t)
+
+(rangetransition device_t console_t file low_high)
+
+(nametypetransition some_file device_t console_t file getty_t)
+
+(allow foo_type self (file (execute)))
+(allow bin_t device_t (file (execute)))
+
+(booleanif secure_mode
+ (true
+ (auditallow device_t exec_t (file (read write)))
+ )
+)
+
+(booleanif console_login
+ (true
+ (typechange auditadm_t console_device_t file user_tty_device_t)
+ (allow getty_t console_device_t (file (getattr open read write append)))
+ )
+ (false
+ (dontaudit getty_t console_device_t (file (getattr open read write append)))
+ )
+)
+
+(booleanif (not (xor (eq secure_mode console_login)
+ (and (or secure_mode console_login) secure_mode ) ) )
+ (true
+ (allow bin_t exec_t (file (execute)))
+ )
+)
+
+(tunable allow_execfile true)
+(tunable allow_userexec false)
+
+(tunableif (not (xor (eq allow_execfile allow_userexec)
+ (and (or allow_execfile allow_userexec)
+ (and allow_execfile allow_userexec) ) ) )
+ (true
+ (allow bin_t exec_t (file (execute)))
+ )
+)
+
+(optional allow_rules
+ (allow user_t exec_t (bins (execute)))
+)
+
+(dontaudit device_t auditadm_t (file (read)))
+(auditallow device_t auditadm_t (file (open)))
+
+(user system_u)
+(user user_u)
+(userprefix user_u user)
+(userprefix system_u user)
+
+(selinuxuser name user_u low_high)
+(selinuxuserdefault user_u low_high)
+
+(role system_r)
+(role user_r)
+
+(roletype system_r bin_t)
+(roletype system_r kernel_t)
+(roletype system_r security_t)
+(roletype system_r unlabeled_t)
+(roleallow system_r user_r)
+(rolebounds system_r user_r)
+(roletransition system_r bin_t process user_r)
+
+(userrole system_u system_r)
+(userlevel system_u low)
+(userrange system_u low_high)
+(userbounds system_u user_u)
+(userrole user_u user_r)
+(userlevel user_u low)
+(userrange user_u (low low))
+
+(sidcontext kernel (system_u system_r kernel_t (low high)))
+(sidcontext security (system_u system_r security_t (low high)))
+(sidcontext unlabeled (system_u system_r unlabeled_t (low high)))
+
+(context system_u_bin_t_l2h (system_u system_r bin_t (low high)))
+
+(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::)
+
+(filecon "/usr/bin/" "foo" file system_u_bin_t_l2h)
+(filecon "/usr/bin/" "bar" file ())
+(filecon "/usr/bin/" "baz" any ())
+(nodecon ip_v4 netmask system_u_bin_t_l2h)
+(nodecon ip_v6 netmask_v6 system_u_bin_t_l2h)
+(portcon udp 25 system_u_bin_t_l2h)
+(portcon tcp 22 system_u_bin_t_l2h)
+(genfscon - "/usr/bin" system_u_bin_t_l2h)
+(netifcon eth0 system_u_bin_t_l2h system_u_bin_t_l2h) ;different contexts?
+(fsuse xattr ext3 system_u_bin_t_l2h)
+
+; XEN
+(pirqcon 256 system_u_bin_t_l2h)
+(iomemcon (0 255) system_u_bin_t_l2h)
+(ioportcon (22 22) system_u_bin_t_l2h)
+(pcidevicecon 345 system_u_bin_t_l2h)
+
+(constrain (files (read)) (not (or (and (eq t1 exec_t) (eq t2 bin_t)) (eq r1 r2))))
+(constrain char_w (not (or (and (eq t1 exec_t) (eq t2 bin_t)) (eq r1 r2))))
+
+(constrain (file (read)) (or (and (eq t1 exec_t) (neq t2 bin_t) ) (eq u1 u2) ) )
+(constrain (file (open)) (dom r1 r2))
+(constrain (file (open)) (domby r1 r2))
+(constrain (file (open)) (incomp r1 r2))
+
+(validatetrans file (eq t1 exec_t))
+
+(mlsconstrain (file (open)) (not (or (and (eq l1 l2) (eq u1 u2)) (eq r1 r2))))
+(mlsconstrain (file (open)) (or (and (eq l1 l2) (eq u1 u2)) (neq r1 r2)))
+(mlsconstrain (file (open)) (dom h1 l2))
+(mlsconstrain (file (open)) (domby l1 h2))
+(mlsconstrain (file (open)) (incomp l1 l2))
+
+(mlsvalidatetrans file (domby l1 h2))
+
+(macro all ((type x))
+ (allow x bin_t (file (execute)))
+)
+(call all (bin_t))
+
+(type a_t)
+(type b_t)
+(boolean b1 false)
+(tunable tun1 true)
+(macro m ((boolean b))
+ (tunableif tun1
+ (true
+ (allow a_t b_t (file (write))))
+ (false
+ (allow a_t b_t (file (execute)))))
+ (booleanif b
+ (true
+ (allow a_t b_t (file (read))))))
+
+(call m (b1))
+
diff --git a/cil/test/integration_testing/mls_policy.cil b/cil/test/integration_testing/mls_policy.cil
new file mode 100644
index 0000000..535ac11
--- /dev/null
+++ b/cil/test/integration_testing/mls_policy.cil
@@ -0,0 +1,115 @@
+(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)))
+
+
diff --git a/cil/test/integration_testing/nonmls.cil b/cil/test/integration_testing/nonmls.cil
new file mode 100644
index 0000000..382b95d
--- /dev/null
+++ b/cil/test/integration_testing/nonmls.cil
@@ -0,0 +1,86 @@
+(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)))
+
+
diff --git a/cil/test/integration_testing/nonmls.conf b/cil/test/integration_testing/nonmls.conf
new file mode 100644
index 0000000..729c7b1
--- /dev/null
+++ b/cil/test/integration_testing/nonmls.conf
@@ -0,0 +1,76 @@
+
+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
diff --git a/cil/test/integration_testing/ordered_lists_bad1.cil b/cil/test/integration_testing/ordered_lists_bad1.cil
new file mode 100644
index 0000000..321fe2f
--- /dev/null
+++ b/cil/test/integration_testing/ordered_lists_bad1.cil
@@ -0,0 +1,42 @@
+; 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))
diff --git a/cil/test/integration_testing/ordered_lists_bad2.cil b/cil/test/integration_testing/ordered_lists_bad2.cil
new file mode 100644
index 0000000..9e84191
--- /dev/null
+++ b/cil/test/integration_testing/ordered_lists_bad2.cil
@@ -0,0 +1,43 @@
+; 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))
+
diff --git a/cil/test/integration_testing/ordered_lists_bad3.cil b/cil/test/integration_testing/ordered_lists_bad3.cil
new file mode 100644
index 0000000..36aa687
--- /dev/null
+++ b/cil/test/integration_testing/ordered_lists_bad3.cil
@@ -0,0 +1,43 @@
+; 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))
diff --git a/cil/test/integration_testing/ordered_lists_easy.cil b/cil/test/integration_testing/ordered_lists_easy.cil
new file mode 100644
index 0000000..36df1e6
--- /dev/null
+++ b/cil/test/integration_testing/ordered_lists_easy.cil
@@ -0,0 +1,38 @@
+; 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))
+
diff --git a/cil/test/integration_testing/ordered_lists_hard.cil b/cil/test/integration_testing/ordered_lists_hard.cil
new file mode 100644
index 0000000..f00c5b1
--- /dev/null
+++ b/cil/test/integration_testing/ordered_lists_hard.cil
@@ -0,0 +1,43 @@
+; 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))
diff --git a/cil/test/integration_testing/small.cil b/cil/test/integration_testing/small.cil
new file mode 100644
index 0000000..9973166
--- /dev/null
+++ b/cil/test/integration_testing/small.cil
@@ -0,0 +1,5 @@
+(class foo (read))
+
+(type bar)
+(allow bar self (foo (read)))
+
diff --git a/cil/test/policy.cil b/cil/test/policy.cil
new file mode 100644
index 0000000..9c76cad
--- /dev/null
+++ b/cil/test/policy.cil
@@ -0,0 +1,322 @@
+(type bin_t)
+(type kernel_t)
+(type security_t)
+(type unlabeled_t)
+(handleunknown allow)
+(mls true)
+
+(policycap open_perms)
+
+(category c0)
+(category c1)
+(category c2)
+(category c3)
+(category c4)
+(category c5)
+(categoryalias cat0)
+(categoryaliasactual cat0 c0)
+(categoryset cats01 (c0 c1))
+(categoryset cats02 (c2 c3))
+(categoryset cats03 (range c0 c5))
+(categoryset cats04 (not (range c0 c2)))
+(categoryorder (cat0 c1 c2 c3))
+(categoryorder (c3 c4 c5))
+
+(sensitivity s0)
+(sensitivity s1)
+(sensitivity s2)
+(sensitivity s3)
+(sensitivityalias sens0)
+(sensitivityaliasactual sens0 s0)
+(sensitivityorder (s0 s1 s2 s3))
+
+(sensitivitycategory s0 (cats03))
+(sensitivitycategory s1 cats01)
+(sensitivitycategory s1 (c2))
+(sensitivitycategory s2 (cats01 cats02))
+(sensitivitycategory s2 (range c4 c5))
+(sensitivitycategory s3 (range c0 c5))
+
+(level low (s0))
+(level high (s3 (range c0 c3)))
+(levelrange low_high (low high))
+(levelrange lh1 ((s0 (c0)) (s2 (c0 c3))))
+(levelrange lh2 (low (s2 (c0 c3))))
+(levelrange lh3 ((s0 cats04) (s2 (range c0 c5))))
+(levelrange lh4 ((s0) (s1)))
+
+(block policy
+ (classorder (file char dir))
+ (class file (execute_no_trans entrypoint execmod open audit_access))
+ (common file (ioctl read write create getattr setattr lock relabelfrom
+ relabelto append unlink link rename execute swapon
+ quotaon mounton))
+ (classcommon file file)
+
+ (classpermission file_rw)
+ (classpermissionset file_rw (file (read write getattr setattr lock append)))
+
+ ;;(classpermission loop1)
+ ;;(classpermissionset loop1 ((loop2)))
+ ;;(classpermission loop2)
+ ;;(classpermissionset loop2 ((loop3)))
+ ;;(classpermission loop3)
+ ;;(classpermissionset loop3 ((loop1)))
+
+ (class char (foo))
+ (classcommon char file)
+
+ (class dir ())
+ (classcommon dir file)
+
+ (classpermission char_w)
+ (classpermissionset char_w (char (write setattr)))
+ (classpermissionset char_w (file (open read getattr)))
+
+ (classmap files (read))
+ (classmapping files read
+ (file (open read getattr)))
+ (classmapping files read
+ char_w)
+
+ (type auditadm_t)
+ (type console_t)
+ (type console_device_t)
+ (type user_tty_device_t)
+ (type device_t)
+ (type getty_t)
+ (type exec_t)
+ (type bad_t)
+
+ ;;(allow console_t console_device_t file_rw)
+ (allow console_t console_device_t (files (read)))
+
+ (boolean secure_mode false)
+ (boolean console_login true)
+
+ (sid kernel)
+ (sid security)
+ (sid unlabeled)
+ (sidorder (kernel security))
+ (sidorder (security unlabeled))
+
+ (typeattribute exec_type)
+ (typeattribute foo_type)
+ (typeattribute bar_type)
+ (typeattribute baz_type)
+ (typeattribute not_bad_type)
+ (typeattributeset exec_type (or bin_t kernel_t))
+ (typeattributeset foo_type (and exec_type kernel_t))
+ (typeattributeset bar_type (xor exec_type foo_type))
+ (typeattributeset baz_type (not bin_t))
+ (typeattributeset baz_type (and exec_type (and bar_type bin_t)))
+ (typeattributeset not_bad_type (not bad_t))
+ (typealias sbin_t)
+ (typealiasactual sbin_t bin_t)
+ (typepermissive device_t)
+ (typebounds device_t bin_t)
+ ;;(typebounds bin_t kernel_t) ;; This statement and the next can be used
+ ;;(typebounds kernel_t device_t) ;; to verify that circular bounds can be found
+ (typemember device_t bin_t file exec_t)
+ (typetransition device_t console_t files console_device_t)
+
+ (roleattribute exec_role)
+ (roleattribute foo_role)
+ (roleattribute bar_role)
+ (roleattribute baz_role)
+ (roleattributeset exec_role (or user_r system_r))
+ (roleattributeset foo_role (and exec_role system_r))
+ (roleattributeset bar_role (xor exec_role foo_role))
+ (roleattributeset baz_role (not user_r))
+
+ (rangetransition device_t console_t file low_high)
+ (rangetransition device_t kernel_t file ((s0) (s3 (not c3))))
+
+ (typetransition device_t console_t file "some_file" getty_t)
+
+ (allow foo_type self (file (execute)))
+ (allow bin_t device_t (file (execute)))
+
+ ;; Next two rules violate the neverallow rule that follows
+ ;;(allow bad_t not_bad_type (file (execute)))
+ ;;(allow bad_t exec_t (file (execute)))
+ (neverallow bad_t not_bad_type (file (execute)))
+
+ (booleanif secure_mode
+ (true
+ (auditallow device_t exec_t (file (read write)))
+ )
+ )
+
+ (booleanif console_login
+ (true
+ (typechange auditadm_t console_device_t file user_tty_device_t)
+ (allow getty_t console_device_t (file (getattr open read write append)))
+ )
+ (false
+ (dontaudit getty_t console_device_t (file (getattr open read write append)))
+ )
+ )
+
+ (booleanif (not (xor (eq secure_mode console_login)
+ (and (or secure_mode console_login) secure_mode ) ) )
+ (true
+ (allow bin_t exec_t (file (execute)))
+ )
+ )
+
+ (tunable allow_execfile true)
+ (tunable allow_userexec false)
+
+ (tunableif (not (xor (eq allow_execfile allow_userexec)
+ (and (or allow_execfile allow_userexec)
+ (and allow_execfile allow_userexec) ) ) )
+ (true
+ (allow bin_t exec_t (file (execute)))
+ )
+ )
+
+ (optional allow_rules
+ (allow user_t exec_t (bins (execute)))
+ )
+
+ (dontaudit device_t auditadm_t (file (read)))
+ (auditallow device_t auditadm_t (file (open)))
+
+ (user system_u)
+ (user user_u)
+ (user foo_u)
+ (userprefix user_u user)
+ (userprefix system_u user)
+
+ (selinuxuser name user_u low_high)
+ (selinuxuserdefault user_u ((s0 (c0)) (s3 (range c0 c3))))
+
+ (role system_r)
+ (role user_r)
+
+ (roletype system_r bin_t)
+ (roletype system_r kernel_t)
+ (roletype system_r security_t)
+ (roletype system_r unlabeled_t)
+ (roletype system_r exec_type)
+ (roletype exec_role bin_t)
+ (roletype exec_role exec_type)
+ (roleallow system_r user_r)
+ (rolebounds system_r user_r)
+ (roletransition system_r bin_t file user_r)
+
+ (userrole foo_u foo_role)
+ (userlevel foo_u low)
+ (userrange foo_u low_high)
+
+ (userrole system_u system_r)
+ (userlevel system_u low)
+ (userrange system_u low_high)
+ (userbounds system_u user_u)
+
+ (userrole user_u user_r)
+ (userlevel user_u (s0 (range c0 c2)))
+ (userrange user_u (low high))
+
+ (sidcontext kernel (system_u system_r kernel_t ((s0) high)))
+ (sidcontext security (system_u system_r security_t (low (s3 (range c0 c3)))))
+ (sidcontext unlabeled (system_u system_r unlabeled_t (low high)))
+
+ (context system_u_bin_t_l2h (system_u system_r bin_t (low high)))
+
+ (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::)
+
+ (filecon "/usr/bin/foo" file system_u_bin_t_l2h)
+ (filecon "/usr/bin/bar" file (system_u system_r kernel_t (low low)))
+ (filecon "/usr/bin/baz" any ())
+ (filecon "/usr/bin/aaa" any (system_u system_r kernel_t ((s0) (s3 (range c0 c2)))))
+ (filecon "/usr/bin/bbb" any (system_u system_r kernel_t ((s0 (c0)) high)))
+ (filecon "/usr/bin/ccc" any (system_u system_r kernel_t (low (s3 (cats01)))))
+ (filecon "/usr/bin/ddd" any (system_u system_r kernel_t (low (s3 (cats01 cats02)))))
+ (nodecon ip_v4 netmask system_u_bin_t_l2h)
+ (nodecon ip_v6 netmask_v6 system_u_bin_t_l2h)
+ (portcon udp 25 system_u_bin_t_l2h)
+ (portcon tcp 22 system_u_bin_t_l2h)
+ (genfscon - "/usr/bin" system_u_bin_t_l2h)
+ (netifcon eth0 system_u_bin_t_l2h system_u_bin_t_l2h) ;different contexts?
+ (fsuse xattr ext3 system_u_bin_t_l2h)
+
+ ; XEN
+ (pirqcon 256 system_u_bin_t_l2h)
+ (iomemcon (0 255) system_u_bin_t_l2h)
+ (ioportcon (22 22) system_u_bin_t_l2h)
+ (pcidevicecon 345 system_u_bin_t_l2h)
+
+ (constrain (files (read)) (not (or (and (eq t1 exec_t) (eq t2 bin_t)) (eq r1 r2))))
+ (constrain char_w (not (or (and (eq t1 exec_t) (eq t2 bin_t)) (eq r1 r2))))
+
+ (constrain (file (read)) (or (and (eq t1 exec_t) (neq t2 bin_t) ) (eq u1 u2) ) )
+ (constrain (file (open)) (dom r1 r2))
+ (constrain (file (open)) (domby r1 r2))
+ (constrain (file (open)) (incomp r1 r2))
+
+ (validatetrans file (eq t1 exec_t))
+
+ (mlsconstrain (file (open)) (not (or (and (eq l1 l2) (eq u1 u2)) (eq r1 r2))))
+ (mlsconstrain (file (open)) (or (and (eq l1 l2) (eq u1 u2)) (neq r1 r2)))
+ (mlsconstrain (file (open)) (dom h1 l2))
+ (mlsconstrain (file (open)) (domby l1 h2))
+ (mlsconstrain (file (open)) (incomp l1 l2))
+
+ (mlsvalidatetrans file (domby l1 h2))
+
+ (macro test_mapping ((classpermission cps))
+ (allow bin_t auditadm_t cps))
+
+ (call test_mapping ((file (read))))
+ (call test_mapping ((files (read))))
+ (call test_mapping (char_w))
+
+ (defaultuser (file char) source)
+ (defaultrole char target)
+ (defaulttype (files) source)
+ (defaultrange (file) target low)
+ (defaultrange (char) source low-high)
+)
+
+(macro all ((type x))
+ (allow x bin_t (policy.file (execute)))
+)
+(call all (bin_t))
+
+(block z
+ (block ba
+ (roletype r t)
+ (blockabstract z.ba)))
+
+(block test_ba
+ (blockinherit z.ba)
+ (role r)
+ (type t))
+
+(block bb
+ (type t1)
+ (type t2)
+ (boolean b1 false)
+ (tunable tun1 true)
+ (macro m ((boolean b))
+ (tunableif tun1
+ (true
+ (allow t1 t2 (policy.file (write))))
+ (false
+ (allow t1 t2 (policy.file (execute)))))
+ (booleanif b
+ (true
+ (allow t1 t2 (policy.file (read))))))
+
+ (call m (b1))
+)
+
+(in bb
+ (tunableif bb.tun1
+ (true
+ (allow bb.t2 bb.t1 (policy.file (read write execute))))))
diff --git a/cil/test/policy.conf b/cil/test/policy.conf
new file mode 100644
index 0000000..938af91
--- /dev/null
+++ b/cil/test/policy.conf
@@ -0,0 +1,143 @@
+class file
+class process
+class char
+
+sid kernel
+sid security
+sid unlabeled
+
+common file {ioctl read write create getattr setattr lock relabelfrom relabelto append unlink link rename execute swapon quotaon mounton }
+
+class file inherits file { execute_no_trans entrypoint execmod open audit_access }
+class char inherits file { foo transition }
+class process { open }
+
+sensitivity s0 alias sens0;
+sensitivity s1;
+
+dominance { s0 s1 }
+
+category c0 alias cat0;
+category c1;
+category c2;
+
+level s0:c0.c2;
+level s1:c0.c2;
+
+mlsconstrain file { open } (not (((l1 eq l2) and (u1 eq u2)) or (r1 eq r2)));
+mlsconstrain file { open } (((l1 eq l2) and (u1 eq u2)) or (r1 != r2));
+mlsconstrain file { open } (l1 dom h2);
+mlsconstrain file { open } (h1 domby l2);
+mlsconstrain file { open } (l1 incomp l2);
+
+mlsvalidatetrans file (h1 domby l2);
+
+attribute foo_type;
+attribute bar_type;
+attribute baz_type;
+attribute exec_type;
+
+type bin_t, bar_type, exec_type;
+type kernel_t, foo_type, exec_type, baz_type;
+type security_t, baz_type;
+type unlabeled_t, baz_type;
+
+type exec_t, baz_type;
+type console_t, baz_type;
+type auditadm_t, baz_type;
+type console_device_t, baz_type;
+type user_tty_device_t, baz_type;
+type device_t, baz_type;
+type getty_t, baz_type;
+type a_t, baz_type;
+type b_t, baz_type;
+
+typealias bin_t alias sbin_t;
+
+bool secure_mode false;
+bool console_login true;
+bool b1 false;
+
+role system_r;
+role user_r;
+role system_r types bin_t;
+role system_r types kernel_t;
+role system_r types security_t;
+role system_r types unlabeled_t;
+
+policycap open_perms;
+permissive device_t;
+
+range_transition device_t console_t : file s0:c0 - s1:c0.c1;
+
+type_transition device_t console_t : file console_device_t;
+type_member device_t bin_t : file exec_t;
+
+if console_login{
+ type_change auditadm_t console_device_t : file user_tty_device_t;
+}
+
+role_transition system_r bin_t user_r;
+
+auditallow device_t auditadm_t: file { open };
+dontaudit device_t auditadm_t: file { read };
+
+allow system_r user_r;
+
+allow console_t console_device_t: char { write setattr };
+allow console_t console_device_t: file { open read getattr };
+allow foo_type self: file { execute };
+allow bin_t device_t: file { execute };
+allow bin_t exec_t: file { execute };
+allow bin_t bin_t: file { execute };
+allow a_t b_t : file { write };
+allow console_t console_device_t: file { read write getattr setattr lock append };
+allow kernel_t kernel_t : file { execute };
+
+if b1 {
+ allow a_t b_t : file { read };
+}
+
+if secure_mode{
+ auditallow device_t exec_t: file { read write };
+}
+
+if console_login{
+ allow getty_t console_device_t: file { getattr open read write append };
+}
+else {
+ dontaudit getty_t console_device_t: file { getattr open read write append };
+}
+
+if (not ((secure_mode eq console_login) xor ((secure_mode or console_login) and secure_mode))){
+ allow bin_t exec_t: file { execute };
+}
+
+user system_u roles system_r level s0:c0 range s0:c0 - s1:c0,c1;
+user user_u roles user_r level s0:c0 range s0:c0 - s0:c0;
+
+validatetrans file (t1 == exec_t);
+
+constrain char transition (not (((t1 eq exec_t) and (t2 eq bin_t)) or (r1 eq r2)));
+constrain file { open } (r1 dom r2);
+constrain file { open } (r1 domby r2);
+constrain file { open } (r1 incomp r2);
+constrain file { open read getattr } (not (((t1 eq exec_t) and (t2 eq bin_t)) or (r1 eq r2)));
+constrain char { write setattr } (not (((t1 eq exec_t) and (t2 eq bin_t)) or (r1 eq r2)));
+
+
+sid kernel system_u:system_r:kernel_t:s0:c0 - s1:c0,c1
+sid security system_u:system_r:security_t:s0:c0 - s1:c0,c1
+sid unlabeled system_u:system_r:unlabeled_t:s0:c0 - s1:c0,c1
+
+fs_use_xattr ext3 system_u:system_r:bin_t:s0:c0 - s1:c0,c1;
+
+genfscon proc /usr/bin system_u:system_r:bin_t:s0:c0 - s1:c0,c1
+
+portcon tcp 22 system_u:system_r:bin_t:s0:c0 - s1:c0,c1
+portcon udp 25 system_u:system_r:bin_t:s0:c0 - s1:c0,c1
+
+netifcon eth0 system_u:system_r:bin_t:s0:c0 - s1:c0,c1 system_u:system_r:bin_t:s0:c0 - s1:c0,c1
+
+nodecon 192.25.35.200 192.168.1.1 system_u:system_r:bin_t:s0:c0 - s1:c0,c1
+nodecon 2001:db8:ac10:fe01:: 2001:de0:da88:2222:: system_u:system_r:bin_t:s0:c0 - s1:c0,c1
diff --git a/cil/test/unit/AllTests.c b/cil/test/unit/AllTests.c
new file mode 100644
index 0000000..40080c8
--- /dev/null
+++ b/cil/test/unit/AllTests.c
@@ -0,0 +1,76 @@
+/*
+ * 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 <stdio.h>
+#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;
+}
diff --git a/cil/test/unit/CilTest.c b/cil/test/unit/CilTest.c
new file mode 100644
index 0000000..c0c2f3b
--- /dev/null
+++ b/cil/test/unit/CilTest.c
@@ -0,0 +1,1974 @@
+/*
+ * 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 <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sepol/policydb/symtab.h>
+#include <sepol/policydb/policydb.h>
+
+#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;
+}
diff --git a/cil/test/unit/CilTest.h b/cil/test/unit/CilTest.h
new file mode 100644
index 0000000..f43b0ed
--- /dev/null
+++ b/cil/test/unit/CilTest.h
@@ -0,0 +1,44 @@
+/*
+ * 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
diff --git a/cil/test/unit/CuTest.c b/cil/test/unit/CuTest.c
new file mode 100644
index 0000000..9b481e3
--- /dev/null
+++ b/cil/test/unit/CuTest.c
@@ -0,0 +1,362 @@
+/*
+ * 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 <assert.h>
+#include <setjmp.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+
+#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);
+ }
+}
diff --git a/cil/test/unit/CuTest.h b/cil/test/unit/CuTest.h
new file mode 100644
index 0000000..c5ed90f
--- /dev/null
+++ b/cil/test/unit/CuTest.h
@@ -0,0 +1,139 @@
+/*
+ * 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 <setjmp.h>
+#include <stdarg.h>
+
+#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 */
diff --git a/cil/test/unit/test_cil.c b/cil/test/unit/test_cil.c
new file mode 100644
index 0000000..7b57525
--- /dev/null
+++ b/cil/test/unit/test_cil.c
@@ -0,0 +1,179 @@
+/*
+ * 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 <sepol/policydb/policydb.h>
+
+#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);
+}
+
diff --git a/cil/test/unit/test_cil.h b/cil/test/unit/test_cil.h
new file mode 100644
index 0000000..285b4ff
--- /dev/null
+++ b/cil/test/unit/test_cil.h
@@ -0,0 +1,46 @@
+/*
+ * 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
diff --git a/cil/test/unit/test_cil_build_ast.c b/cil/test/unit/test_cil_build_ast.c
new file mode 100644
index 0000000..f8cef71
--- /dev/null
+++ b/cil/test/unit/test_cil_build_ast.c
@@ -0,0 +1,19179 @@
+/*
+ * 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 <sepol/policydb/policydb.h>
+
+#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(&macro);
+
+ struct cil_tree_node *macronode;
+ cil_tree_node_init(&macronode);
+ 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(&macro);
+
+ struct cil_tree_node *macronode;
+ cil_tree_node_init(&macronode);
+ 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);
+}
+
diff --git a/cil/test/unit/test_cil_build_ast.h b/cil/test/unit/test_cil_build_ast.h
new file mode 100644
index 0000000..d697433
--- /dev/null
+++ b/cil/test/unit/test_cil_build_ast.h
@@ -0,0 +1,1198 @@
+/*
+ * 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
diff --git a/cil/test/unit/test_cil_copy_ast.c b/cil/test/unit/test_cil_copy_ast.c
new file mode 100644
index 0000000..0053e85
--- /dev/null
+++ b/cil/test/unit/test_cil_copy_ast.c
@@ -0,0 +1,2571 @@
+/*
+ * 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(&copy_list);
+
+ int rc =cil_copy_list(cil_l, &copy_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(&copy_list);
+
+ int rc = cil_copy_list(cil_l, &copy_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(&copy_list);
+
+ int rc = cil_copy_list(cil_l, &copy_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(&copy_list);
+
+ int rc = cil_copy_list(cil_l, &copy_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);
+}
diff --git a/cil/test/unit/test_cil_copy_ast.h b/cil/test/unit/test_cil_copy_ast.h
new file mode 100644
index 0000000..b1aace1
--- /dev/null
+++ b/cil/test/unit/test_cil_copy_ast.h
@@ -0,0 +1,176 @@
+/*
+ * 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
diff --git a/cil/test/unit/test_cil_fqn.c b/cil/test/unit/test_cil_fqn.c
new file mode 100644
index 0000000..4304fc1
--- /dev/null
+++ b/cil/test/unit/test_cil_fqn.c
@@ -0,0 +1,75 @@
+/*
+ * 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 <sepol/policydb/policydb.h>
+
+#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);
+}
diff --git a/cil/test/unit/test_cil_fqn.h b/cil/test/unit/test_cil_fqn.h
new file mode 100644
index 0000000..93f0ffd
--- /dev/null
+++ b/cil/test/unit/test_cil_fqn.h
@@ -0,0 +1,37 @@
+/*
+ * 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
diff --git a/cil/test/unit/test_cil_lexer.c b/cil/test/unit/test_cil_lexer.c
new file mode 100644
index 0000000..011afef
--- /dev/null
+++ b/cil/test/unit/test_cil_lexer.c
@@ -0,0 +1,100 @@
+/*
+ * 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 <sepol/policydb/policydb.h>
+
+#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);
+}
+
diff --git a/cil/test/unit/test_cil_lexer.h b/cil/test/unit/test_cil_lexer.h
new file mode 100644
index 0000000..78a4609
--- /dev/null
+++ b/cil/test/unit/test_cil_lexer.h
@@ -0,0 +1,38 @@
+/*
+ * 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
diff --git a/cil/test/unit/test_cil_list.c b/cil/test/unit/test_cil_list.c
new file mode 100644
index 0000000..b7a63af
--- /dev/null
+++ b/cil/test/unit/test_cil_list.c
@@ -0,0 +1,345 @@
+/*
+ * 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);
+}
diff --git a/cil/test/unit/test_cil_list.h b/cil/test/unit/test_cil_list.h
new file mode 100644
index 0000000..e627683
--- /dev/null
+++ b/cil/test/unit/test_cil_list.h
@@ -0,0 +1,46 @@
+/*
+ * 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
diff --git a/cil/test/unit/test_cil_parser.c b/cil/test/unit/test_cil_parser.c
new file mode 100644
index 0000000..43dc305
--- /dev/null
+++ b/cil/test/unit/test_cil_parser.c
@@ -0,0 +1,57 @@
+/*
+ * 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 <sepol/policydb/policydb.h>
+
+#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
+}
+
diff --git a/cil/test/unit/test_cil_parser.h b/cil/test/unit/test_cil_parser.h
new file mode 100644
index 0000000..2cb280d
--- /dev/null
+++ b/cil/test/unit/test_cil_parser.h
@@ -0,0 +1,37 @@
+/*
+ * 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
diff --git a/cil/test/unit/test_cil_post.c b/cil/test/unit/test_cil_post.c
new file mode 100644
index 0000000..8bb7e76
--- /dev/null
+++ b/cil/test/unit/test_cil_post.c
@@ -0,0 +1,703 @@
+/*
+ * 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 <sepol/policydb/policydb.h>
+
+#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);
+}
+
+
+
diff --git a/cil/test/unit/test_cil_post.h b/cil/test/unit/test_cil_post.h
new file mode 100644
index 0000000..b3c16a3
--- /dev/null
+++ b/cil/test/unit/test_cil_post.h
@@ -0,0 +1,79 @@
+/*
+ * 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
+
diff --git a/cil/test/unit/test_cil_resolve_ast.c b/cil/test/unit/test_cil_resolve_ast.c
new file mode 100644
index 0000000..1540c2b
--- /dev/null
+++ b/cil/test/unit/test_cil_resolve_ast.c
@@ -0,0 +1,11319 @@
+/*
+ * 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 <sepol/policydb/policydb.h>
+
+#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, &macro_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, &macro_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, &macro_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);
+}
+
diff --git a/cil/test/unit/test_cil_resolve_ast.h b/cil/test/unit/test_cil_resolve_ast.h
new file mode 100644
index 0000000..394efde
--- /dev/null
+++ b/cil/test/unit/test_cil_resolve_ast.h
@@ -0,0 +1,578 @@
+/*
+ * 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
diff --git a/cil/test/unit/test_cil_symtab.c b/cil/test/unit/test_cil_symtab.c
new file mode 100644
index 0000000..379149a
--- /dev/null
+++ b/cil/test/unit/test_cil_symtab.c
@@ -0,0 +1,61 @@
+/*
+ * 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 <sepol/policydb/policydb.h>
+
+#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);
+}
diff --git a/cil/test/unit/test_cil_symtab.h b/cil/test/unit/test_cil_symtab.h
new file mode 100644
index 0000000..76053af
--- /dev/null
+++ b/cil/test/unit/test_cil_symtab.h
@@ -0,0 +1,37 @@
+/*
+ * 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
diff --git a/cil/test/unit/test_cil_tree.c b/cil/test/unit/test_cil_tree.c
new file mode 100644
index 0000000..8bdc113
--- /dev/null
+++ b/cil/test/unit/test_cil_tree.c
@@ -0,0 +1,71 @@
+/*
+ * 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 <sepol/policydb/policydb.h>
+
+#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);
+}
+
diff --git a/cil/test/unit/test_cil_tree.h b/cil/test/unit/test_cil_tree.h
new file mode 100644
index 0000000..15c0824
--- /dev/null
+++ b/cil/test/unit/test_cil_tree.h
@@ -0,0 +1,38 @@
+/*
+ * 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
diff --git a/cil/test/unit/test_integration.c b/cil/test/unit/test_integration.c
new file mode 100644
index 0000000..d9cdb46
--- /dev/null
+++ b/cil/test/unit/test_integration.c
@@ -0,0 +1,76 @@
+/*
+ * 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 <sepol/policydb/policydb.h>
+
+#include "CuTest.h"
+#include "test_integration.h"
+#include <unistd.h>
+#include <sys/wait.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+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));
+}
diff --git a/cil/test/unit/test_integration.h b/cil/test/unit/test_integration.h
new file mode 100644
index 0000000..4cbcce3
--- /dev/null
+++ b/cil/test/unit/test_integration.h
@@ -0,0 +1,38 @@
+/*
+ * 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
diff --git a/include/Makefile b/include/Makefile
index 2ef418c..56b7a11 100644
--- a/include/Makefile
+++ b/include/Makefile
@@ -1,14 +1,17 @@
# Installation directories.
PREFIX ?= $(DESTDIR)/usr
INCDIR ?= $(PREFIX)/include/sepol
+CILDIR ?= ../cil
all:
install: all
test -d $(INCDIR) || install -m 755 -d $(INCDIR)
test -d $(INCDIR)/policydb || install -m 755 -d $(INCDIR)/policydb
+ test -d $(INCDIR)/cil || install -m 755 -d $(INCDIR)/cil
install -m 644 $(wildcard sepol/*.h) $(INCDIR)
install -m 644 $(wildcard sepol/policydb/*.h) $(INCDIR)/policydb
+ install -m 644 $(wildcard $(CILDIR)/include/cil/*.h) $(INCDIR)/cil
indent:
../../scripts/Lindent $(wildcard sepol/*.h)
diff --git a/include/sepol/policydb.h b/include/sepol/policydb.h
index a726b81..c3943e9 100644
--- a/include/sepol/policydb.h
+++ b/include/sepol/policydb.h
@@ -93,6 +93,12 @@ extern int sepol_policydb_set_vers(sepol_policydb_t * p, unsigned int vers);
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
diff --git a/include/sepol/policydb/avtab.h b/include/sepol/policydb/avtab.h
index e75b18a..3f56a0e 100644
--- a/include/sepol/policydb/avtab.h
+++ b/include/sepol/policydb/avtab.h
@@ -84,7 +84,7 @@ typedef struct avtab {
avtab_ptr_t *htable;
uint32_t nel; /* number of elements */
uint32_t nslot; /* number of hash slots */
- uint16_t mask; /* mask to compute hash func */
+ uint32_t mask; /* mask to compute hash func */
} avtab_t;
extern int avtab_init(avtab_t *);
@@ -120,10 +120,11 @@ 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 13
+#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)
-#define MAX_AVTAB_SIZE MAX_AVTAB_HASH_BUCKETS
+/* avtab_alloc uses one bucket per 2-4 elements, so adjust to get maximum buckets */
+#define MAX_AVTAB_SIZE (MAX_AVTAB_HASH_BUCKETS << 1)
__END_DECLS
#endif /* _AVTAB_H_ */
diff --git a/include/sepol/policydb/policydb.h b/include/sepol/policydb/policydb.h
index 20239a0..6254fef 100644
--- a/include/sepol/policydb/policydb.h
+++ b/include/sepol/policydb/policydb.h
@@ -743,8 +743,6 @@ extern int policydb_set_target_platform(policydb_t *p, int platform);
#define POLICYDB_STRING_MAX_LENGTH 32
#define POLICYDB_MOD_MAGIC SELINUX_MOD_MAGIC
#define POLICYDB_MOD_STRING "SE Linux Module"
-#define SEPOL_TARGET_SELINUX 0
-#define SEPOL_TARGET_XEN 1
__END_DECLS
#endif /* _POLICYDB_H_ */
diff --git a/include/sepol/policydb/services.h b/include/sepol/policydb/services.h
index 9ac495a..8a5dc9a 100644
--- a/include/sepol/policydb/services.h
+++ b/include/sepol/policydb/services.h
@@ -78,6 +78,20 @@ extern int sepol_compute_av_reason_buffer(sepol_security_id_t ssid,
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'.
@@ -212,7 +226,7 @@ extern int sepol_fs_use(const char *fstype, /* IN */
* fixed labeling behavior like transition SIDs or task SIDs.
*/
extern int sepol_genfs_sid(const char *fstype, /* IN */
- char *name, /* IN */
+ const char *name, /* IN */
sepol_security_class_t sclass, /* IN */
sepol_security_id_t * sid); /* OUT */
diff --git a/src/Makefile b/src/Makefile
index e10d356..db6c2ba 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -5,32 +5,58 @@ LIBDIR ?= $(PREFIX)/lib
SHLIBDIR ?= $(DESTDIR)/lib
RANLIB ?= ranlib
LIBBASE ?= $(shell basename $(LIBDIR))
+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,$(wildcard *.c))
LOBJS= $(patsubst %.c,%.lo,$(wildcard *.c))
-CFLAGS ?= -Werror -Wall -W -Wundef -Wshadow -Wmissing-noreturn -Wmissing-format-attribute
+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,$(wildcard $(CILDIR)/src/*.c) $(CIL_GENERATED)))
+LOBJS += $(sort $(patsubst %.c,%.lo,$(wildcard $(CILDIR)/src/*.c) $(CIL_GENERATED)))
+override CFLAGS += -I$(CILDIR)/include
+endif
+
+
all: $(LIBA) $(LIBSO) $(LIBPC)
+
$(LIBA): $(OBJS)
$(AR) rcs $@ $^
$(RANLIB) $@
-$(LIBSO): $(LOBJS)
- $(CC) $(CFLAGS) $(LDFLAGS) -shared -o $@ $^ -Wl,-soname,$(LIBSO),--version-script=libsepol.map,-z,defs
+$(LIBSO): $(LOBJS) $(LIBMAP)
+ $(CC) $(CFLAGS) $(LDFLAGS) -shared -o $@ $(LOBJS) -Wl,-soname,$(LIBSO),--version-script=$(LIBMAP),-z,defs
ln -sf $@ $(TARGET)
$(LIBPC): $(LIBPC).in ../VERSION
sed -e 's/@VERSION@/$(VERSION)/; s:@prefix@:$(PREFIX):; s:@libdir@:$(LIBBASE):; 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.c: $(CILDIR)/src/cil_lexer.l
+ $(LEX) -t $< > $@
+endif
+
%.o: %.c
$(CC) $(CFLAGS) -fPIC -c -o $@ $<
@@ -44,13 +70,13 @@ install: all
install -m 755 $(LIBSO) $(SHLIBDIR)
test -d $(LIBDIR)/pkgconfig || install -m 755 -d $(LIBDIR)/pkgconfig
install -m 644 $(LIBPC) $(LIBDIR)/pkgconfig
- cd $(LIBDIR) && ln -sf ../../`basename $(SHLIBDIR)`/$(LIBSO) $(TARGET)
+ ln -sf --relative $(SHLIBDIR)/$(LIBSO) $(LIBDIR)/$(TARGET)
relabel:
/sbin/restorecon $(SHLIBDIR)/$(LIBSO)
clean:
- -rm -f $(LIBPC) $(OBJS) $(LOBJS) $(LIBA) $(LIBSO) $(TARGET)
+ -rm -f $(LIBPC) $(OBJS) $(LOBJS) $(LIBA) $(LIBSO) $(TARGET) $(CIL_GENERATED)
indent:
../../scripts/Lindent $(wildcard *.[ch])
diff --git a/src/avtab.c b/src/avtab.c
index ea947cb..d6041d4 100644
--- a/src/avtab.c
+++ b/src/avtab.c
@@ -49,10 +49,43 @@
#include "debug.h"
#include "private.h"
-static inline int avtab_hash(struct avtab_key *keyp, uint16_t mask)
+/* 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)
{
- return ((keyp->target_class + (keyp->target_type << 2) +
- (keyp->source_type << 9)) & 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
@@ -300,7 +333,7 @@ int avtab_init(avtab_t * h)
int avtab_alloc(avtab_t *h, uint32_t nrules)
{
- uint16_t mask = 0;
+ uint32_t mask = 0;
uint32_t shift = 0;
uint32_t work = nrules;
uint32_t nslot = 0;
@@ -315,8 +348,8 @@ int avtab_alloc(avtab_t *h, uint32_t nrules)
if (shift > 2)
shift = shift - 2;
nslot = 1 << shift;
- if (nslot > MAX_AVTAB_SIZE)
- nslot = MAX_AVTAB_SIZE;
+ if (nslot > MAX_AVTAB_HASH_BUCKETS)
+ nslot = MAX_AVTAB_HASH_BUCKETS;
mask = nslot - 1;
h->htable = calloc(nslot, sizeof(avtab_ptr_t));
diff --git a/src/expand.c b/src/expand.c
index 9c327b6..467f7a7 100644
--- a/src/expand.c
+++ b/src/expand.c
@@ -49,82 +49,6 @@ typedef struct expand_state {
int expand_neverallow;
} expand_state_t;
-struct linear_probe {
- filename_trans_t **table; /* filename_trans chunks with same stype */
- filename_trans_t **ends; /* pointers to ends of **table chunks */
- uint32_t length; /* length of the table */
-};
-
-static int linear_probe_create(struct linear_probe *probe, uint32_t length)
-{
- probe->table = calloc(length, sizeof(*probe->table));
- if (probe->table == NULL)
- return -1;
-
- probe->ends = calloc(length, sizeof(*probe->ends));
- if (probe->ends == NULL)
- return -1;
-
- probe->length = length;
-
- return 0;
-}
-
-static void linear_probe_destroy(struct linear_probe *probe)
-{
- if (probe->length == 0)
- return;
-
- free(probe->table);
- free(probe->ends);
- memset(probe, 0, sizeof(*probe));
-}
-
-static void linear_probe_insert(struct linear_probe *probe, uint32_t key,
- filename_trans_t *data)
-{
- assert(probe->length > key);
-
- if (probe->table[key] != NULL) {
- data->next = probe->table[key];
- probe->table[key] = data;
- } else {
- probe->table[key] = probe->ends[key] = data;
- }
-}
-
-static filename_trans_t *linear_probe_find(struct linear_probe *probe, uint32_t key)
-{
- assert(probe->length > key);
-
- return probe->table[key];
-}
-
-/* Returns all chunks stored in the *probe as single-linked list */
-static filename_trans_t *linear_probe_dump(struct linear_probe *probe,
- filename_trans_t **endp)
-{
- uint32_t i;
- filename_trans_t *result = NULL;
- filename_trans_t *end = NULL;
-
- for (i = 0; i < probe->length; i++) {
- if (probe->table[i] != NULL) {
- if (end == NULL)
- end = probe->ends[i];
- probe->ends[i]->next = result;
- result = probe->table[i];
- probe->table[i] = probe->ends[i] = NULL;
- }
- }
-
- /* Incoherent result and end pointers indicates bug */
- assert((result != NULL && end != NULL) || (result == NULL && end == NULL));
-
- *endp = end;
- return result;
-}
-
static void expand_state_init(expand_state_t * state)
{
memset(state, 0, sizeof(expand_state_t));
@@ -1459,20 +1383,10 @@ static int copy_role_trans(expand_state_t * state, role_trans_rule_t * rules)
static int expand_filename_trans(expand_state_t *state, filename_trans_rule_t *rules)
{
unsigned int i, j;
- filename_trans_t *new_trans, *cur_trans, *end;
+ filename_trans_t *new_trans, *cur_trans;
filename_trans_rule_t *cur_rule;
ebitmap_t stypes, ttypes;
ebitmap_node_t *snode, *tnode;
- struct linear_probe probe;
-
- /*
- * Linear probing speeds-up finding filename_trans rules with certain
- * "stype" value.
- */
- if (linear_probe_create(&probe, 4096)) { /* Assume 4096 is enough for most cases */
- ERR(state->handle, "Out of memory!");
- return -1;
- }
cur_rule = rules;
while (cur_rule) {
@@ -1495,14 +1409,6 @@ static int expand_filename_trans(expand_state_t *state, filename_trans_rule_t *r
mapped_otype = state->typemap[cur_rule->otype - 1];
- if (ebitmap_length(&stypes) > probe.length) {
- linear_probe_destroy(&probe);
- if (linear_probe_create(&probe, ebitmap_length(&stypes))) {
- ERR(state->handle, "Out of memory!");
- return -1;
- }
- }
-
ebitmap_for_each_bit(&stypes, snode, i) {
if (!ebitmap_node_get_bit(snode, i))
continue;
@@ -1510,19 +1416,21 @@ static int expand_filename_trans(expand_state_t *state, filename_trans_rule_t *r
if (!ebitmap_node_get_bit(tnode, j))
continue;
- cur_trans = linear_probe_find(&probe, i);
- while (cur_trans != NULL) {
- if ((cur_trans->ttype == j + 1) &&
+ cur_trans = state->out->filename_trans;
+ while (cur_trans) {
+ if ((cur_trans->stype == i + 1) &&
+ (cur_trans->ttype == j + 1) &&
(cur_trans->tclass == cur_rule->tclass) &&
(!strcmp(cur_trans->name, cur_rule->name))) {
/* duplicate rule, who cares */
if (cur_trans->otype == mapped_otype)
break;
- ERR(state->handle, "Conflicting filename trans rules %s %s %s : %s otype1:%s otype2:%s",
- cur_trans->name,
+
+ 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_trans->tclass - 1],
+ cur_trans->name,
state->out->p_type_val_to_name[cur_trans->otype - 1],
state->out->p_type_val_to_name[mapped_otype - 1]);
@@ -1540,6 +1448,8 @@ static int expand_filename_trans(expand_state_t *state, filename_trans_rule_t *r
return -1;
}
memset(new_trans, 0, sizeof(*new_trans));
+ new_trans->next = state->out->filename_trans;
+ state->out->filename_trans = new_trans;
new_trans->name = strdup(cur_rule->name);
if (!new_trans->name) {
@@ -1550,16 +1460,9 @@ static int expand_filename_trans(expand_state_t *state, filename_trans_rule_t *r
new_trans->ttype = j + 1;
new_trans->tclass = cur_rule->tclass;
new_trans->otype = mapped_otype;
- linear_probe_insert(&probe, i, new_trans);
}
}
- cur_trans = linear_probe_dump(&probe, &end);
- if (cur_trans != NULL) {
- end->next = state->out->filename_trans;
- state->out->filename_trans = cur_trans;
- }
-
ebitmap_destroy(&stypes);
ebitmap_destroy(&ttypes);
@@ -3256,12 +3159,12 @@ static int expand_avtab_node(avtab_key_t * k, avtab_datum_t * d, void *args)
newkey.target_class = k->target_class;
newkey.specified = k->specified;
- if (stype->flavor != TYPE_ATTRIB && ttype->flavor != TYPE_ATTRIB) {
+ 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->flavor != TYPE_ATTRIB) {
+ 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) {
@@ -3275,7 +3178,7 @@ static int expand_avtab_node(avtab_key_t * k, avtab_datum_t * d, void *args)
return 0;
}
- if (ttype->flavor != TYPE_ATTRIB) {
+ 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) {
@@ -3386,12 +3289,12 @@ int expand_cond_av_node(policydb_t * p,
newkey.target_class = k->target_class;
newkey.specified = k->specified;
- if (stype->flavor != TYPE_ATTRIB && ttype->flavor != TYPE_ATTRIB) {
+ 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->flavor != TYPE_ATTRIB) {
+ 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) {
@@ -3405,7 +3308,7 @@ int expand_cond_av_node(policydb_t * p,
return 0;
}
- if (ttype->flavor != TYPE_ATTRIB) {
+ 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) {
diff --git a/src/libsepol.map.in b/src/libsepol.map.in
new file mode 100644
index 0000000..c18f57d
--- /dev/null
+++ b/src/libsepol.map.in
@@ -0,0 +1,36 @@
+{
+ 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_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: *;
+};
diff --git a/src/link.c b/src/link.c
index 709f4e2..f98a8d2 100644
--- a/src/link.c
+++ b/src/link.c
@@ -2089,7 +2089,7 @@ static int debug_requirements(link_state_t * state, policydb_t * p)
if (ret < 0) {
return ret;
} else if (ret == 0) {
- char *mod_name = cur->branch_list->module_name ?
+ 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;
@@ -2148,7 +2148,7 @@ static void print_missing_requirements(link_state_t * state,
missing_requirement_t * req)
{
policydb_t *p = state->base;
- char *mod_name = cur->branch_list->module_name ?
+ const char *mod_name = cur->branch_list->module_name ?
cur->branch_list->module_name : "BASE";
if (req->symbol_type == SYM_CLASSES) {
@@ -2220,7 +2220,7 @@ static int enable_avrules(link_state_t * state, policydb_t * pol)
}
decl = block->branch_list;
if (state->verbose) {
- char *mod_name = decl->module_name ?
+ 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);
diff --git a/src/policydb.c b/src/policydb.c
index 8c372fd..667e98a 100644
--- a/src/policydb.c
+++ b/src/policydb.c
@@ -55,7 +55,7 @@
#include "mls.h"
#define POLICYDB_TARGET_SZ ARRAY_SIZE(policydb_target_strings)
-char *policydb_target_strings[] = { POLICYDB_STRING, POLICYDB_XEN_STRING };
+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[] = {
diff --git a/src/policydb_internal.h b/src/policydb_internal.h
index 8a31506..f7bcdfa 100644
--- a/src/policydb_internal.h
+++ b/src/policydb_internal.h
@@ -6,5 +6,5 @@
hidden_proto(sepol_policydb_create)
hidden_proto(sepol_policydb_free)
-extern char *policydb_target_strings[];
+extern const char *policydb_target_strings[];
#endif
diff --git a/src/policydb_public.c b/src/policydb_public.c
index f6ae793..e721842 100644
--- a/src/policydb_public.c
+++ b/src/policydb_public.c
@@ -152,6 +152,23 @@ int sepol_policydb_set_handle_unknown(sepol_policydb_t * sp,
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);
diff --git a/src/services.c b/src/services.c
index 73faa05..d64a8e8 100644
--- a/src/services.c
+++ b/src/services.c
@@ -174,7 +174,7 @@ static char **expr_list;
static int expr_buf_used;
static int expr_buf_len;
-static void cat_expr_buf(char *e_buf, char *string)
+static void cat_expr_buf(char *e_buf, const char *string)
{
int len, new_buf_len;
char *p, *new_buf = e_buf;
@@ -209,7 +209,7 @@ static void cat_expr_buf(char *e_buf, char *string)
* POLICYDB_VERSION_CONSTRAINT_NAMES) just read the e->names list.
*/
static void get_name_list(constraint_expr_t *e, int type,
- char *src, char *op, int failed)
+ const char *src, const char *op, int failed)
{
ebitmap_t *types;
int rc = 0;
@@ -273,7 +273,7 @@ static void get_name_list(constraint_expr_t *e, int type,
return;
}
-static void msgcat(char *src, char *tgt, char *op, int failed)
+static void msgcat(const char *src, const char *tgt, const char *op, int failed)
{
char tmp_buf[128];
if (failed)
@@ -303,7 +303,7 @@ static char *get_class_info(sepol_security_class_t tclass,
}
/* Determine statement type */
- char *statements[] = {
+ const char *statements[] = {
"constrain ", /* 0 */
"mlsconstrain ", /* 1 */
"validatetrans ", /* 2 */
@@ -344,11 +344,16 @@ static char *get_class_info(sepol_security_class_t tclass,
if (len < 0 || len >= class_buf_len - buf_used)
continue;
- /* Add permission entries */
+ /* Add permission entries (validatetrans does not have perms) */
p += len;
buf_used += len;
- len = snprintf(p, class_buf_len - buf_used, "{%s } (",
- sepol_av_to_string(policydb, tclass, constraint->permissions));
+ 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;
@@ -412,6 +417,12 @@ static int constraint_expr_eval_reason(context_struct_t *scontext,
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");
@@ -681,13 +692,9 @@ mls_ops:
expr_counter = 0;
/*
- * The array of expression answer buffer pointers and counter.
* Generate the same number of answer buffer entries as expression
* buffers (as there will never be more).
*/
- char **answer_list;
- int answer_counter = 0;
-
answer_list = malloc(expr_count * sizeof(*answer_list));
if (!answer_list) {
ERR(NULL, "failed to allocate answer stack");
@@ -723,6 +730,7 @@ mls_ops:
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);
@@ -743,6 +751,7 @@ mls_ops:
expr_list[x], b);
push(answer_list[answer_counter++]);
free(b);
+ free(expr_list[x]);
} else {
push(expr_list[x]);
}
@@ -750,8 +759,11 @@ mls_ops:
/* Get the final answer from tos and build constraint text */
a = pop();
- /* Constraint calculation: rc = 0 is denied, rc = 1 is granted */
- sprintf(tmp_buf, "Constraint %s\n", s[0] ? "GRANTED" : "DENIED");
+ /* 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;
@@ -759,7 +771,7 @@ mls_ops:
* These contain the constraint components that are added to the
* callers reason buffer.
*/
- char *buffers[] = { class_buf, a, "); ", tmp_buf, 0 };
+ const char *buffers[] = { class_buf, a, "); ", tmp_buf, 0 };
/*
* This will add the constraints to the callers reason buffer (who is
@@ -807,6 +819,8 @@ out:
for (x = 0; expr_list[x] != NULL; x++)
free(expr_list[x]);
}
+ free(answer_list);
+ free(expr_list);
return rc;
}
@@ -982,6 +996,68 @@ int hidden sepol_validate_transition(sepol_security_id_t oldsid,
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,
@@ -2009,7 +2085,7 @@ int hidden sepol_get_user_sids(sepol_security_id_t fromsid,
* fixed labeling behavior like transition SIDs or task SIDs.
*/
int hidden sepol_genfs_sid(const char *fstype,
- char *path,
+ const char *path,
sepol_security_class_t sclass,
sepol_security_id_t * sid)
{
diff --git a/src/write.c b/src/write.c
index 0224b5a..d03dc20 100644
--- a/src/write.c
+++ b/src/write.c
@@ -1880,7 +1880,7 @@ int policydb_write(policydb_t * p, struct policy_file *fp)
size_t items, items2, len;
struct policydb_compat_info *info;
struct policy_data pd;
- char *policydb_str;
+ const char *policydb_str;
if (p->unsupported_format)
return POLICYDB_UNSUPPORTED;
diff --git a/tests/test-linker-roles.c b/tests/test-linker-roles.c
index 42f92d3..2c4a804 100644
--- a/tests/test-linker-roles.c
+++ b/tests/test-linker-roles.c
@@ -101,7 +101,7 @@ void module_role_tests(policydb_t * base)
{
role_datum_t *role;
avrule_decl_t *decl;
- unsigned int decls[2];
+ unsigned int decls[3];
char *types[3];
/* These tests are run when the base is linked with 2 modules,