pax_global_header00006660000000000000000000000064147621173720014524gustar00rootroot0000000000000052 comment=8e9157bbeea1899b7b8b257e7eaa71efef3fffed libsepol-3.8.1/000077500000000000000000000000001476211737200133465ustar00rootroot00000000000000libsepol-3.8.1/.gitignore000066400000000000000000000002411476211737200153330ustar00rootroot00000000000000utils/chkcon utils/sepol_check_access utils/sepol_compute_av utils/sepol_compute_member utils/sepol_compute_relabel utils/sepol_validate_transition libsepol.map libsepol-3.8.1/LICENSE000066400000000000000000000635001476211737200143570ustar00rootroot00000000000000 GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! libsepol-3.8.1/Makefile000066400000000000000000000006271476211737200150130ustar00rootroot00000000000000DISABLE_CIL ?= n export DISABLE_CIL all: $(MAKE) -C src $(MAKE) -C utils install: $(MAKE) -C include install $(MAKE) -C src install $(MAKE) -C utils install $(MAKE) -C man install relabel: $(MAKE) -C src relabel clean: $(MAKE) -C src clean $(MAKE) -C utils clean $(MAKE) -C tests clean indent: $(MAKE) -C src $@ $(MAKE) -C include $@ $(MAKE) -C utils $@ test: $(MAKE) -C tests test libsepol-3.8.1/VERSION000066400000000000000000000000061476211737200144120ustar00rootroot000000000000003.8.1 libsepol-3.8.1/cil/000077500000000000000000000000001476211737200141155ustar00rootroot00000000000000libsepol-3.8.1/cil/.gitignore000066400000000000000000000001711476211737200161040ustar00rootroot00000000000000*.swp *.gcda *.gcno *.o *.a src/cil_lexer.c unit_tests cov secilc docs/pdf/ docs/html/ docs/man8/ policy.* file_contexts libsepol-3.8.1/cil/include/000077500000000000000000000000001476211737200155405ustar00rootroot00000000000000libsepol-3.8.1/cil/include/cil/000077500000000000000000000000001476211737200163075ustar00rootroot00000000000000libsepol-3.8.1/cil/include/cil/cil.h000066400000000000000000000073511476211737200172350ustar00rootroot00000000000000/* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #ifndef CIL_H_ #define CIL_H_ #include #ifdef __cplusplus extern "C" { #endif struct cil_db; typedef struct cil_db cil_db_t; extern void cil_db_init(cil_db_t **db); extern void cil_db_destroy(cil_db_t **db); extern int cil_add_file(cil_db_t *db, const char *name, const char *data, size_t size); extern int cil_compile(cil_db_t *db); extern int cil_build_policydb(cil_db_t *db, sepol_policydb_t **sepol_db); extern int cil_userprefixes_to_string(cil_db_t *db, char **out, size_t *size); extern int cil_selinuxusers_to_string(cil_db_t *db, char **out, size_t *size); extern int cil_filecons_to_string(cil_db_t *db, char **out, size_t *size); extern void cil_set_disable_dontaudit(cil_db_t *db, int disable_dontaudit); extern void cil_set_multiple_decls(cil_db_t *db, int multiple_decls); extern void cil_set_qualified_names(struct cil_db *db, int qualified_names); extern void cil_set_disable_neverallow(cil_db_t *db, int disable_neverallow); extern void cil_set_preserve_tunables(cil_db_t *db, int preserve_tunables); extern int cil_set_handle_unknown(cil_db_t *db, int handle_unknown); extern void cil_set_mls(cil_db_t *db, int mls); extern void cil_set_attrs_expand_generated(struct cil_db *db, int attrs_expand_generated); extern void cil_set_attrs_expand_size(struct cil_db *db, unsigned attrs_expand_size); extern void cil_set_target_platform(cil_db_t *db, int target_platform); extern void cil_set_policy_version(cil_db_t *db, int policy_version); extern void cil_write_policy_conf(FILE *out, struct cil_db *db); extern int cil_write_parse_ast(FILE *out, cil_db_t *db); extern int cil_write_build_ast(FILE *out, cil_db_t *db); extern int cil_write_resolve_ast(FILE *out, cil_db_t *db); extern int cil_write_post_ast(FILE *out, cil_db_t *db); enum cil_log_level { CIL_ERR = 1, CIL_WARN, CIL_INFO }; extern void cil_set_log_level(enum cil_log_level lvl); extern void cil_set_log_handler(void (*handler)(int lvl, const char *msg)); #ifdef __GNUC__ __attribute__ ((format(printf, 2, 3))) #endif extern void cil_log(enum cil_log_level lvl, const char *msg, ...); extern void cil_set_malloc_error_handler(void (*handler)(void)); #ifdef __cplusplus } #endif #endif libsepol-3.8.1/cil/src/000077500000000000000000000000001476211737200147045ustar00rootroot00000000000000libsepol-3.8.1/cil/src/cil.c000066400000000000000000002165171476211737200156330ustar00rootroot00000000000000/* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #include #include #include #include #include "cil_internal.h" #include "cil_flavor.h" #include "cil_log.h" #include "cil_mem.h" #include "cil_tree.h" #include "cil_list.h" #include "cil_symtab.h" #include "cil_build_ast.h" #include "cil_parser.h" #include "cil_build_ast.h" #include "cil_resolve_ast.h" #include "cil_fqn.h" #include "cil_post.h" #include "cil_binary.h" #include "cil_policy.h" #include "cil_strpool.h" #include "cil_write_ast.h" const 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}, {8, 8, 8, 32, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} }; 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_NOTSELF; char *CIL_KEY_OTHER; char *CIL_KEY_OBJECT_R; char *CIL_KEY_STAR; char *CIL_KEY_TCP; char *CIL_KEY_UDP; char *CIL_KEY_DCCP; char *CIL_KEY_SCTP; char *CIL_KEY_AUDITALLOW; char *CIL_KEY_TUNABLEIF; char *CIL_KEY_ALLOW; char *CIL_KEY_DONTAUDIT; char *CIL_KEY_TYPETRANSITION; char *CIL_KEY_TYPECHANGE; char *CIL_KEY_CALL; char *CIL_KEY_TUNABLE; char *CIL_KEY_XOR; char *CIL_KEY_ALL; char *CIL_KEY_RANGE; char *CIL_KEY_GLOB; char *CIL_KEY_FILE; char *CIL_KEY_DIR; char *CIL_KEY_CHAR; char *CIL_KEY_BLOCK; char *CIL_KEY_SOCKET; char *CIL_KEY_PIPE; char *CIL_KEY_SYMLINK; char *CIL_KEY_ANY; char *CIL_KEY_XATTR; char *CIL_KEY_TASK; char *CIL_KEY_TRANS; char *CIL_KEY_TYPE; char *CIL_KEY_ROLE; char *CIL_KEY_USER; char *CIL_KEY_USERATTRIBUTE; char *CIL_KEY_USERATTRIBUTESET; char *CIL_KEY_SENSITIVITY; char *CIL_KEY_CATEGORY; char *CIL_KEY_CATSET; char *CIL_KEY_LEVEL; char *CIL_KEY_LEVELRANGE; char *CIL_KEY_CLASS; char *CIL_KEY_IPADDR; char *CIL_KEY_MAP_CLASS; char *CIL_KEY_CLASSPERMISSION; char *CIL_KEY_BOOL; char *CIL_KEY_STRING; char *CIL_KEY_NAME; char *CIL_KEY_SOURCE; char *CIL_KEY_TARGET; char *CIL_KEY_LOW; char *CIL_KEY_HIGH; char *CIL_KEY_LOW_HIGH; char *CIL_KEY_GLBLUB; 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_IN_BEFORE; char *CIL_KEY_IN_AFTER; char *CIL_KEY_MLS; char *CIL_KEY_DEFAULTRANGE; char *CIL_KEY_BLOCKINHERIT; char *CIL_KEY_BLOCKABSTRACT; char *CIL_KEY_CLASSORDER; char *CIL_KEY_CLASSMAPPING; char *CIL_KEY_CLASSPERMISSIONSET; char *CIL_KEY_COMMON; char *CIL_KEY_CLASSCOMMON; char *CIL_KEY_SID; char *CIL_KEY_SIDCONTEXT; char *CIL_KEY_SIDORDER; char *CIL_KEY_USERLEVEL; char *CIL_KEY_USERRANGE; char *CIL_KEY_USERBOUNDS; char *CIL_KEY_USERPREFIX; char *CIL_KEY_SELINUXUSER; char *CIL_KEY_SELINUXUSERDEFAULT; char *CIL_KEY_TYPEATTRIBUTE; char *CIL_KEY_TYPEATTRIBUTESET; char *CIL_KEY_EXPANDTYPEATTRIBUTE; char *CIL_KEY_TYPEALIAS; char *CIL_KEY_TYPEALIASACTUAL; char *CIL_KEY_TYPEBOUNDS; char *CIL_KEY_TYPEPERMISSIVE; char *CIL_KEY_RANGETRANSITION; char *CIL_KEY_USERROLE; char *CIL_KEY_ROLETYPE; char *CIL_KEY_ROLETRANSITION; char *CIL_KEY_ROLEALLOW; char *CIL_KEY_ROLEATTRIBUTE; char *CIL_KEY_ROLEATTRIBUTESET; char *CIL_KEY_ROLEBOUNDS; char *CIL_KEY_BOOLEANIF; char *CIL_KEY_NEVERALLOW; char *CIL_KEY_TYPEMEMBER; char *CIL_KEY_SENSALIAS; char *CIL_KEY_SENSALIASACTUAL; char *CIL_KEY_CATALIAS; char *CIL_KEY_CATALIASACTUAL; char *CIL_KEY_CATORDER; char *CIL_KEY_SENSITIVITYORDER; char *CIL_KEY_SENSCAT; char *CIL_KEY_CONSTRAIN; char *CIL_KEY_MLSCONSTRAIN; char *CIL_KEY_VALIDATETRANS; char *CIL_KEY_MLSVALIDATETRANS; char *CIL_KEY_CONTEXT; char *CIL_KEY_FILECON; char *CIL_KEY_IBPKEYCON; char *CIL_KEY_IBENDPORTCON; char *CIL_KEY_PORTCON; char *CIL_KEY_NODECON; char *CIL_KEY_GENFSCON; char *CIL_KEY_NETIFCON; char *CIL_KEY_PIRQCON; char *CIL_KEY_IOMEMCON; char *CIL_KEY_IOPORTCON; char *CIL_KEY_PCIDEVICECON; char *CIL_KEY_DEVICETREECON; char *CIL_KEY_FSUSE; char *CIL_KEY_POLICYCAP; char *CIL_KEY_OPTIONAL; char *CIL_KEY_DEFAULTUSER; char *CIL_KEY_DEFAULTROLE; char *CIL_KEY_DEFAULTTYPE; char *CIL_KEY_ROOT; char *CIL_KEY_NODE; char *CIL_KEY_PERM; char *CIL_KEY_ALLOWX; char *CIL_KEY_AUDITALLOWX; char *CIL_KEY_DONTAUDITX; char *CIL_KEY_NEVERALLOWX; char *CIL_KEY_PERMISSIONX; char *CIL_KEY_IOCTL; char *CIL_KEY_NLMSG; char *CIL_KEY_UNORDERED; char *CIL_KEY_SRC_INFO; char *CIL_KEY_SRC_CIL; char *CIL_KEY_SRC_HLL_LMS; char *CIL_KEY_SRC_HLL_LMX; char *CIL_KEY_SRC_HLL_LME; char *CIL_KEY_DENY_RULE; 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_NOTSELF = cil_strpool_add("notself"); CIL_KEY_OTHER = cil_strpool_add("other"); CIL_KEY_OBJECT_R = cil_strpool_add("object_r"); CIL_KEY_STAR = cil_strpool_add("*"); CIL_KEY_UDP = cil_strpool_add("udp"); CIL_KEY_TCP = cil_strpool_add("tcp"); CIL_KEY_DCCP = cil_strpool_add("dccp"); CIL_KEY_SCTP = cil_strpool_add("sctp"); CIL_KEY_AUDITALLOW = cil_strpool_add("auditallow"); CIL_KEY_TUNABLEIF = cil_strpool_add("tunableif"); CIL_KEY_ALLOW = cil_strpool_add("allow"); CIL_KEY_DONTAUDIT = cil_strpool_add("dontaudit"); CIL_KEY_TYPETRANSITION = cil_strpool_add("typetransition"); CIL_KEY_TYPECHANGE = cil_strpool_add("typechange"); CIL_KEY_CALL = cil_strpool_add("call"); CIL_KEY_TUNABLE = cil_strpool_add("tunable"); CIL_KEY_XOR = cil_strpool_add("xor"); CIL_KEY_ALL = cil_strpool_add("all"); CIL_KEY_RANGE = cil_strpool_add("range"); CIL_KEY_TYPE = cil_strpool_add("type"); CIL_KEY_ROLE = cil_strpool_add("role"); CIL_KEY_USER = cil_strpool_add("user"); CIL_KEY_USERATTRIBUTE = cil_strpool_add("userattribute"); CIL_KEY_USERATTRIBUTESET = cil_strpool_add("userattributeset"); CIL_KEY_SENSITIVITY = cil_strpool_add("sensitivity"); CIL_KEY_CATEGORY = cil_strpool_add("category"); CIL_KEY_CATSET = cil_strpool_add("categoryset"); CIL_KEY_LEVEL = cil_strpool_add("level"); CIL_KEY_LEVELRANGE = cil_strpool_add("levelrange"); CIL_KEY_CLASS = cil_strpool_add("class"); CIL_KEY_IPADDR = cil_strpool_add("ipaddr"); CIL_KEY_MAP_CLASS = cil_strpool_add("classmap"); CIL_KEY_CLASSPERMISSION = cil_strpool_add("classpermission"); CIL_KEY_BOOL = cil_strpool_add("boolean"); CIL_KEY_STRING = cil_strpool_add("string"); CIL_KEY_NAME = cil_strpool_add("name"); CIL_KEY_HANDLEUNKNOWN = cil_strpool_add("handleunknown"); CIL_KEY_HANDLEUNKNOWN_ALLOW = cil_strpool_add("allow"); CIL_KEY_HANDLEUNKNOWN_DENY = cil_strpool_add("deny"); CIL_KEY_HANDLEUNKNOWN_REJECT = cil_strpool_add("reject"); CIL_KEY_BLOCKINHERIT = cil_strpool_add("blockinherit"); CIL_KEY_BLOCKABSTRACT = cil_strpool_add("blockabstract"); CIL_KEY_CLASSORDER = cil_strpool_add("classorder"); CIL_KEY_CLASSMAPPING = cil_strpool_add("classmapping"); CIL_KEY_CLASSPERMISSIONSET = cil_strpool_add("classpermissionset"); CIL_KEY_COMMON = cil_strpool_add("common"); CIL_KEY_CLASSCOMMON = cil_strpool_add("classcommon"); CIL_KEY_SID = cil_strpool_add("sid"); CIL_KEY_SIDCONTEXT = cil_strpool_add("sidcontext"); CIL_KEY_SIDORDER = cil_strpool_add("sidorder"); CIL_KEY_USERLEVEL = cil_strpool_add("userlevel"); CIL_KEY_USERRANGE = cil_strpool_add("userrange"); CIL_KEY_USERBOUNDS = cil_strpool_add("userbounds"); CIL_KEY_USERPREFIX = cil_strpool_add("userprefix"); CIL_KEY_SELINUXUSER = cil_strpool_add("selinuxuser"); CIL_KEY_SELINUXUSERDEFAULT = cil_strpool_add("selinuxuserdefault"); CIL_KEY_TYPEATTRIBUTE = cil_strpool_add("typeattribute"); CIL_KEY_TYPEATTRIBUTESET = cil_strpool_add("typeattributeset"); CIL_KEY_EXPANDTYPEATTRIBUTE = cil_strpool_add("expandtypeattribute"); CIL_KEY_TYPEALIAS = cil_strpool_add("typealias"); CIL_KEY_TYPEALIASACTUAL = cil_strpool_add("typealiasactual"); CIL_KEY_TYPEBOUNDS = cil_strpool_add("typebounds"); CIL_KEY_TYPEPERMISSIVE = cil_strpool_add("typepermissive"); CIL_KEY_RANGETRANSITION = cil_strpool_add("rangetransition"); CIL_KEY_USERROLE = cil_strpool_add("userrole"); CIL_KEY_ROLETYPE = cil_strpool_add("roletype"); CIL_KEY_ROLETRANSITION = cil_strpool_add("roletransition"); CIL_KEY_ROLEALLOW = cil_strpool_add("roleallow"); CIL_KEY_ROLEATTRIBUTE = cil_strpool_add("roleattribute"); CIL_KEY_ROLEATTRIBUTESET = cil_strpool_add("roleattributeset"); CIL_KEY_ROLEBOUNDS = cil_strpool_add("rolebounds"); CIL_KEY_BOOLEANIF = cil_strpool_add("booleanif"); CIL_KEY_NEVERALLOW = cil_strpool_add("neverallow"); CIL_KEY_TYPEMEMBER = cil_strpool_add("typemember"); CIL_KEY_SENSALIAS = cil_strpool_add("sensitivityalias"); CIL_KEY_SENSALIASACTUAL = cil_strpool_add("sensitivityaliasactual"); CIL_KEY_CATALIAS = cil_strpool_add("categoryalias"); CIL_KEY_CATALIASACTUAL = cil_strpool_add("categoryaliasactual"); CIL_KEY_CATORDER = cil_strpool_add("categoryorder"); CIL_KEY_SENSITIVITYORDER = cil_strpool_add("sensitivityorder"); CIL_KEY_SENSCAT = cil_strpool_add("sensitivitycategory"); CIL_KEY_CONSTRAIN = cil_strpool_add("constrain"); CIL_KEY_MLSCONSTRAIN = cil_strpool_add("mlsconstrain"); CIL_KEY_VALIDATETRANS = cil_strpool_add("validatetrans"); CIL_KEY_MLSVALIDATETRANS = cil_strpool_add("mlsvalidatetrans"); CIL_KEY_CONTEXT = cil_strpool_add("context"); CIL_KEY_FILECON = cil_strpool_add("filecon"); CIL_KEY_IBPKEYCON = cil_strpool_add("ibpkeycon"); CIL_KEY_IBENDPORTCON = cil_strpool_add("ibendportcon"); CIL_KEY_PORTCON = cil_strpool_add("portcon"); CIL_KEY_NODECON = cil_strpool_add("nodecon"); CIL_KEY_GENFSCON = cil_strpool_add("genfscon"); CIL_KEY_NETIFCON = cil_strpool_add("netifcon"); CIL_KEY_PIRQCON = cil_strpool_add("pirqcon"); CIL_KEY_IOMEMCON = cil_strpool_add("iomemcon"); CIL_KEY_IOPORTCON = cil_strpool_add("ioportcon"); CIL_KEY_PCIDEVICECON = cil_strpool_add("pcidevicecon"); CIL_KEY_DEVICETREECON = cil_strpool_add("devicetreecon"); CIL_KEY_FSUSE = cil_strpool_add("fsuse"); CIL_KEY_POLICYCAP = cil_strpool_add("policycap"); CIL_KEY_OPTIONAL = cil_strpool_add("optional"); CIL_KEY_DEFAULTUSER = cil_strpool_add("defaultuser"); CIL_KEY_DEFAULTROLE = cil_strpool_add("defaultrole"); CIL_KEY_DEFAULTTYPE = cil_strpool_add("defaulttype"); CIL_KEY_MACRO = cil_strpool_add("macro"); CIL_KEY_IN = cil_strpool_add("in"); CIL_KEY_IN_BEFORE = cil_strpool_add("before"); CIL_KEY_IN_AFTER = cil_strpool_add("after"); 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_GLBLUB = cil_strpool_add("glblub"); CIL_KEY_ROOT = cil_strpool_add(""); CIL_KEY_NODE = cil_strpool_add(""); CIL_KEY_PERM = cil_strpool_add("perm"); CIL_KEY_ALLOWX = cil_strpool_add("allowx"); CIL_KEY_AUDITALLOWX = cil_strpool_add("auditallowx"); CIL_KEY_DONTAUDITX = cil_strpool_add("dontauditx"); CIL_KEY_NEVERALLOWX = cil_strpool_add("neverallowx"); CIL_KEY_PERMISSIONX = cil_strpool_add("permissionx"); CIL_KEY_IOCTL = cil_strpool_add("ioctl"); CIL_KEY_NLMSG = cil_strpool_add("nlmsg"); CIL_KEY_UNORDERED = cil_strpool_add("unordered"); CIL_KEY_SRC_INFO = cil_strpool_add(""); CIL_KEY_SRC_CIL = cil_strpool_add("cil"); CIL_KEY_SRC_HLL_LMS = cil_strpool_add("lms"); CIL_KEY_SRC_HLL_LMX = cil_strpool_add("lmx"); CIL_KEY_SRC_HLL_LME = cil_strpool_add("lme"); CIL_KEY_DENY_RULE = cil_strpool_add("deny"); } void cil_db_init(struct cil_db **db) { *db = cil_malloc(sizeof(**db)); cil_strpool_init(); cil_init_keys(); cil_tree_init(&(*db)->parse); cil_tree_init(&(*db)->ast); cil_root_init((struct cil_root **)&(*db)->ast->root->data); (*db)->sidorder = NULL; (*db)->classorder = NULL; (*db)->catorder = NULL; (*db)->sensitivityorder = NULL; cil_sort_init(&(*db)->netifcon); cil_sort_init(&(*db)->genfscon); cil_sort_init(&(*db)->filecon); cil_sort_init(&(*db)->nodecon); cil_sort_init(&(*db)->ibpkeycon); cil_sort_init(&(*db)->ibendportcon); cil_sort_init(&(*db)->portcon); cil_sort_init(&(*db)->pirqcon); cil_sort_init(&(*db)->iomemcon); cil_sort_init(&(*db)->ioportcon); cil_sort_init(&(*db)->pcidevicecon); cil_sort_init(&(*db)->devicetreecon); cil_sort_init(&(*db)->fsuse); cil_list_init(&(*db)->userprefixes, CIL_LIST_ITEM); cil_list_init(&(*db)->selinuxusers, CIL_LIST_ITEM); cil_list_init(&(*db)->declared_strings, CIL_LIST_ITEM); cil_type_init(&(*db)->selftype); (*db)->selftype->datum.name = CIL_KEY_SELF; (*db)->selftype->datum.fqn = CIL_KEY_SELF; cil_type_init(&(*db)->notselftype); (*db)->notselftype->datum.name = CIL_KEY_NOTSELF; (*db)->notselftype->datum.fqn = CIL_KEY_NOTSELF; cil_type_init(&(*db)->othertype); (*db)->othertype->datum.name = CIL_KEY_OTHER; (*db)->othertype->datum.fqn = CIL_KEY_OTHER; (*db)->num_types_and_attrs = 0; (*db)->num_classes = 0; (*db)->num_types = 0; (*db)->num_roles = 0; (*db)->num_users = 0; (*db)->num_cats = 0; (*db)->val_to_type = NULL; (*db)->val_to_role = NULL; (*db)->val_to_user = NULL; (*db)->disable_dontaudit = CIL_FALSE; (*db)->disable_neverallow = CIL_FALSE; (*db)->attrs_expand_generated = CIL_FALSE; (*db)->attrs_expand_size = 1; (*db)->preserve_tunables = CIL_FALSE; (*db)->handle_unknown = -1; (*db)->mls = -1; (*db)->multiple_decls = CIL_FALSE; (*db)->qualified_names = CIL_FALSE; (*db)->target_platform = SEPOL_TARGET_SELINUX; (*db)->policy_version = POLICYDB_VERSION_MAX; } static void cil_declared_strings_list_destroy(struct cil_list **strings) { struct cil_list_item *i; cil_list_for_each(i, *strings) { struct cil_symtab_datum *d = i->data; cil_symtab_datum_destroy(d); free(d); } cil_list_destroy(strings, CIL_FALSE); } void cil_db_destroy(struct cil_db **db) { if (db == NULL || *db == NULL) { return; } cil_tree_destroy(&(*db)->parse); cil_tree_destroy(&(*db)->ast); cil_list_destroy(&(*db)->sidorder, CIL_FALSE); cil_list_destroy(&(*db)->classorder, CIL_FALSE); cil_list_destroy(&(*db)->catorder, CIL_FALSE); cil_list_destroy(&(*db)->sensitivityorder, CIL_FALSE); cil_sort_destroy(&(*db)->netifcon); cil_sort_destroy(&(*db)->genfscon); cil_sort_destroy(&(*db)->filecon); cil_sort_destroy(&(*db)->nodecon); cil_sort_destroy(&(*db)->ibpkeycon); cil_sort_destroy(&(*db)->ibendportcon); cil_sort_destroy(&(*db)->portcon); cil_sort_destroy(&(*db)->pirqcon); cil_sort_destroy(&(*db)->iomemcon); cil_sort_destroy(&(*db)->ioportcon); cil_sort_destroy(&(*db)->pcidevicecon); cil_sort_destroy(&(*db)->devicetreecon); cil_sort_destroy(&(*db)->fsuse); cil_list_destroy(&(*db)->userprefixes, CIL_FALSE); cil_list_destroy(&(*db)->selinuxusers, CIL_FALSE); cil_declared_strings_list_destroy(&(*db)->declared_strings); cil_destroy_type((*db)->selftype); cil_destroy_type((*db)->notselftype); cil_destroy_type((*db)->othertype); cil_strpool_destroy(); free((*db)->val_to_type); free((*db)->val_to_role); free((*db)->val_to_user); free(*db); *db = NULL; } void cil_root_init(struct cil_root **root) { struct cil_root *r = cil_malloc(sizeof(*r)); cil_symtab_array_init(r->symtab, cil_sym_sizes[CIL_SYM_ARRAY_ROOT]); *root = r; } void cil_root_destroy(struct cil_root *root) { if (root == NULL) { return; } cil_symtab_array_destroy(root->symtab); free(root); } int cil_add_file(cil_db_t *db, const char *name, const char *data, size_t size) { char *buffer = NULL; int rc; cil_log(CIL_INFO, "Parsing %s\n", name); buffer = cil_malloc(size + 2); memcpy(buffer, data, size); memset(buffer + size, 0, 2); rc = cil_parser(name, buffer, size + 2, &db->parse); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "Failed to parse %s\n", name); goto exit; } free(buffer); buffer = NULL; rc = SEPOL_OK; exit: free(buffer); return rc; } int cil_compile(struct cil_db *db) { int rc = SEPOL_ERR; if (db == NULL) { goto exit; } cil_log(CIL_INFO, "Building AST from Parse Tree\n"); rc = cil_build_ast(db, db->parse->root, db->ast->root); if (rc != SEPOL_OK) { cil_log(CIL_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_write_parse_ast(FILE *out, cil_db_t *db) { int rc = SEPOL_ERR; if (db == NULL) { goto exit; } cil_log(CIL_INFO, "Writing Parse AST\n"); rc = cil_write_ast(out, CIL_WRITE_AST_PHASE_PARSE, db->parse->root); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Failed to write parse ast\n"); goto exit; } exit: return rc; } int cil_write_build_ast(FILE *out, cil_db_t *db) { int rc = SEPOL_ERR; if (db == NULL) { goto exit; } cil_log(CIL_INFO, "Building AST from Parse Tree\n"); rc = cil_build_ast(db, db->parse->root, db->ast->root); if (rc != SEPOL_OK) { cil_log(CIL_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, "Writing Build AST\n"); rc = cil_write_ast(out, CIL_WRITE_AST_PHASE_BUILD, db->ast->root); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Failed to write build ast\n"); goto exit; } exit: return rc; } int cil_write_resolve_ast(FILE *out, cil_db_t *db) { int rc = SEPOL_ERR; if (db == NULL) { goto exit; } cil_log(CIL_INFO, "Building AST from Parse Tree\n"); rc = cil_build_ast(db, db->parse->root, db->ast->root); if (rc != SEPOL_OK) { cil_log(CIL_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, "Writing Resolve AST\n"); rc = cil_write_ast(out, CIL_WRITE_AST_PHASE_RESOLVE, db->ast->root); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Failed to write resolve ast\n"); goto exit; } exit: return rc; } int cil_write_post_ast(FILE *out, cil_db_t *db) { int rc = SEPOL_ERR; if (db == NULL) { goto exit; } cil_log(CIL_INFO, "Building AST from Parse Tree\n"); rc = cil_build_ast(db, db->parse->root, db->ast->root); if (rc != SEPOL_OK) { cil_log(CIL_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; } cil_log(CIL_INFO, "Writing Post AST\n"); rc = cil_write_ast(out, CIL_WRITE_AST_PHASE_POST, db->ast->root); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Failed to write post ast\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_write_policy_conf(FILE *out, struct cil_db *db) { cil_log(CIL_INFO, "Writing policy.conf file\n"); cil_gen_policy(out, db); } void cil_destroy_data(void **data, enum cil_flavor flavor) { if (*data == NULL) { return; } switch(flavor) { case CIL_NONE: break; case CIL_ROOT: cil_root_destroy(*data); break; case CIL_NODE: break; case CIL_STRING: break; case CIL_DATUM: break; case CIL_LIST: cil_list_destroy(*data, CIL_FALSE); break; case CIL_LIST_ITEM: break; case CIL_PARAM: cil_destroy_param(*data); break; case CIL_ARGS: cil_destroy_args(*data); break; case CIL_BLOCK: cil_destroy_block(*data); break; case CIL_BLOCKINHERIT: cil_destroy_blockinherit(*data); break; case CIL_BLOCKABSTRACT: cil_destroy_blockabstract(*data); break; case CIL_IN: cil_destroy_in(*data); break; case CIL_MACRO: cil_destroy_macro(*data); break; case CIL_CALL: cil_destroy_call(*data); break; case CIL_OPTIONAL: cil_destroy_optional(*data); break; case CIL_BOOL: cil_destroy_bool(*data); break; case CIL_BOOLEANIF: cil_destroy_boolif(*data); break; case CIL_TUNABLE: cil_destroy_tunable(*data); break; case CIL_TUNABLEIF: cil_destroy_tunif(*data); break; case CIL_CONDBLOCK: cil_destroy_condblock(*data); break; case CIL_CONDTRUE: break; case CIL_CONDFALSE: break; case CIL_PERM: case CIL_MAP_PERM: cil_destroy_perm(*data); break; case CIL_COMMON: case CIL_CLASS: case CIL_MAP_CLASS: cil_destroy_class(*data); break; case CIL_CLASSORDER: cil_destroy_ordered(*data); break; case CIL_CLASSPERMISSION: cil_destroy_classpermission(*data); break; case CIL_CLASSCOMMON: cil_destroy_classcommon(*data); break; case CIL_CLASSMAPPING: cil_destroy_classmapping(*data); break; case CIL_CLASSPERMS: cil_destroy_classperms(*data); break; case CIL_CLASSPERMS_SET: cil_destroy_classperms_set(*data); break; case CIL_CLASSPERMISSIONSET: cil_destroy_classpermissionset(*data); break; case CIL_USER: cil_destroy_user(*data); break; case CIL_USERATTRIBUTE: cil_destroy_userattribute(*data); break; case CIL_USERATTRIBUTESET: cil_destroy_userattributeset(*data); break; case CIL_USERPREFIX: cil_destroy_userprefix(*data); break; case CIL_USERROLE: cil_destroy_userrole(*data); break; case CIL_USERLEVEL: cil_destroy_userlevel(*data); break; case CIL_USERRANGE: cil_destroy_userrange(*data); break; case CIL_USERBOUNDS: cil_destroy_bounds(*data); break; case CIL_SELINUXUSER: case CIL_SELINUXUSERDEFAULT: cil_destroy_selinuxuser(*data); break; case CIL_ROLE: cil_destroy_role(*data); break; case CIL_ROLEATTRIBUTE: cil_destroy_roleattribute(*data); break; case CIL_ROLEATTRIBUTESET: cil_destroy_roleattributeset(*data); break; case CIL_ROLETYPE: cil_destroy_roletype(*data); break; case CIL_ROLEBOUNDS: cil_destroy_bounds(*data); break; case CIL_TYPE: cil_destroy_type(*data); break; case CIL_TYPEATTRIBUTE: cil_destroy_typeattribute(*data); break; case CIL_TYPEALIAS: cil_destroy_alias(*data); break; case CIL_TYPEATTRIBUTESET: cil_destroy_typeattributeset(*data); break; case CIL_EXPANDTYPEATTRIBUTE: cil_destroy_expandtypeattribute(*data); break; case CIL_TYPEALIASACTUAL: cil_destroy_aliasactual(*data); break; case CIL_TYPEBOUNDS: cil_destroy_bounds(*data); break; case CIL_TYPEPERMISSIVE: cil_destroy_typepermissive(*data); break; case CIL_SENS: cil_destroy_sensitivity(*data); break; case CIL_SENSALIAS: cil_destroy_alias(*data); break; case CIL_SENSALIASACTUAL: cil_destroy_aliasactual(*data); break; case CIL_SENSITIVITYORDER: cil_destroy_ordered(*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_ordered(*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_ordered(*data); break; case CIL_ROLEALLOW: cil_destroy_roleallow(*data); break; case CIL_AVRULE: case CIL_AVRULEX: cil_destroy_avrule(*data); break; case CIL_PERMISSIONX: cil_destroy_permissionx(*data); break; case CIL_DENY_RULE: cil_destroy_deny_rule(*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_DECLARED_STRING: break; case CIL_SIDCONTEXT: cil_destroy_sidcontext(*data); break; case CIL_FSUSE: cil_destroy_fsuse(*data); break; case CIL_FILECON: cil_destroy_filecon(*data); break; case CIL_IBPKEYCON: cil_destroy_ibpkeycon(*data); break; case CIL_PORTCON: cil_destroy_portcon(*data); break; case CIL_IBENDPORTCON: cil_destroy_ibendportcon(*data); break; case CIL_NODECON: cil_destroy_nodecon(*data); break; case CIL_GENFSCON: cil_destroy_genfscon(*data); break; case CIL_NETIFCON: cil_destroy_netifcon(*data); break; case CIL_PIRQCON: cil_destroy_pirqcon(*data); break; case CIL_IOMEMCON: cil_destroy_iomemcon(*data); break; case CIL_IOPORTCON: cil_destroy_ioportcon(*data); break; case CIL_PCIDEVICECON: cil_destroy_pcidevicecon(*data); break; case CIL_DEVICETREECON: cil_destroy_devicetreecon(*data); break; case CIL_POLICYCAP: cil_destroy_policycap(*data); break; case CIL_DEFAULTUSER: case CIL_DEFAULTROLE: case CIL_DEFAULTTYPE: cil_destroy_default(*data); break; case CIL_DEFAULTRANGE: cil_destroy_defaultrange(*data); break; case CIL_HANDLEUNKNOWN: cil_destroy_handleunknown(*data); break; case CIL_MLS: cil_destroy_mls(*data); break; case CIL_SRC_INFO: cil_destroy_src_info(*data); break; case CIL_OP: case CIL_CONS_OPERAND: break; default: cil_log(CIL_INFO, "Unknown data flavor: %d\n", flavor); break; } *data = NULL; } int cil_flavor_to_symtab_index(enum cil_flavor flavor, enum cil_sym_index *sym_index) { if (flavor < CIL_MIN_DECLARATIVE) { return SEPOL_ERR; } switch(flavor) { case CIL_BLOCK: *sym_index = CIL_SYM_BLOCKS; break; case CIL_MACRO: *sym_index = CIL_SYM_BLOCKS; break; case CIL_OPTIONAL: *sym_index = CIL_SYM_BLOCKS; break; case CIL_BOOL: *sym_index = CIL_SYM_BOOLS; break; case CIL_TUNABLE: *sym_index = CIL_SYM_TUNABLES; break; case CIL_PERM: case CIL_MAP_PERM: *sym_index = CIL_SYM_PERMS; break; case CIL_COMMON: *sym_index = CIL_SYM_COMMONS; break; case CIL_CLASS: case CIL_MAP_CLASS: *sym_index = CIL_SYM_CLASSES; break; case CIL_CLASSPERMISSION: case CIL_CLASSPERMISSIONSET: *sym_index = CIL_SYM_CLASSPERMSETS; break; case CIL_USER: case CIL_USERATTRIBUTE: *sym_index = CIL_SYM_USERS; break; case CIL_ROLE: case CIL_ROLEATTRIBUTE: *sym_index = CIL_SYM_ROLES; break; case CIL_TYPE: case CIL_TYPEALIAS: case CIL_TYPEATTRIBUTE: *sym_index = CIL_SYM_TYPES; break; case CIL_SENS: case CIL_SENSALIAS: *sym_index = CIL_SYM_SENS; break; case CIL_CAT: case CIL_CATSET: case CIL_CATALIAS: *sym_index = CIL_SYM_CATS; break; case CIL_LEVEL: *sym_index = CIL_SYM_LEVELS; break; case CIL_LEVELRANGE: *sym_index = CIL_SYM_LEVELRANGES; break; case CIL_SID: *sym_index = CIL_SYM_SIDS; break; case CIL_DECLARED_STRING: *sym_index = CIL_SYM_STRINGS; break; case CIL_CONTEXT: *sym_index = CIL_SYM_CONTEXTS; break; case CIL_IPADDR: *sym_index = CIL_SYM_IPADDRS; break; case CIL_POLICYCAP: *sym_index = CIL_SYM_POLICYCAPS; break; case CIL_PERMISSIONX: *sym_index = CIL_SYM_PERMX; break; default: *sym_index = CIL_SYM_UNKNOWN; cil_log(CIL_INFO, "Failed to find flavor: %d\n", flavor); return SEPOL_ERR; } return SEPOL_OK; } const char * cil_node_to_string(struct cil_tree_node *node) { switch (node->flavor) { case CIL_NONE: return ""; case CIL_ROOT: return CIL_KEY_ROOT; case CIL_NODE: return CIL_KEY_NODE; case CIL_STRING: return CIL_KEY_STRING; case CIL_DATUM: return ""; case CIL_LIST: return ""; case CIL_LIST_ITEM: return ""; case CIL_PARAM: return ""; case CIL_ARGS: return ""; case CIL_BLOCK: return CIL_KEY_BLOCK; case CIL_BLOCKINHERIT: return CIL_KEY_BLOCKINHERIT; case CIL_BLOCKABSTRACT: return CIL_KEY_BLOCKABSTRACT; case CIL_IN: return CIL_KEY_IN; case CIL_MACRO: return CIL_KEY_MACRO; case CIL_CALL: return CIL_KEY_CALL; case CIL_OPTIONAL: return CIL_KEY_OPTIONAL; case CIL_BOOL: return CIL_KEY_BOOL; case CIL_BOOLEANIF: return CIL_KEY_BOOLEANIF; case CIL_TUNABLE: return CIL_KEY_TUNABLE; case CIL_TUNABLEIF: return CIL_KEY_TUNABLEIF; case CIL_CONDBLOCK: switch (((struct cil_condblock*)node->data)->flavor) { case CIL_CONDTRUE: return CIL_KEY_CONDTRUE; case CIL_CONDFALSE: return CIL_KEY_CONDFALSE; default: break; } break; case CIL_CONDTRUE: return CIL_KEY_CONDTRUE; case CIL_CONDFALSE: return CIL_KEY_CONDFALSE; case CIL_PERM: return CIL_KEY_PERM; case CIL_COMMON: return CIL_KEY_COMMON; case CIL_CLASS: return CIL_KEY_CLASS; case CIL_CLASSORDER: return CIL_KEY_CLASSORDER; case CIL_MAP_CLASS: return CIL_KEY_MAP_CLASS; case CIL_CLASSPERMISSION: return CIL_KEY_CLASSPERMISSION; case CIL_CLASSCOMMON: return CIL_KEY_CLASSCOMMON; case CIL_CLASSMAPPING: return CIL_KEY_CLASSMAPPING; case CIL_CLASSPERMISSIONSET: return CIL_KEY_CLASSPERMISSIONSET; case CIL_USER: return CIL_KEY_USER; case CIL_USERATTRIBUTE: return CIL_KEY_USERATTRIBUTE; case CIL_USERATTRIBUTESET: return CIL_KEY_USERATTRIBUTESET; case CIL_USERPREFIX: return CIL_KEY_USERPREFIX; case CIL_USERROLE: return CIL_KEY_USERROLE; case CIL_USERLEVEL: return CIL_KEY_USERLEVEL; case CIL_USERRANGE: return CIL_KEY_USERRANGE; case CIL_USERBOUNDS: return CIL_KEY_USERBOUNDS; case CIL_SELINUXUSER: return CIL_KEY_SELINUXUSER; case CIL_SELINUXUSERDEFAULT: return CIL_KEY_SELINUXUSERDEFAULT; case CIL_ROLE: return CIL_KEY_ROLE; case CIL_ROLEATTRIBUTE: return CIL_KEY_ROLEATTRIBUTE; case CIL_ROLEATTRIBUTESET: return CIL_KEY_ROLEATTRIBUTESET; case CIL_ROLETYPE: return CIL_KEY_ROLETYPE; case CIL_ROLEBOUNDS: return CIL_KEY_ROLEBOUNDS; case CIL_TYPE: return CIL_KEY_TYPE; case CIL_TYPEATTRIBUTE: return CIL_KEY_TYPEATTRIBUTE; case CIL_TYPEALIAS: return CIL_KEY_TYPEALIAS; case CIL_TYPEATTRIBUTESET: return CIL_KEY_TYPEATTRIBUTESET; case CIL_EXPANDTYPEATTRIBUTE: return CIL_KEY_EXPANDTYPEATTRIBUTE; case CIL_TYPEALIASACTUAL: return CIL_KEY_TYPEALIASACTUAL; case CIL_TYPEBOUNDS: return CIL_KEY_TYPEBOUNDS; case CIL_TYPEPERMISSIVE: return CIL_KEY_TYPEPERMISSIVE; case CIL_SENS: return CIL_KEY_SENSITIVITY; case CIL_SENSALIAS: return CIL_KEY_SENSALIAS; case CIL_SENSALIASACTUAL: return CIL_KEY_SENSALIASACTUAL; case CIL_SENSITIVITYORDER: return CIL_KEY_SENSITIVITYORDER; case CIL_SENSCAT: return CIL_KEY_SENSCAT; case CIL_CAT: return CIL_KEY_CATEGORY; case CIL_CATSET: return CIL_KEY_CATSET; case CIL_CATALIAS: return CIL_KEY_CATALIAS; case CIL_CATALIASACTUAL: return CIL_KEY_CATALIASACTUAL; case CIL_CATORDER: return CIL_KEY_CATORDER; case CIL_LEVEL: return CIL_KEY_LEVEL; case CIL_LEVELRANGE: return CIL_KEY_LEVELRANGE; case CIL_SID: return CIL_KEY_SID; case CIL_SIDORDER: return CIL_KEY_SIDORDER; case CIL_ROLEALLOW: return CIL_KEY_ROLEALLOW; case CIL_AVRULE: switch (((struct cil_avrule *)node->data)->rule_kind) { case CIL_AVRULE_ALLOWED: return CIL_KEY_ALLOW; case CIL_AVRULE_AUDITALLOW: return CIL_KEY_AUDITALLOW; case CIL_AVRULE_DONTAUDIT: return CIL_KEY_DONTAUDIT; case CIL_AVRULE_NEVERALLOW: return CIL_KEY_NEVERALLOW; default: break; } break; case CIL_AVRULEX: switch (((struct cil_avrule *)node->data)->rule_kind) { case CIL_AVRULE_ALLOWED: return CIL_KEY_ALLOWX; case CIL_AVRULE_AUDITALLOW: return CIL_KEY_AUDITALLOWX; case CIL_AVRULE_DONTAUDIT: return CIL_KEY_DONTAUDITX; case CIL_AVRULE_NEVERALLOW: return CIL_KEY_NEVERALLOWX; default: break; } break; case CIL_PERMISSIONX: return CIL_KEY_PERMISSIONX; case CIL_DENY_RULE: return CIL_KEY_DENY_RULE; case CIL_ROLETRANSITION: return CIL_KEY_ROLETRANSITION; case CIL_TYPE_RULE: switch (((struct cil_type_rule *)node->data)->rule_kind) { case CIL_TYPE_TRANSITION: return CIL_KEY_TYPETRANSITION; case CIL_TYPE_MEMBER: return CIL_KEY_TYPEMEMBER; case CIL_TYPE_CHANGE: return CIL_KEY_TYPECHANGE; default: break; } break; case CIL_NAMETYPETRANSITION: return CIL_KEY_TYPETRANSITION; case CIL_RANGETRANSITION: return CIL_KEY_RANGETRANSITION; case CIL_CONSTRAIN: return CIL_KEY_CONSTRAIN; case CIL_MLSCONSTRAIN: return CIL_KEY_MLSCONSTRAIN; case CIL_VALIDATETRANS: return CIL_KEY_VALIDATETRANS; case CIL_MLSVALIDATETRANS: return CIL_KEY_MLSVALIDATETRANS; case CIL_CONTEXT: return CIL_KEY_CONTEXT; case CIL_IPADDR: return CIL_KEY_IPADDR; case CIL_SIDCONTEXT: return CIL_KEY_SIDCONTEXT; case CIL_FSUSE: return CIL_KEY_FSUSE; case CIL_FILECON: return CIL_KEY_FILECON; case CIL_IBPKEYCON: return CIL_KEY_IBPKEYCON; case CIL_IBENDPORTCON: return CIL_KEY_IBENDPORTCON; case CIL_PORTCON: return CIL_KEY_PORTCON; case CIL_NODECON: return CIL_KEY_NODECON; case CIL_GENFSCON: return CIL_KEY_GENFSCON; case CIL_NETIFCON: return CIL_KEY_NETIFCON; case CIL_PIRQCON: return CIL_KEY_PIRQCON; case CIL_IOMEMCON: return CIL_KEY_IOMEMCON; case CIL_IOPORTCON: return CIL_KEY_IOPORTCON; case CIL_PCIDEVICECON: return CIL_KEY_PCIDEVICECON; case CIL_DEVICETREECON: return CIL_KEY_DEVICETREECON; case CIL_POLICYCAP: return CIL_KEY_POLICYCAP; case CIL_DEFAULTUSER: return CIL_KEY_DEFAULTUSER; case CIL_DEFAULTROLE: return CIL_KEY_DEFAULTROLE; case CIL_DEFAULTTYPE: return CIL_KEY_DEFAULTTYPE; case CIL_DEFAULTRANGE: return CIL_KEY_DEFAULTRANGE; case CIL_HANDLEUNKNOWN: return CIL_KEY_HANDLEUNKNOWN; case CIL_MLS: return CIL_KEY_MLS; case CIL_SRC_INFO: return CIL_KEY_SRC_INFO; case CIL_ALL: return CIL_KEY_ALL; case CIL_RANGE: return CIL_KEY_RANGE; case CIL_AND: return CIL_KEY_AND; case CIL_OR: return CIL_KEY_OR; case CIL_XOR: return CIL_KEY_XOR; case CIL_NOT: return CIL_KEY_NOT; case CIL_EQ: return CIL_KEY_EQ; case CIL_NEQ: return CIL_KEY_NEQ; case CIL_CONS_DOM: return CIL_KEY_CONS_DOM; case CIL_CONS_DOMBY: return CIL_KEY_CONS_DOMBY; case CIL_CONS_INCOMP: return CIL_KEY_CONS_INCOMP; case CIL_CONS_U1: return CIL_KEY_CONS_U1; case CIL_CONS_U2: return CIL_KEY_CONS_U2; case CIL_CONS_U3: return CIL_KEY_CONS_U3; case CIL_CONS_T1: return CIL_KEY_CONS_T1; case CIL_CONS_T2: return CIL_KEY_CONS_T2; case CIL_CONS_T3: return CIL_KEY_CONS_T3; case CIL_CONS_R1: return CIL_KEY_CONS_R1; case CIL_CONS_R2: return CIL_KEY_CONS_R2; case CIL_CONS_R3: return CIL_KEY_CONS_R3; case CIL_CONS_L1: return CIL_KEY_CONS_L1; case CIL_CONS_L2: return CIL_KEY_CONS_L2; case CIL_CONS_H1: return CIL_KEY_CONS_H1; case CIL_CONS_H2: return CIL_KEY_CONS_H2; default: break; } return ""; } int cil_userprefixes_to_string(struct cil_db *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.fqn) + strlen(" prefix ") + strlen(userprefix->prefix_str) + 2; } *size = str_len * sizeof(char); str_len++; str_tmp = cil_malloc(str_len * sizeof(char)); *out = str_tmp; cil_list_for_each(curr, db->userprefixes) { userprefix = curr->data; user = userprefix->user; buf_pos = snprintf(str_tmp, str_len, "user %s prefix %s;\n", user->datum.fqn, userprefix->prefix_str); if (buf_pos < 0) { free(str_tmp); *size = 0; *out = NULL; goto exit; } str_len -= buf_pos; str_tmp += buf_pos; } rc = SEPOL_OK; exit: return rc; } static int cil_cats_to_ebitmap(struct cil_cats *cats, struct ebitmap* cats_ebitmap) { int rc = SEPOL_ERR; struct cil_list_item *i; struct cil_list_item *j; struct cil_cat* cat; struct cil_catset *cs; struct cil_tree_node *node; if (cats == NULL) { rc = SEPOL_OK; goto exit; } cil_list_for_each(i, cats->datum_expr) { node = NODE(i->data); if (node->flavor == CIL_CATSET) { cs = (struct cil_catset*)i->data; cil_list_for_each(j, cs->cats->datum_expr) { cat = (struct cil_cat*)j->data; rc = ebitmap_set_bit(cats_ebitmap, cat->value, 1); if (rc != SEPOL_OK) { goto exit; } } } else { cat = (struct cil_cat*)i->data; rc = ebitmap_set_bit(cats_ebitmap, cat->value, 1); if (rc != SEPOL_OK) { goto exit; } } } return SEPOL_OK; exit: return rc; } static int cil_level_equals(struct cil_level *low, struct cil_level *high) { int rc; struct ebitmap elow; struct ebitmap ehigh; if (strcmp(low->sens->datum.fqn, high->sens->datum.fqn)) { rc = 0; goto exit; } ebitmap_init(&elow); ebitmap_init(&ehigh); rc = cil_cats_to_ebitmap(low->cats, &elow); if (rc != SEPOL_OK) { goto exit; } rc = cil_cats_to_ebitmap(high->cats, &ehigh); if (rc != SEPOL_OK) { goto exit; } rc = ebitmap_cmp(&elow, &ehigh); ebitmap_destroy(&elow); ebitmap_destroy(&ehigh); exit: return rc; } static int __cil_level_strlen(struct cil_level *lvl) { struct cil_list_item *item; struct cil_cats *cats = lvl->cats; int str_len = 0; char *str1 = NULL; char *str2 = NULL; int first = -1; int last = -1; str_len += strlen(lvl->sens->datum.fqn); if (cats && cats->datum_expr != NULL) { str_len++; /* initial ":" */ cil_list_for_each(item, cats->datum_expr) { struct cil_cat *cat = item->data; if (first == -1) { str1 = cat->datum.fqn; first = cat->value; last = first; } else if (cat->value == last + 1) { last++; str2 = cat->datum.fqn; } else { if (first == last) { str_len += strlen(str1) + strlen(cat->datum.fqn) + 1; } else if (last == first + 1) { str_len += strlen(str1) + strlen(str2) + strlen(cat->datum.fqn) + 2; } else { str_len += strlen(str1) + strlen(str2) + strlen(cat->datum.fqn) + 2; } first = -1; last = -1; if (item->next != NULL) { str_len++; /* space for "," after */ } } } if (first != -1) { if (first == last) { str_len += strlen(str1); } else if (last == first + 1) { str_len += strlen(str1) + strlen(str2) + 1; } else { str_len += strlen(str1) + strlen(str2) + 1; } } } return str_len; } static int __cil_level_to_string(struct cil_level *lvl, char *out) { struct cil_list_item *item; struct cil_cats *cats = lvl->cats; int buf_pos = 0; char *str_tmp = out; char *str1 = NULL; char *str2 = NULL; int first = -1; int last = -1; buf_pos = sprintf(str_tmp, "%s", lvl->sens->datum.fqn); str_tmp += buf_pos; if (cats && cats->datum_expr != NULL) { buf_pos = sprintf(str_tmp, ":"); str_tmp += buf_pos; cil_list_for_each(item, cats->datum_expr) { struct cil_cat *cat = item->data; if (first == -1) { str1 = cat->datum.fqn; first = cat->value; last = first; } else if (cat->value == last + 1) { last++; str2 = cat->datum.fqn; } else { if (first == last) { buf_pos = sprintf(str_tmp, "%s,%s", str1, cat->datum.fqn); str_tmp += buf_pos; } else if (last == first + 1) { buf_pos = sprintf(str_tmp, "%s,%s,%s", str1, str2, cat->datum.fqn); str_tmp += buf_pos; } else { buf_pos = sprintf(str_tmp, "%s.%s,%s",str1, str2, cat->datum.fqn); str_tmp += buf_pos; } first = -1; last = -1; if (item->next != NULL) { buf_pos = sprintf(str_tmp, ","); str_tmp += buf_pos; } } } if (first != -1) { if (first == last) { buf_pos = sprintf(str_tmp, "%s", str1); str_tmp += buf_pos; } else if (last == first + 1) { buf_pos = sprintf(str_tmp, "%s,%s", str1, str2); str_tmp += buf_pos; } else { buf_pos = sprintf(str_tmp, "%s.%s",str1, str2); str_tmp += buf_pos; } } } return str_tmp - out; } int cil_selinuxusers_to_string(struct cil_db *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.fqn) + 1; if (db->mls == CIL_TRUE) { struct cil_levelrange *range = selinuxuser->range; str_len += __cil_level_strlen(range->low) + __cil_level_strlen(range->high) + 2; } str_len++; } *size = str_len * sizeof(char); str_tmp = cil_malloc(*size+1); *out = str_tmp; for(curr = db->selinuxusers->head; curr != NULL; curr = curr->next) { struct cil_selinuxuser *selinuxuser = curr->data; struct cil_user *user = selinuxuser->user; buf_pos = sprintf(str_tmp, "%s:%s", selinuxuser->name_str, user->datum.fqn); str_tmp += buf_pos; if (db->mls == CIL_TRUE) { struct cil_levelrange *range = selinuxuser->range; buf_pos = sprintf(str_tmp, ":"); str_tmp += buf_pos; buf_pos = __cil_level_to_string(range->low, str_tmp); str_tmp += buf_pos; buf_pos = sprintf(str_tmp, "-"); str_tmp += buf_pos; buf_pos = __cil_level_to_string(range->high, str_tmp); str_tmp += buf_pos; } buf_pos = sprintf(str_tmp, "\n"); str_tmp += buf_pos; } return SEPOL_OK; } int cil_filecons_to_string(struct cil_db *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; char *path_str = filecon->path ? DATUM(filecon->path)->fqn : filecon->path_str; str_len += strlen(path_str); if (filecon->type != CIL_FILECON_ANY) { /* If a type is specified, +2 for type string, +1 for tab */ str_len += 3; } if (ctx != NULL) { struct cil_user *user = ctx->user; struct cil_role *role = ctx->role; struct cil_type *type = ctx->type; str_len += (strlen(user->datum.fqn) + strlen(role->datum.fqn) + strlen(type->datum.fqn) + 3); if (db->mls == CIL_TRUE) { struct cil_levelrange *range = ctx->range; if (cil_level_equals(range->low, range->high)) { str_len += __cil_level_strlen(range->low) + 1; } else { str_len += __cil_level_strlen(range->low) + __cil_level_strlen(range->high) + 2; } } } else { str_len += strlen("\t<>"); } str_len++; } *size = str_len * sizeof(char); str_tmp = cil_malloc(*size+1); *out = str_tmp; for (i = 0; i < filecons->count; i++) { struct cil_filecon *filecon = filecons->array[i]; struct cil_context *ctx = filecon->context; const char *str_type = NULL; char *path_str = filecon->path ? DATUM(filecon->path)->fqn : filecon->path_str; buf_pos = sprintf(str_tmp, "%s", path_str); str_tmp += buf_pos; switch(filecon->type) { case CIL_FILECON_ANY: str_type = ""; break; case CIL_FILECON_FILE: str_type = "\t--"; break; case CIL_FILECON_DIR: str_type = "\t-d"; break; case CIL_FILECON_CHAR: str_type = "\t-c"; break; case CIL_FILECON_BLOCK: str_type = "\t-b"; break; case CIL_FILECON_SOCKET: str_type = "\t-s"; break; case CIL_FILECON_PIPE: str_type = "\t-p"; break; case CIL_FILECON_SYMLINK: str_type = "\t-l"; break; default: str_type = ""; break; } buf_pos = sprintf(str_tmp, "%s", str_type); str_tmp += buf_pos; if (ctx != NULL) { struct cil_user *user = ctx->user; struct cil_role *role = ctx->role; struct cil_type *type = ctx->type; buf_pos = sprintf(str_tmp, "\t%s:%s:%s", user->datum.fqn, role->datum.fqn, type->datum.fqn); str_tmp += buf_pos; if (db->mls == CIL_TRUE) { struct cil_levelrange *range = ctx->range; buf_pos = sprintf(str_tmp, ":"); str_tmp += buf_pos; buf_pos = __cil_level_to_string(range->low, str_tmp); str_tmp += buf_pos; if (!cil_level_equals(range->low, range->high)) { buf_pos = sprintf(str_tmp, "-"); str_tmp += buf_pos; buf_pos = __cil_level_to_string(range->high, str_tmp); str_tmp += buf_pos; } } } else { buf_pos = sprintf(str_tmp, "\t<>"); str_tmp += buf_pos; } buf_pos = sprintf(str_tmp, "\n"); str_tmp += buf_pos; } return SEPOL_OK; } void cil_set_disable_dontaudit(struct cil_db *db, int disable_dontaudit) { db->disable_dontaudit = disable_dontaudit; } void cil_set_disable_neverallow(struct cil_db *db, int disable_neverallow) { db->disable_neverallow = disable_neverallow; } void cil_set_attrs_expand_generated(struct cil_db *db, int attrs_expand_generated) { db->attrs_expand_generated = attrs_expand_generated; } void cil_set_attrs_expand_size(struct cil_db *db, unsigned attrs_expand_size) { db->attrs_expand_size = attrs_expand_size; } void cil_set_preserve_tunables(struct cil_db *db, int preserve_tunables) { db->preserve_tunables = preserve_tunables; } int cil_set_handle_unknown(struct cil_db *db, int handle_unknown) { int rc = 0; switch (handle_unknown) { case SEPOL_DENY_UNKNOWN: case SEPOL_REJECT_UNKNOWN: case SEPOL_ALLOW_UNKNOWN: db->handle_unknown = handle_unknown; break; default: cil_log(CIL_ERR, "Unknown value for handle-unknown: %i\n", handle_unknown); rc = -1; } return rc; } void cil_set_mls(struct cil_db *db, int mls) { db->mls = mls; } void cil_set_multiple_decls(struct cil_db *db, int multiple_decls) { db->multiple_decls = multiple_decls; } void cil_set_qualified_names(struct cil_db *db, int qualified_names) { db->qualified_names = qualified_names; } void cil_set_target_platform(struct cil_db *db, int target_platform) { db->target_platform = target_platform; } void cil_set_policy_version(struct cil_db *db, int policy_version) { db->policy_version = policy_version; } void cil_symtab_array_init(symtab_t symtab[], const int symtab_sizes[CIL_SYM_NUM]) { uint32_t i = 0; for (i = 0; i < CIL_SYM_NUM; i++) { cil_symtab_init(&symtab[i], symtab_sizes[i]); } } void cil_symtab_array_destroy(symtab_t symtab[]) { int i = 0; for (i = 0; i < CIL_SYM_NUM; i++) { cil_symtab_destroy(&symtab[i]); } } void cil_destroy_ast_symtabs(struct cil_tree_node *current) { while (current) { switch (current->flavor) { case CIL_BLOCK: cil_symtab_array_destroy(((struct cil_block*)current->data)->symtab); break; case CIL_IN: cil_symtab_array_destroy(((struct cil_in*)current->data)->symtab); break; case CIL_CLASS: case CIL_COMMON: case CIL_MAP_CLASS: cil_symtab_destroy(&((struct cil_class*)current->data)->perms); break; case CIL_MACRO: cil_symtab_array_destroy(((struct cil_macro*)current->data)->symtab); break; case CIL_CONDBLOCK: cil_symtab_array_destroy(((struct cil_condblock*)current->data)->symtab); break; default: break; } if (current->cl_head) { cil_destroy_ast_symtabs(current->cl_head); } current = current->next; } } int cil_get_symtab(struct cil_tree_node *ast_node, symtab_t **symtab, enum cil_sym_index sym_index) { struct cil_tree_node *node = ast_node; *symtab = NULL; if (sym_index == CIL_SYM_PERMS) { /* Class statements are not blocks, so the passed node should be the class */ if (node->flavor == CIL_CLASS || node->flavor == CIL_MAP_CLASS || node->flavor == CIL_COMMON) { *symtab = &((struct cil_class*)node->data)->perms; return SEPOL_OK; } goto exit; } if (sym_index < CIL_SYM_BLOCKS || sym_index >= CIL_SYM_NUM) { cil_log(CIL_ERR, "Invalid symtab type\n"); goto exit; } while (node != NULL && *symtab == NULL) { switch (node->flavor) { case CIL_ROOT: *symtab = &((struct cil_root *)node->data)->symtab[sym_index]; break; case CIL_BLOCK: *symtab = &((struct cil_block*)node->data)->symtab[sym_index]; break; case CIL_MACRO: *symtab = &((struct cil_macro*)node->data)->symtab[sym_index]; break; case CIL_IN: /* In blocks only exist before resolving the AST */ *symtab = &((struct cil_in*)node->data)->symtab[sym_index]; break; case CIL_CONDBLOCK: { if (node->parent->flavor == CIL_TUNABLEIF) { /* Cond blocks only exist before resolving the AST */ *symtab = &((struct cil_condblock*)node->data)->symtab[sym_index]; } else if (node->parent->flavor == CIL_BOOLEANIF) { node = node->parent->parent; } break; } default: node = node->parent; } } if (*symtab == NULL) { goto exit; } return SEPOL_OK; exit: cil_tree_log(ast_node, CIL_ERR, "Failed to get symtab from node"); return SEPOL_ERR; } int cil_string_to_uint32(const char *string, uint32_t *value, int base) { unsigned long val; char *end = NULL; int rc = SEPOL_ERR; if (string == NULL || value == NULL) { goto exit; } errno = 0; val = strtoul(string, &end, base); if (errno != 0 || end == string || *end != '\0') { rc = SEPOL_ERR; goto exit; } /* Ensure that the value fits a 32-bit integer without triggering -Wtype-limits */ #if ULONG_MAX > UINT32_MAX if (val > UINT32_MAX) { rc = SEPOL_ERR; goto exit; } #endif *value = val; return SEPOL_OK; exit: cil_log(CIL_ERR, "Failed to create uint32_t from string\n"); return rc; } int cil_string_to_uint64(const char *string, uint64_t *value, int base) { char *end = NULL; int rc = SEPOL_ERR; if (string == NULL || value == NULL) { goto exit; } errno = 0; *value = strtoull(string, &end, base); if (errno != 0 || end == string || *end != '\0') { rc = SEPOL_ERR; goto exit; } return SEPOL_OK; exit: cil_log(CIL_ERR, "Failed to create uint64_t from string\n"); return rc; } 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_ordered_init(struct cil_ordered **ordered) { *ordered = cil_malloc(sizeof(**ordered)); (*ordered)->merged = CIL_FALSE; (*ordered)->strs = NULL; (*ordered)->datums = NULL; } void cil_netifcon_init(struct cil_netifcon **netifcon) { *netifcon = cil_malloc(sizeof(**netifcon)); (*netifcon)->interface_str = NULL; (*netifcon)->if_context_str = NULL; (*netifcon)->if_context = NULL; (*netifcon)->packet_context_str = NULL; (*netifcon)->packet_context = NULL; (*netifcon)->context_str = NULL; } void cil_ibendportcon_init(struct cil_ibendportcon **ibendportcon) { *ibendportcon = cil_malloc(sizeof(**ibendportcon)); (*ibendportcon)->dev_name_str = NULL; (*ibendportcon)->port = 0; (*ibendportcon)->context_str = NULL; (*ibendportcon)->context = NULL; } void cil_context_init(struct cil_context **context) { *context = cil_malloc(sizeof(**context)); cil_symtab_datum_init(&(*context)->datum); (*context)->user_str = NULL; (*context)->user = NULL; (*context)->role_str = NULL; (*context)->role = NULL; (*context)->type_str = NULL; (*context)->type = NULL; (*context)->range_str = NULL; (*context)->range = NULL; } void cil_level_init(struct cil_level **level) { *level = cil_malloc(sizeof(**level)); cil_symtab_datum_init(&(*level)->datum); (*level)->sens_str = NULL; (*level)->sens = NULL; (*level)->cats = NULL; } void cil_levelrange_init(struct cil_levelrange **range) { *range = cil_malloc(sizeof(**range)); cil_symtab_datum_init(&(*range)->datum); (*range)->low_str = NULL; (*range)->low = NULL; (*range)->high_str = NULL; (*range)->high = NULL; } void cil_sens_init(struct cil_sens **sens) { *sens = cil_malloc(sizeof(**sens)); cil_symtab_datum_init(&(*sens)->datum); (*sens)->cats_list = NULL; (*sens)->ordered = CIL_FALSE; } void cil_block_init(struct cil_block **block) { *block = cil_malloc(sizeof(**block)); cil_symtab_datum_init(&(*block)->datum); cil_symtab_array_init((*block)->symtab, cil_sym_sizes[CIL_SYM_ARRAY_BLOCK]); (*block)->is_abstract = CIL_FALSE; (*block)->bi_nodes = NULL; } void cil_blockinherit_init(struct cil_blockinherit **inherit) { *inherit = cil_malloc(sizeof(**inherit)); (*inherit)->block_str = NULL; (*inherit)->block = NULL; } void cil_blockabstract_init(struct cil_blockabstract **abstract) { *abstract = cil_malloc(sizeof(**abstract)); (*abstract)->block_str = NULL; (*abstract)->block = 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)->is_after = CIL_FALSE; (*in)->block_str = NULL; (*in)->block = 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_classcommon_init(struct cil_classcommon **classcommon) { *classcommon = cil_malloc(sizeof(**classcommon)); (*classcommon)->class_str = NULL; (*classcommon)->class = NULL; (*classcommon)->common_str = NULL; (*classcommon)->common = 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)->sid = NULL; (*sidcontext)->context_str = NULL; (*sidcontext)->context = 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)->attr = NULL; (*attrset)->str_expr = NULL; (*attrset)->datum_expr = NULL; } void cil_typeattribute_init(struct cil_typeattribute **attr) { *attr = cil_malloc(sizeof(**attr)); cil_symtab_datum_init(&(*attr)->datum); (*attr)->expr_list = NULL; (*attr)->types = NULL; (*attr)->used = CIL_FALSE; (*attr)->keep = CIL_FALSE; } void cil_typeattributeset_init(struct cil_typeattributeset **attrset) { *attrset = cil_malloc(sizeof(**attrset)); (*attrset)->attr_str = NULL; (*attrset)->attr = NULL; (*attrset)->str_expr = NULL; (*attrset)->datum_expr = NULL; } void cil_expandtypeattribute_init(struct cil_expandtypeattribute **expandattr) { *expandattr = cil_malloc(sizeof(**expandattr)); (*expandattr)->attr_strs = NULL; (*expandattr)->attr_datums = NULL; (*expandattr)->expand = 0; } void cil_alias_init(struct cil_alias **alias) { *alias = cil_malloc(sizeof(**alias)); (*alias)->actual = NULL; cil_symtab_datum_init(&(*alias)->datum); } void cil_aliasactual_init(struct cil_aliasactual **aliasactual) { *aliasactual = cil_malloc(sizeof(**aliasactual)); (*aliasactual)->alias_str = NULL; (*aliasactual)->alias = NULL; (*aliasactual)->actual_str = NULL; (*aliasactual)->actual = NULL; } void cil_typepermissive_init(struct cil_typepermissive **typeperm) { *typeperm = cil_malloc(sizeof(**typeperm)); (*typeperm)->type_str = NULL; (*typeperm)->type = NULL; } void cil_nametypetransition_init(struct cil_nametypetransition **nametypetrans) { *nametypetrans = cil_malloc(sizeof(**nametypetrans)); (*nametypetrans)->src_str = NULL; (*nametypetrans)->src = NULL; (*nametypetrans)->tgt_str = NULL; (*nametypetrans)->tgt = NULL; (*nametypetrans)->obj_str = NULL; (*nametypetrans)->obj = NULL; (*nametypetrans)->name_str = NULL; (*nametypetrans)->name = NULL; (*nametypetrans)->result_str = NULL; (*nametypetrans)->result = NULL; } void cil_rangetransition_init(struct cil_rangetransition **rangetrans) { *rangetrans = cil_malloc(sizeof(**rangetrans)); (*rangetrans)->src_str = NULL; (*rangetrans)->src = NULL; (*rangetrans)->exec_str = NULL; (*rangetrans)->exec = NULL; (*rangetrans)->obj_str = NULL; (*rangetrans)->obj = NULL; (*rangetrans)->range_str = NULL; (*rangetrans)->range = NULL; } void cil_bool_init(struct cil_bool **cilbool) { *cilbool = cil_malloc(sizeof(**cilbool)); cil_symtab_datum_init(&(*cilbool)->datum); (*cilbool)->value = 0; } void cil_tunable_init(struct cil_tunable **ciltun) { *ciltun = cil_malloc(sizeof(**ciltun)); cil_symtab_datum_init(&(*ciltun)->datum); (*ciltun)->value = 0; } void cil_condblock_init(struct cil_condblock **cb) { *cb = cil_malloc(sizeof(**cb)); (*cb)->flavor = CIL_NONE; cil_symtab_array_init((*cb)->symtab, cil_sym_sizes[CIL_SYM_ARRAY_CONDBLOCK]); } void cil_boolif_init(struct cil_booleanif **bif) { *bif = cil_malloc(sizeof(**bif)); (*bif)->str_expr = NULL; (*bif)->datum_expr = NULL; } void cil_tunif_init(struct cil_tunableif **tif) { *tif = cil_malloc(sizeof(**tif)); (*tif)->str_expr = NULL; (*tif)->datum_expr = NULL; } void cil_avrule_init(struct cil_avrule **avrule) { *avrule = cil_malloc(sizeof(**avrule)); (*avrule)->is_extended = 0; (*avrule)->rule_kind = CIL_NONE; (*avrule)->src_str = NULL; (*avrule)->src = NULL; (*avrule)->tgt_str = NULL; (*avrule)->tgt = NULL; memset(&((*avrule)->perms), 0, sizeof((*avrule)->perms)); } void cil_permissionx_init(struct cil_permissionx **permx) { *permx = cil_malloc(sizeof(**permx)); cil_symtab_datum_init(&(*permx)->datum); (*permx)->kind = CIL_NONE; (*permx)->obj_str = NULL; (*permx)->obj = NULL; (*permx)->expr_str = NULL; (*permx)->perms = NULL; } void cil_deny_rule_init(struct cil_deny_rule **rule) { *rule = cil_malloc(sizeof(**rule)); (*rule)->src_str = NULL; (*rule)->src = NULL; (*rule)->tgt_str = NULL; (*rule)->tgt = NULL; (*rule)->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)->sens = 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 = CIL_FILECON_ANY; (*filecon)->context_str = NULL; (*filecon)->context = NULL; } void cil_ibpkeycon_init(struct cil_ibpkeycon **ibpkeycon) { *ibpkeycon = cil_malloc(sizeof(**ibpkeycon)); (*ibpkeycon)->subnet_prefix_str = NULL; (*ibpkeycon)->pkey_low = 0; (*ibpkeycon)->pkey_high = 0; (*ibpkeycon)->context_str = NULL; (*ibpkeycon)->context = NULL; } void cil_portcon_init(struct cil_portcon **portcon) { *portcon = cil_malloc(sizeof(**portcon)); (*portcon)->proto = 0; (*portcon)->port_low = 0; (*portcon)->port_high = 0; (*portcon)->context_str = NULL; (*portcon)->context = NULL; } void cil_nodecon_init(struct cil_nodecon **nodecon) { *nodecon = cil_malloc(sizeof(**nodecon)); (*nodecon)->addr_str = NULL; (*nodecon)->addr = NULL; (*nodecon)->mask_str = NULL; (*nodecon)->mask = NULL; (*nodecon)->context_str = NULL; (*nodecon)->context = NULL; } void cil_genfscon_init(struct cil_genfscon **genfscon) { *genfscon = cil_malloc(sizeof(**genfscon)); (*genfscon)->fs_str = NULL; (*genfscon)->path_str = NULL; (*genfscon)->file_type = CIL_FILECON_ANY; (*genfscon)->context_str = NULL; (*genfscon)->context = NULL; } void cil_pirqcon_init(struct cil_pirqcon **pirqcon) { *pirqcon = cil_malloc(sizeof(**pirqcon)); (*pirqcon)->pirq = 0; (*pirqcon)->context_str = NULL; (*pirqcon)->context = NULL; } void cil_iomemcon_init(struct cil_iomemcon **iomemcon) { *iomemcon = cil_malloc(sizeof(**iomemcon)); (*iomemcon)->iomem_low = 0; (*iomemcon)->iomem_high = 0; (*iomemcon)->context_str = NULL; (*iomemcon)->context = NULL; } void cil_ioportcon_init(struct cil_ioportcon **ioportcon) { *ioportcon = cil_malloc(sizeof(**ioportcon)); (*ioportcon)->context_str = NULL; (*ioportcon)->context = NULL; } void cil_pcidevicecon_init(struct cil_pcidevicecon **pcidevicecon) { *pcidevicecon = cil_malloc(sizeof(**pcidevicecon)); (*pcidevicecon)->dev = 0; (*pcidevicecon)->context_str = NULL; (*pcidevicecon)->context = NULL; } void cil_devicetreecon_init(struct cil_devicetreecon **dtcon) { *dtcon = cil_malloc(sizeof(**dtcon)); (*dtcon)->path = NULL; (*dtcon)->context_str = NULL; (*dtcon)->context = NULL; } void cil_fsuse_init(struct cil_fsuse **fsuse) { *fsuse = cil_malloc(sizeof(**fsuse)); (*fsuse)->type = 0; (*fsuse)->fs_str = NULL; (*fsuse)->context_str = NULL; (*fsuse)->context = NULL; } void cil_constrain_init(struct cil_constrain **constrain) { *constrain = cil_malloc(sizeof(**constrain)); (*constrain)->classperms = NULL; (*constrain)->str_expr = NULL; (*constrain)->datum_expr = NULL; } void cil_validatetrans_init(struct cil_validatetrans **validtrans) { *validtrans = cil_malloc(sizeof(**validtrans)); (*validtrans)->class_str = NULL; (*validtrans)->class = NULL; (*validtrans)->str_expr = NULL; (*validtrans)->datum_expr = NULL; } void cil_ipaddr_init(struct cil_ipaddr **ipaddr) { *ipaddr = cil_malloc(sizeof(**ipaddr)); cil_symtab_datum_init(&(*ipaddr)->datum); memset(&(*ipaddr)->ip, 0, sizeof((*ipaddr)->ip)); } void cil_perm_init(struct cil_perm **perm) { *perm = cil_malloc(sizeof(**perm)); cil_symtab_datum_init(&(*perm)->datum); (*perm)->value = 0; (*perm)->classperms = NULL; } void cil_classpermission_init(struct cil_classpermission **cp) { *cp = cil_malloc(sizeof(**cp)); cil_symtab_datum_init(&(*cp)->datum); (*cp)->classperms = NULL; } void cil_classpermissionset_init(struct cil_classpermissionset **cps) { *cps = cil_malloc(sizeof(**cps)); (*cps)->set_str = NULL; (*cps)->set = 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_class = NULL; (*mapping)->map_perm_str = NULL; (*mapping)->map_perm = NULL; (*mapping)->classperms = NULL; } void cil_user_init(struct cil_user **user) { *user = cil_malloc(sizeof(**user)); cil_symtab_datum_init(&(*user)->datum); (*user)->bounds = NULL; (*user)->roles = NULL; (*user)->dftlevel = NULL; (*user)->range = NULL; (*user)->value = 0; } void cil_userattribute_init(struct cil_userattribute **attr) { *attr = cil_malloc(sizeof(**attr)); cil_symtab_datum_init(&(*attr)->datum); (*attr)->expr_list = NULL; (*attr)->users = NULL; } void cil_userattributeset_init(struct cil_userattributeset **attrset) { *attrset = cil_malloc(sizeof(**attrset)); (*attrset)->attr_str = NULL; (*attrset)->attr = NULL; (*attrset)->str_expr = NULL; (*attrset)->datum_expr = NULL; } void cil_userlevel_init(struct cil_userlevel **usrlvl) { *usrlvl = cil_malloc(sizeof(**usrlvl)); (*usrlvl)->user_str = NULL; (*usrlvl)->user = 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)->user = 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_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)->parent = NULL; (*bounds)->child_str = NULL; (*bounds)->child = NULL; } void cil_default_init(struct cil_default **def) { *def = cil_malloc(sizeof(**def)); (*def)->flavor = CIL_NONE; (*def)->class_strs = NULL; (*def)->class_datums = NULL; } void cil_defaultrange_init(struct cil_defaultrange **def) { *def = cil_malloc(sizeof(**def)); (*def)->class_strs = NULL; (*def)->class_datums = NULL; } void cil_handleunknown_init(struct cil_handleunknown **unk) { *unk = cil_malloc(sizeof(**unk)); } void cil_mls_init(struct cil_mls **mls) { *mls = cil_malloc(sizeof(**mls)); (*mls)->value = 0; } void cil_src_info_init(struct cil_src_info **info) { *info = cil_malloc(sizeof(**info)); (*info)->kind = NULL; (*info)->hll_line = 0; (*info)->path = NULL; } libsepol-3.8.1/cil/src/cil_binary.c000066400000000000000000004312251476211737200171720ustar00rootroot00000000000000/* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #include #include #include #include #ifndef IPPROTO_DCCP #define IPPROTO_DCCP 33 #endif #ifndef IPPROTO_SCTP #define IPPROTO_SCTP 132 #endif #include #include #include #include #include #include #include "cil_internal.h" #include "cil_flavor.h" #include "cil_log.h" #include "cil_mem.h" #include "cil_tree.h" #include "cil_binary.h" #include "cil_symtab.h" #include "cil_find.h" #include "cil_build_ast.h" #define ROLE_TRANS_TABLE_SIZE (1 << 10) #define AVRULEX_TABLE_SIZE (1 << 10) #define PERMS_PER_CLASS 32 struct cil_args_xperm_tables { hashtab_t ioctl; hashtab_t nlmsg; }; struct cil_args_binary { const struct cil_db *db; policydb_t *pdb; struct cil_list *neverallows; int pass; hashtab_t role_trans_table; struct cil_args_xperm_tables avrulex_xperm_tables; void **type_value_to_cil; }; struct cil_args_booleanif { const struct cil_db *db; policydb_t *pdb; cond_node_t *cond_node; enum cil_flavor cond_flavor; struct cil_args_xperm_tables avrulex_xperm_tables; }; static unsigned int avrulex_hash(__attribute__((unused)) hashtab_t h, const_hashtab_key_t key); static int avrulex_compare(hashtab_t h __attribute__ ((unused)), const_hashtab_key_t key1, const_hashtab_key_t key2); static int __cil_get_sepol_user_datum(policydb_t *pdb, struct cil_symtab_datum *datum, user_datum_t **sepol_user) { *sepol_user = hashtab_search(pdb->p_users.table, datum->fqn); if (*sepol_user == NULL) { cil_log(CIL_INFO, "Failed to find user %s in sepol hashtab\n", datum->fqn); return SEPOL_ERR; } return SEPOL_OK; } static int __cil_get_sepol_role_datum(policydb_t *pdb, struct cil_symtab_datum *datum, role_datum_t **sepol_role) { *sepol_role = hashtab_search(pdb->p_roles.table, datum->fqn); if (*sepol_role == NULL) { cil_log(CIL_INFO, "Failed to find role %s in sepol hashtab\n", datum->fqn); return SEPOL_ERR; } return SEPOL_OK; } static int __cil_get_sepol_type_datum(policydb_t *pdb, struct cil_symtab_datum *datum, type_datum_t **sepol_type) { *sepol_type = hashtab_search(pdb->p_types.table, datum->fqn); if (*sepol_type == NULL) { cil_log(CIL_INFO, "Failed to find type %s in sepol hashtab\n", datum->fqn); return SEPOL_ERR; } return SEPOL_OK; } static int __cil_get_sepol_class_datum(policydb_t *pdb, struct cil_symtab_datum *datum, class_datum_t **sepol_class) { *sepol_class = hashtab_search(pdb->p_classes.table, datum->fqn); if (*sepol_class == NULL) { cil_log(CIL_INFO, "Failed to find class %s in sepol hashtab\n", datum->fqn); return SEPOL_ERR; } return SEPOL_OK; } static int __cil_get_sepol_cat_datum(policydb_t *pdb, struct cil_symtab_datum *datum, cat_datum_t **sepol_cat) { *sepol_cat = hashtab_search(pdb->p_cats.table, datum->fqn); if (*sepol_cat == NULL) { cil_log(CIL_INFO, "Failed to find category %s in sepol hashtab\n", datum->fqn); return SEPOL_ERR; } return SEPOL_OK; } static int __cil_get_sepol_level_datum(policydb_t *pdb, struct cil_symtab_datum *datum, level_datum_t **sepol_level) { *sepol_level = hashtab_search(pdb->p_levels.table, datum->fqn); if (*sepol_level == NULL) { cil_log(CIL_INFO, "Failed to find level %s in sepol hashtab\n", datum->fqn); return SEPOL_ERR; } return SEPOL_OK; } static int __cil_expand_user(struct cil_symtab_datum *datum, ebitmap_t *new) { struct cil_tree_node *node = NODE(datum); struct cil_user *user = NULL; struct cil_userattribute *attr = NULL; if (node->flavor == CIL_USERATTRIBUTE) { attr = (struct cil_userattribute *)datum; if (ebitmap_cpy(new, attr->users)) { cil_log(CIL_ERR, "Failed to copy user bits\n"); goto exit; } } else { user = (struct cil_user *)datum; ebitmap_init(new); if (ebitmap_set_bit(new, user->value, 1)) { cil_log(CIL_ERR, "Failed to set user bit\n"); ebitmap_destroy(new); goto exit; } } return SEPOL_OK; exit: return SEPOL_ERR; } static int __cil_expand_role(struct cil_symtab_datum *datum, ebitmap_t *new) { struct cil_tree_node *node = NODE(datum); 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 = NODE(datum); if (node->flavor == CIL_TYPEATTRIBUTE) { struct cil_typeattribute *attr = (struct cil_typeattribute *)datum; if (ebitmap_cpy(new, attr->types)) { cil_log(CIL_ERR, "Failed to copy type bits\n"); goto exit; } } else { struct cil_type *type = (struct cil_type *)datum; ebitmap_init(new); if (ebitmap_set_bit(new, type->value, 1)) { cil_log(CIL_ERR, "Failed to set type bit\n"); ebitmap_destroy(new); goto exit; } } return SEPOL_OK; exit: return SEPOL_ERR; } static ocontext_t *cil_add_ocontext(ocontext_t **head, ocontext_t **tail) { ocontext_t *new = cil_malloc(sizeof(ocontext_t)); memset(new, 0, sizeof(ocontext_t)); if (*tail) { (*tail)->next = new; } else { *head = new; } *tail = new; return new; } int cil_common_to_policydb(policydb_t *pdb, struct cil_class *cil_common, common_datum_t **common_out) { int rc = SEPOL_ERR; uint32_t value = 0; char *key = NULL; struct cil_tree_node *node = cil_common->datum.nodes->head->data; struct cil_tree_node *cil_perm = node->cl_head; common_datum_t *sepol_common = cil_malloc(sizeof(*sepol_common)); memset(sepol_common, 0, sizeof(common_datum_t)); key = cil_strdup(cil_common->datum.fqn); rc = symtab_insert(pdb, SYM_COMMONS, key, sepol_common, SCOPE_DECL, 0, &value); if (rc != SEPOL_OK) { free(sepol_common); goto exit; } sepol_common->s.value = value; rc = symtab_init(&sepol_common->permissions, PERM_SYMTAB_SIZE); if (rc != SEPOL_OK) { goto exit; } while (cil_perm != NULL) { struct cil_perm *curr = cil_perm->data; perm_datum_t *sepol_perm = cil_malloc(sizeof(*sepol_perm)); memset(sepol_perm, 0, sizeof(perm_datum_t)); key = cil_strdup(curr->datum.fqn); rc = hashtab_insert(sepol_common->permissions.table, key, sepol_perm); if (rc != SEPOL_OK) { free(sepol_perm); goto exit; } sepol_perm->s.value = sepol_common->permissions.nprim + 1; sepol_common->permissions.nprim++; cil_perm = cil_perm->next; } *common_out = sepol_common; return SEPOL_OK; exit: free(key); return rc; } static int cil_classorder_to_policydb(policydb_t *pdb, const struct cil_db *db, struct cil_class *class_value_to_cil[], struct cil_perm **perm_value_to_cil[]) { int rc = SEPOL_ERR; struct cil_list_item *curr_class; cil_list_for_each(curr_class, db->classorder) { struct cil_class *cil_class = curr_class->data; uint32_t value = 0; char *key = NULL; int class_index; struct cil_tree_node *curr; common_datum_t *sepol_common = NULL; class_datum_t *sepol_class = cil_malloc(sizeof(*sepol_class)); memset(sepol_class, 0, sizeof(class_datum_t)); key = cil_strdup(cil_class->datum.fqn); rc = symtab_insert(pdb, SYM_CLASSES, key, sepol_class, SCOPE_DECL, 0, &value); if (rc != SEPOL_OK) { free(sepol_class); free(key); goto exit; } sepol_class->s.value = value; class_index = value; class_value_to_cil[class_index] = cil_class; rc = symtab_init(&sepol_class->permissions, PERM_SYMTAB_SIZE); if (rc != SEPOL_OK) { goto exit; } if (cil_class->common != NULL) { int i; struct cil_class *cil_common = cil_class->common; key = cil_class->common->datum.fqn; sepol_common = hashtab_search(pdb->p_commons.table, key); if (sepol_common == NULL) { rc = cil_common_to_policydb(pdb, cil_common, &sepol_common); if (rc != SEPOL_OK) { goto exit; } } sepol_class->comdatum = sepol_common; sepol_class->comkey = cil_strdup(key); sepol_class->permissions.nprim += sepol_common->permissions.nprim; for (curr = NODE(cil_class->common)->cl_head, i = 1; curr; curr = curr->next, i++) { struct cil_perm *cil_perm = curr->data; perm_value_to_cil[class_index][i] = cil_perm; } } for (curr = NODE(cil_class)->cl_head; curr; curr = curr->next) { struct cil_perm *cil_perm = curr->data; perm_datum_t *sepol_perm = cil_malloc(sizeof(*sepol_perm)); memset(sepol_perm, 0, sizeof(perm_datum_t)); key = cil_strdup(cil_perm->datum.fqn); rc = hashtab_insert(sepol_class->permissions.table, key, sepol_perm); if (rc != SEPOL_OK) { free(sepol_perm); free(key); goto exit; } sepol_perm->s.value = sepol_class->permissions.nprim + 1; sepol_class->permissions.nprim++; perm_value_to_cil[class_index][sepol_perm->s.value] = cil_perm; } } return SEPOL_OK; exit: return rc; } int cil_role_to_policydb(policydb_t *pdb, struct cil_role *cil_role) { int rc = SEPOL_ERR; uint32_t value = 0; char *key = NULL; role_datum_t *sepol_role = cil_malloc(sizeof(*sepol_role)); role_datum_init(sepol_role); if (cil_role->datum.fqn == CIL_KEY_OBJECT_R) { /* special case * object_r defaults to 1 in libsepol symtab */ rc = SEPOL_OK; goto exit; } key = cil_strdup(cil_role->datum.fqn); rc = symtab_insert(pdb, SYM_ROLES, (hashtab_key_t)key, sepol_role, SCOPE_DECL, 0, &value); if (rc != SEPOL_OK) { goto exit; } if (ebitmap_set_bit(&sepol_role->dominates, value - 1, 1)) { cil_log(CIL_INFO, "Failed to set dominates bit for role\n"); rc = SEPOL_ERR; goto exit; } sepol_role->s.value = value; return SEPOL_OK; exit: free(key); role_datum_destroy(sepol_role); free(sepol_role); return rc; } static int cil_role_bounds_to_policydb(policydb_t *pdb, struct cil_role *cil_role) { int rc = SEPOL_ERR; role_datum_t *sepol_role = NULL; role_datum_t *sepol_parent = NULL; if (cil_role->bounds) { rc = __cil_get_sepol_role_datum(pdb, DATUM(cil_role), &sepol_role); if (rc != SEPOL_OK) goto exit; rc = __cil_get_sepol_role_datum(pdb, DATUM(cil_role->bounds), &sepol_parent); if (rc != SEPOL_OK) goto exit; sepol_role->bounds = sepol_parent->s.value; } return SEPOL_OK; exit: cil_log(CIL_ERR, "Failed to insert role bounds for role %s\n", cil_role->datum.fqn); return SEPOL_ERR; } int cil_roletype_to_policydb(policydb_t *pdb, const struct cil_db *db, struct cil_role *role) { int rc = SEPOL_ERR; if (role->types) { role_datum_t *sepol_role = NULL; type_datum_t *sepol_type = NULL; ebitmap_node_t *tnode; unsigned int i; rc = __cil_get_sepol_role_datum(pdb, DATUM(role), &sepol_role); if (rc != SEPOL_OK) goto exit; ebitmap_for_each_positive_bit(role->types, tnode, i) { rc = __cil_get_sepol_type_datum(pdb, DATUM(db->val_to_type[i]), &sepol_type); if (rc != SEPOL_OK) goto exit; if (ebitmap_set_bit(&sepol_role->types.types, sepol_type->s.value - 1, 1)) { cil_log(CIL_INFO, "Failed to set type bit for role\n"); rc = SEPOL_ERR; goto exit; } } } return SEPOL_OK; exit: return rc; } int cil_type_to_policydb(policydb_t *pdb, struct cil_type *cil_type, void *type_value_to_cil[]) { int rc = SEPOL_ERR; uint32_t value = 0; char *key = NULL; type_datum_t *sepol_type = cil_malloc(sizeof(*sepol_type)); type_datum_init(sepol_type); sepol_type->flavor = TYPE_TYPE; key = cil_strdup(cil_type->datum.fqn); rc = symtab_insert(pdb, SYM_TYPES, key, sepol_type, SCOPE_DECL, 0, &value); if (rc != SEPOL_OK) { goto exit; } sepol_type->s.value = value; sepol_type->primary = 1; type_value_to_cil[value] = cil_type; return SEPOL_OK; exit: free(key); type_datum_destroy(sepol_type); free(sepol_type); return rc; } static int cil_type_bounds_to_policydb(policydb_t *pdb, struct cil_type *cil_type) { int rc = SEPOL_ERR; type_datum_t *sepol_type = NULL; type_datum_t *sepol_parent = NULL; if (cil_type->bounds) { rc = __cil_get_sepol_type_datum(pdb, DATUM(cil_type), &sepol_type); if (rc != SEPOL_OK) goto exit; rc = __cil_get_sepol_type_datum(pdb, DATUM(cil_type->bounds), &sepol_parent); if (rc != SEPOL_OK) goto exit; sepol_type->bounds = sepol_parent->s.value; } return SEPOL_OK; exit: cil_log(CIL_ERR, "Failed to insert type bounds for type %s\n", cil_type->datum.fqn); return SEPOL_ERR; } int cil_typealias_to_policydb(policydb_t *pdb, struct cil_alias *cil_alias) { int rc = SEPOL_ERR; char *key = NULL; type_datum_t *sepol_type = NULL; type_datum_t *sepol_alias = cil_malloc(sizeof(*sepol_alias)); type_datum_init(sepol_alias); rc = __cil_get_sepol_type_datum(pdb, DATUM(cil_alias->actual), &sepol_type); if (rc != SEPOL_OK) goto exit; sepol_alias->flavor = TYPE_TYPE; key = cil_strdup(cil_alias->datum.fqn); rc = symtab_insert(pdb, SYM_TYPES, key, sepol_alias, SCOPE_DECL, 0, NULL); if (rc != SEPOL_OK) { goto exit; } sepol_alias->s.value = sepol_type->s.value; sepol_alias->primary = 0; return SEPOL_OK; exit: free(key); type_datum_destroy(sepol_alias); free(sepol_alias); return rc; } int cil_typepermissive_to_policydb(policydb_t *pdb, struct cil_typepermissive *cil_typeperm) { int rc = SEPOL_ERR; type_datum_t *sepol_type = NULL; rc = __cil_get_sepol_type_datum(pdb, DATUM(cil_typeperm->type), &sepol_type); if (rc != SEPOL_OK) goto exit; if (ebitmap_set_bit(&pdb->permissive_map, sepol_type->s.value, 1)) { goto exit; } return SEPOL_OK; exit: type_datum_destroy(sepol_type); free(sepol_type); return rc; } int cil_typeattribute_to_policydb(policydb_t *pdb, struct cil_typeattribute *cil_attr, void *type_value_to_cil[]) { int rc = SEPOL_ERR; uint32_t value = 0; char *key = NULL; type_datum_t *sepol_attr = NULL; if (!cil_attr->keep) { return SEPOL_OK; } sepol_attr = cil_malloc(sizeof(*sepol_attr)); type_datum_init(sepol_attr); sepol_attr->flavor = TYPE_ATTRIB; key = cil_strdup(cil_attr->datum.fqn); rc = symtab_insert(pdb, SYM_TYPES, key, sepol_attr, SCOPE_DECL, 0, &value); if (rc != SEPOL_OK) { goto exit; } sepol_attr->s.value = value; sepol_attr->primary = 1; type_value_to_cil[value] = cil_attr; return SEPOL_OK; exit: type_datum_destroy(sepol_attr); free(sepol_attr); return rc; } static int __cil_typeattr_bitmap_init(policydb_t *pdb) { int rc = SEPOL_ERR; uint32_t i; pdb->type_attr_map = cil_malloc(pdb->p_types.nprim * sizeof(ebitmap_t)); pdb->attr_type_map = cil_malloc(pdb->p_types.nprim * sizeof(ebitmap_t)); for (i = 0; i < pdb->p_types.nprim; i++) { ebitmap_init(&pdb->type_attr_map[i]); ebitmap_init(&pdb->attr_type_map[i]); if (ebitmap_set_bit(&pdb->type_attr_map[i], i, 1)) { rc = SEPOL_ERR; goto exit; } if (pdb->type_val_to_struct[i] && pdb->type_val_to_struct[i]->flavor != TYPE_ATTRIB) { if (ebitmap_set_bit(&pdb->attr_type_map[i], i, 1)) { rc = SEPOL_ERR; goto exit; } } } return SEPOL_OK; exit: return rc; } int cil_typeattribute_to_bitmap(policydb_t *pdb, const struct cil_db *db, struct cil_typeattribute *cil_attr) { int rc = SEPOL_ERR; uint32_t value = 0; type_datum_t *sepol_type = NULL; ebitmap_node_t *tnode; unsigned int i; if (!cil_attr->keep) { return SEPOL_OK; } if (pdb->type_attr_map == NULL) { rc = __cil_typeattr_bitmap_init(pdb); if (rc != SEPOL_OK) { goto exit; } } rc = __cil_get_sepol_type_datum(pdb, DATUM(cil_attr), &sepol_type); if (rc != SEPOL_OK) goto exit; value = sepol_type->s.value; ebitmap_for_each_positive_bit(cil_attr->types, tnode, i) { rc = __cil_get_sepol_type_datum(pdb, DATUM(db->val_to_type[i]), &sepol_type); if (rc != SEPOL_OK) goto exit; ebitmap_set_bit(&pdb->type_attr_map[sepol_type->s.value - 1], value - 1, 1); ebitmap_set_bit(&pdb->attr_type_map[value - 1], sepol_type->s.value - 1, 1); } rc = SEPOL_OK; exit: return rc; } int cil_policycap_to_policydb(policydb_t *pdb, struct cil_policycap *cil_polcap) { int rc = SEPOL_ERR; int capnum; capnum = sepol_polcap_getnum(cil_polcap->datum.fqn); if (capnum == -1) { goto exit; } if (ebitmap_set_bit(&pdb->policycaps, capnum, 1)) { goto exit; } return SEPOL_OK; exit: return rc; } int cil_user_to_policydb(policydb_t *pdb, struct cil_user *cil_user) { int rc = SEPOL_ERR; uint32_t value = 0; char *key = NULL; user_datum_t *sepol_user = cil_malloc(sizeof(*sepol_user)); user_datum_init(sepol_user); key = cil_strdup(cil_user->datum.fqn); rc = symtab_insert(pdb, SYM_USERS, key, sepol_user, SCOPE_DECL, 0, &value); if (rc != SEPOL_OK) { goto exit; } sepol_user->s.value = value; return SEPOL_OK; exit: free(key); user_datum_destroy(sepol_user); free(sepol_user); return rc; } static int cil_user_bounds_to_policydb(policydb_t *pdb, struct cil_user *cil_user) { int rc = SEPOL_ERR; user_datum_t *sepol_user = NULL; user_datum_t *sepol_parent = NULL; if (cil_user->bounds) { rc = __cil_get_sepol_user_datum(pdb, DATUM(cil_user), &sepol_user); if (rc != SEPOL_OK) goto exit; rc = __cil_get_sepol_user_datum(pdb, DATUM(cil_user->bounds), &sepol_parent); if (rc != SEPOL_OK) goto exit; sepol_user->bounds = sepol_parent->s.value; } return SEPOL_OK; exit: cil_log(CIL_ERR, "Failed to insert user bounds for user %s\n", cil_user->datum.fqn); return SEPOL_ERR; } int cil_userrole_to_policydb(policydb_t *pdb, const struct cil_db *db, struct cil_user *user) { int rc = SEPOL_ERR; user_datum_t *sepol_user = NULL; role_datum_t *sepol_role = NULL; ebitmap_node_t *rnode = NULL; unsigned int i; if (user->roles) { rc = __cil_get_sepol_user_datum(pdb, DATUM(user), &sepol_user); if (rc != SEPOL_OK) { goto exit; } ebitmap_for_each_positive_bit(user->roles, rnode, i) { rc = __cil_get_sepol_role_datum(pdb, DATUM(db->val_to_role[i]), &sepol_role); if (rc != SEPOL_OK) { goto exit; } if (sepol_role->s.value == 1) { // role is object_r, ignore it since it is implicitly associated // with all users continue; } if (ebitmap_set_bit(&sepol_user->roles.roles, sepol_role->s.value - 1, 1)) { cil_log(CIL_INFO, "Failed to set role bit for user\n"); rc = SEPOL_ERR; goto exit; } } } rc = SEPOL_OK; exit: return rc; } int cil_bool_to_policydb(policydb_t *pdb, struct cil_bool *cil_bool) { int rc = SEPOL_ERR; uint32_t value = 0; char *key = NULL; cond_bool_datum_t *sepol_bool = cil_malloc(sizeof(*sepol_bool)); memset(sepol_bool, 0, sizeof(cond_bool_datum_t)); key = cil_strdup(cil_bool->datum.fqn); rc = symtab_insert(pdb, SYM_BOOLS, key, sepol_bool, SCOPE_DECL, 0, &value); if (rc != SEPOL_OK) { goto exit; } sepol_bool->s.value = value; sepol_bool->state = cil_bool->value; return SEPOL_OK; exit: free(key); free(sepol_bool); return rc; } int cil_catorder_to_policydb(policydb_t *pdb, const struct cil_db *db) { int rc = SEPOL_ERR; uint32_t value = 0; char *key = NULL; struct cil_list_item *curr_cat; struct cil_cat *cil_cat = NULL; cat_datum_t *sepol_cat = NULL; cil_list_for_each(curr_cat, db->catorder) { cil_cat = curr_cat->data; sepol_cat = cil_malloc(sizeof(*sepol_cat)); cat_datum_init(sepol_cat); key = cil_strdup(cil_cat->datum.fqn); rc = symtab_insert(pdb, SYM_CATS, key, sepol_cat, SCOPE_DECL, 0, &value); if (rc != SEPOL_OK) { goto exit; } sepol_cat->s.value = value; } return SEPOL_OK; exit: free(key); cat_datum_destroy(sepol_cat); free(sepol_cat); return rc; } int cil_catalias_to_policydb(policydb_t *pdb, struct cil_alias *cil_alias) { int rc = SEPOL_ERR; char *key = NULL; cat_datum_t *sepol_cat; cat_datum_t *sepol_alias = cil_malloc(sizeof(*sepol_cat)); cat_datum_init(sepol_alias); rc = __cil_get_sepol_cat_datum(pdb, DATUM(cil_alias->actual), &sepol_cat); if (rc != SEPOL_OK) goto exit; key = cil_strdup(cil_alias->datum.fqn); rc = symtab_insert(pdb, SYM_CATS, key, sepol_alias, SCOPE_DECL, 0, NULL); if (rc != SEPOL_OK) { goto exit; } sepol_alias->s.value = sepol_cat->s.value; sepol_alias->isalias = 1; return SEPOL_OK; exit: free(key); cat_datum_destroy(sepol_alias); free(sepol_alias); return rc; } int cil_sensitivityorder_to_policydb(policydb_t *pdb, const struct cil_db *db) { int rc = SEPOL_ERR; uint32_t value = 0; char *key = NULL; struct cil_list_item *curr; struct cil_sens *cil_sens = NULL; level_datum_t *sepol_level = NULL; mls_level_t *mls_level = NULL; cil_list_for_each(curr, db->sensitivityorder) { cil_sens = curr->data; sepol_level = cil_malloc(sizeof(*sepol_level)); mls_level = cil_malloc(sizeof(*mls_level)); level_datum_init(sepol_level); mls_level_init(mls_level); key = cil_strdup(cil_sens->datum.fqn); rc = symtab_insert(pdb, SYM_LEVELS, key, sepol_level, SCOPE_DECL, 0, &value); if (rc != SEPOL_OK) { goto exit; } mls_level->sens = value; sepol_level->level = mls_level; } return SEPOL_OK; exit: level_datum_destroy(sepol_level); mls_level_destroy(mls_level); free(sepol_level); free(mls_level); free(key); return rc; } static int cil_sensalias_to_policydb(policydb_t *pdb, struct cil_alias *cil_alias) { int rc = SEPOL_ERR; char *key = NULL; mls_level_t *mls_level = NULL; level_datum_t *sepol_level = NULL; level_datum_t *sepol_alias = cil_malloc(sizeof(*sepol_alias)); level_datum_init(sepol_alias); rc = __cil_get_sepol_level_datum(pdb, DATUM(cil_alias->actual), &sepol_level); if (rc != SEPOL_OK) goto exit; key = cil_strdup(cil_alias->datum.fqn); rc = symtab_insert(pdb, SYM_LEVELS, key, sepol_alias, SCOPE_DECL, 0, NULL); if (rc != SEPOL_OK) { goto exit; } mls_level = cil_malloc(sizeof(*mls_level)); mls_level_init(mls_level); rc = mls_level_cpy(mls_level, sepol_level->level); if (rc != SEPOL_OK) { free(mls_level); goto exit; } sepol_alias->level = mls_level; sepol_alias->isalias = 1; return SEPOL_OK; exit: level_datum_destroy(sepol_alias); free(sepol_alias); free(key); return rc; } static 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; } static 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; } static int __cil_insert_type_rule(policydb_t *pdb, uint32_t kind, uint32_t src, uint32_t tgt, uint32_t obj, uint32_t res, struct cil_type_rule *cil_rule, cond_node_t *cond_node, enum cil_flavor cond_flavor) { int rc = SEPOL_OK; avtab_key_t avtab_key; avtab_datum_t avtab_datum = { .data = res, .xperms = NULL }; 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; } existing = avtab_search_node(&pdb->te_avtab, &avtab_key); if (existing) { /* Don't add duplicate type rule and warn if they conflict. * A warning should have been previously given if there is a * non-duplicate rule using the same key. */ if (existing->datum.data != res) { cil_log(CIL_ERR, "Conflicting type rules (scontext=%s tcontext=%s tclass=%s result=%s), existing=%s\n", pdb->p_type_val_to_name[src - 1], pdb->p_type_val_to_name[tgt - 1], pdb->p_class_val_to_name[obj - 1], pdb->p_type_val_to_name[res - 1], pdb->p_type_val_to_name[existing->datum.data - 1]); cil_log(CIL_ERR, "Expanded from type rule (scontext=%s tcontext=%s tclass=%s result=%s)\n", cil_rule->src_str, cil_rule->tgt_str, cil_rule->obj_str, cil_rule->result_str); rc = SEPOL_ERR; } goto exit; } if (!cond_node) { rc = avtab_insert(&pdb->te_avtab, &avtab_key, &avtab_datum); } else { existing = avtab_search_node(&pdb->te_cond_avtab, &avtab_key); if (existing) { cond_av_list_t *this_list; cond_av_list_t *other_list; avtab_datum_t *search_datum; if (cond_flavor == CIL_CONDTRUE) { this_list = cond_node->true_list; other_list = cond_node->false_list; } else { this_list = cond_node->false_list; other_list = cond_node->true_list; } search_datum = cil_cond_av_list_search(&avtab_key, other_list); if (search_datum == NULL) { if (existing->datum.data != res) { cil_log(CIL_ERR, "Conflicting type rules (scontext=%s tcontext=%s tclass=%s result=%s), existing=%s\n", pdb->p_type_val_to_name[src - 1], pdb->p_type_val_to_name[tgt - 1], pdb->p_class_val_to_name[obj - 1], pdb->p_type_val_to_name[res - 1], pdb->p_type_val_to_name[existing->datum.data - 1]); cil_log(CIL_ERR, "Expanded from type rule (scontext=%s tcontext=%s tclass=%s result=%s)\n", cil_rule->src_str, cil_rule->tgt_str, cil_rule->obj_str, cil_rule->result_str); rc = SEPOL_ERR; goto exit; } search_datum = cil_cond_av_list_search(&avtab_key, this_list); if (search_datum) { goto exit; } } } rc = __cil_cond_insert_rule(&pdb->te_cond_avtab, &avtab_key, &avtab_datum, cond_node, cond_flavor); } exit: return rc; } static int __cil_type_rule_to_avtab_helper(policydb_t *pdb, type_datum_t *sepol_src, type_datum_t *sepol_tgt, struct cil_list *class_list, type_datum_t *sepol_result, struct cil_type_rule *cil_rule, cond_node_t *cond_node, enum cil_flavor cond_flavor) { int rc; class_datum_t *sepol_obj = NULL; struct cil_list_item *c; cil_list_for_each(c, class_list) { rc = __cil_get_sepol_class_datum(pdb, DATUM(c->data), &sepol_obj); if (rc != SEPOL_OK) return rc; rc = __cil_insert_type_rule( pdb, cil_rule->rule_kind, sepol_src->s.value, sepol_tgt->s.value, sepol_obj->s.value, sepol_result->s.value, cil_rule, cond_node, cond_flavor ); if (rc != SEPOL_OK) return rc; } return SEPOL_OK; } static 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; struct cil_symtab_datum *src = NULL; struct cil_symtab_datum *tgt = NULL; type_datum_t *sepol_src = NULL; type_datum_t *sepol_tgt = NULL; struct cil_list *class_list = NULL; type_datum_t *sepol_result = NULL; ebitmap_t src_bitmap, tgt_bitmap; ebitmap_node_t *node1, *node2; unsigned int i, j; ebitmap_init(&src_bitmap); ebitmap_init(&tgt_bitmap); src = cil_rule->src; tgt = cil_rule->tgt; rc = __cil_expand_type(src, &src_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; if (tgt->fqn == CIL_KEY_SELF) { ebitmap_for_each_positive_bit(&src_bitmap, node1, i) { rc = __cil_get_sepol_type_datum(pdb, DATUM(db->val_to_type[i]), &sepol_src); if (rc != SEPOL_OK) goto exit; rc = __cil_type_rule_to_avtab_helper( pdb, sepol_src, sepol_src, class_list, sepol_result, cil_rule, cond_node, cond_flavor ); if (rc != SEPOL_OK) goto exit; } } else { rc = __cil_expand_type(tgt, &tgt_bitmap); if (rc != SEPOL_OK) goto exit; ebitmap_for_each_positive_bit(&src_bitmap, node1, i) { rc = __cil_get_sepol_type_datum(pdb, DATUM(db->val_to_type[i]), &sepol_src); if (rc != SEPOL_OK) goto exit; ebitmap_for_each_positive_bit(&tgt_bitmap, node2, j) { rc = __cil_get_sepol_type_datum(pdb, DATUM(db->val_to_type[j]), &sepol_tgt); if (rc != SEPOL_OK) goto exit; rc = __cil_type_rule_to_avtab_helper( pdb, sepol_src, sepol_tgt, class_list, sepol_result, cil_rule, cond_node, cond_flavor ); if (rc != SEPOL_OK) goto exit; } } } rc = SEPOL_OK; exit: ebitmap_destroy(&src_bitmap); ebitmap_destroy(&tgt_bitmap); cil_list_destroy(&class_list, CIL_FALSE); return rc; } int cil_type_rule_to_policydb(policydb_t *pdb, const struct cil_db *db, struct cil_type_rule *cil_rule) { return __cil_type_rule_to_avtab(pdb, db, cil_rule, NULL, CIL_FALSE); } static int __cil_typetransition_to_avtab_helper(policydb_t *pdb, type_datum_t *sepol_src, type_datum_t *sepol_tgt, struct cil_list *class_list, char *name, type_datum_t *sepol_result) { int rc; class_datum_t *sepol_obj = NULL; uint32_t otype; struct cil_list_item *c; cil_list_for_each(c, class_list) { rc = __cil_get_sepol_class_datum(pdb, DATUM(c->data), &sepol_obj); if (rc != SEPOL_OK) return rc; rc = policydb_filetrans_insert( pdb, sepol_src->s.value, sepol_tgt->s.value, sepol_obj->s.value, name, NULL, sepol_result->s.value, &otype ); if (rc != SEPOL_OK) { if (rc == SEPOL_EEXIST) { if (sepol_result->s.value!= 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 (rc != SEPOL_OK) { return rc; } } } return SEPOL_OK; } static 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) { int rc = SEPOL_ERR; struct cil_symtab_datum *src = NULL; struct cil_symtab_datum *tgt = NULL; type_datum_t *sepol_src = NULL; type_datum_t *sepol_tgt = NULL; struct cil_list *class_list = NULL; type_datum_t *sepol_result = NULL; ebitmap_t src_bitmap, tgt_bitmap; ebitmap_node_t *node1, *node2; unsigned int i, j; char *name = DATUM(typetrans->name)->name; if (name == CIL_KEY_STAR) { struct cil_type_rule trans; trans.rule_kind = CIL_TYPE_TRANSITION; trans.src = typetrans->src; trans.tgt = typetrans->tgt; trans.obj = typetrans->obj; trans.result = typetrans->result; trans.src_str = typetrans->src_str; trans.tgt_str = typetrans->tgt_str; trans.obj_str = typetrans->obj_str; trans.result_str = typetrans->result_str; return __cil_type_rule_to_avtab(pdb, db, &trans, cond_node, cond_flavor); } ebitmap_init(&src_bitmap); ebitmap_init(&tgt_bitmap); src = typetrans->src; tgt = typetrans->tgt; rc = __cil_expand_type(src, &src_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; if (tgt->fqn == CIL_KEY_SELF) { ebitmap_for_each_positive_bit(&src_bitmap, node1, i) { rc = __cil_get_sepol_type_datum(pdb, DATUM(db->val_to_type[i]), &sepol_src); if (rc != SEPOL_OK) goto exit; rc = __cil_typetransition_to_avtab_helper( pdb, sepol_src, sepol_src, class_list, name, sepol_result ); if (rc != SEPOL_OK) goto exit; } } else { rc = __cil_expand_type(tgt, &tgt_bitmap); if (rc != SEPOL_OK) goto exit; ebitmap_for_each_positive_bit(&src_bitmap, node1, i) { rc = __cil_get_sepol_type_datum(pdb, DATUM(db->val_to_type[i]), &sepol_src); if (rc != SEPOL_OK) goto exit; ebitmap_for_each_positive_bit(&tgt_bitmap, node2, j) { rc = __cil_get_sepol_type_datum(pdb, DATUM(db->val_to_type[j]), &sepol_tgt); if (rc != SEPOL_OK) goto exit; rc = __cil_typetransition_to_avtab_helper( pdb, sepol_src, sepol_tgt, class_list, name, sepol_result ); 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) { return __cil_typetransition_to_avtab(pdb, db, typetrans, NULL, CIL_FALSE); } static int __perm_str_to_datum(char *perm_str, class_datum_t *sepol_class, uint32_t *datum) { int rc; perm_datum_t *sepol_perm; common_datum_t *sepol_common; sepol_perm = hashtab_search(sepol_class->permissions.table, perm_str); if (sepol_perm == NULL) { sepol_common = sepol_class->comdatum; sepol_perm = hashtab_search(sepol_common->permissions.table, perm_str); if (sepol_perm == NULL) { cil_log(CIL_ERR, "Failed to find datum for perm %s\n", perm_str); rc = SEPOL_ERR; goto exit; } } *datum |= UINT32_C(1) << (sepol_perm->s.value - 1); return SEPOL_OK; exit: return rc; } static int __cil_perms_to_datum(struct cil_list *perms, class_datum_t *sepol_class, uint32_t *datum) { int rc = SEPOL_ERR; char *key = NULL; struct cil_list_item *curr_perm; struct cil_perm *cil_perm; uint32_t data = 0; cil_list_for_each(curr_perm, perms) { cil_perm = curr_perm->data; key = cil_perm->datum.fqn; rc = __perm_str_to_datum(key, sepol_class, &data); if (rc != SEPOL_OK) { goto exit; } } *datum = data; return SEPOL_OK; exit: return rc; } static 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 = { .data = data, .xperms = NULL }; 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) { 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 { rc = __cil_cond_insert_rule(&pdb->te_cond_avtab, &avtab_key, &avtab_datum, cond_node, cond_flavor); } exit: return rc; } static int __cil_avrule_expand_helper(policydb_t *pdb, uint16_t kind, struct cil_symtab_datum *src, struct cil_symtab_datum *tgt, struct cil_classperms *cp, cond_node_t *cond_node, enum cil_flavor cond_flavor) { int rc = SEPOL_ERR; type_datum_t *sepol_src = NULL; type_datum_t *sepol_tgt = NULL; class_datum_t *sepol_class = NULL; uint32_t data = 0; rc = __cil_get_sepol_class_datum(pdb, DATUM(cp->class), &sepol_class); if (rc != SEPOL_OK) goto exit; rc = __cil_perms_to_datum(cp->perms, sepol_class, &data); if (rc != SEPOL_OK) goto exit; if (data == 0) { /* No permissions, so don't insert rule. Maybe should return an error? */ return SEPOL_OK; } if (kind == CIL_AVRULE_DONTAUDIT) { data = ~data; } rc = __cil_get_sepol_type_datum(pdb, src, &sepol_src); if (rc != SEPOL_OK) goto exit; rc = __cil_get_sepol_type_datum(pdb, tgt, &sepol_tgt); if (rc != SEPOL_OK) goto exit; rc = __cil_insert_avrule(pdb, kind, sepol_src->s.value, sepol_tgt->s.value, sepol_class->s.value, data, cond_node, cond_flavor); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: return rc; } static int __cil_avrule_expand(policydb_t *pdb, uint16_t kind, struct cil_symtab_datum *src, struct cil_symtab_datum *tgt, struct cil_list *classperms, cond_node_t *cond_node, enum cil_flavor cond_flavor) { int rc = SEPOL_ERR; struct cil_list_item *curr; cil_list_for_each(curr, classperms) { if (curr->flavor == CIL_CLASSPERMS) { struct cil_classperms *cp = curr->data; if (FLAVOR(cp->class) == CIL_CLASS) { rc = __cil_avrule_expand_helper(pdb, kind, src, tgt, cp, cond_node, cond_flavor); if (rc != SEPOL_OK) { goto exit; } } else { /* MAP */ struct cil_list_item *i = NULL; cil_list_for_each(i, cp->perms) { struct cil_perm *cmp = i->data; rc = __cil_avrule_expand(pdb, kind, src, tgt, cmp->classperms, cond_node, cond_flavor); if (rc != SEPOL_OK) { goto exit; } } } } else { /* SET */ struct cil_classperms_set *cp_set = curr->data; struct cil_classpermission *cp = cp_set->set; rc = __cil_avrule_expand(pdb, kind, src, tgt, cp->classperms, cond_node, cond_flavor); if (rc != SEPOL_OK) { goto exit; } } } return SEPOL_OK; exit: return rc; } static int __cil_should_expand_attribute( const struct cil_db *db, struct cil_symtab_datum *datum) { struct cil_tree_node *node; struct cil_typeattribute *attr; node = NODE(datum); if (node->flavor != CIL_TYPEATTRIBUTE) { return CIL_FALSE; } attr = (struct cil_typeattribute *)datum; return !attr->keep || (ebitmap_cardinality(attr->types) < db->attrs_expand_size); } static int __cil_avrule_to_avtab(policydb_t *pdb, const struct cil_db *db, struct cil_avrule *cil_avrule, cond_node_t *cond_node, enum cil_flavor cond_flavor) { int rc = SEPOL_ERR; uint16_t kind = cil_avrule->rule_kind; struct cil_symtab_datum *src = NULL; struct cil_symtab_datum *tgt = NULL; struct cil_list *classperms = cil_avrule->perms.classperms; ebitmap_t src_bitmap, tgt_bitmap; ebitmap_node_t *snode, *tnode; unsigned int s,t; if (cil_avrule->rule_kind == CIL_AVRULE_DONTAUDIT && db->disable_dontaudit == CIL_TRUE) { // Do not add dontaudit rules to binary rc = SEPOL_OK; goto exit; } src = cil_avrule->src; tgt = cil_avrule->tgt; if (tgt->fqn == CIL_KEY_SELF) { rc = __cil_expand_type(src, &src_bitmap); if (rc != SEPOL_OK) { goto exit; } ebitmap_for_each_positive_bit(&src_bitmap, snode, s) { src = DATUM(db->val_to_type[s]); rc = __cil_avrule_expand(pdb, kind, src, src, classperms, cond_node, cond_flavor); if (rc != SEPOL_OK) { ebitmap_destroy(&src_bitmap); goto exit; } } ebitmap_destroy(&src_bitmap); } else if (tgt->fqn == CIL_KEY_NOTSELF) { rc = __cil_expand_type(src, &src_bitmap); if (rc != SEPOL_OK) { goto exit; } ebitmap_for_each_positive_bit(&src_bitmap, snode, s) { src = DATUM(db->val_to_type[s]); for (t = 0; t < (unsigned int)db->num_types; t++) { if (s != t) { tgt = DATUM(db->val_to_type[t]); rc = __cil_avrule_expand(pdb, kind, src, tgt, classperms, cond_node, cond_flavor); if (rc != SEPOL_OK) { ebitmap_destroy(&src_bitmap); goto exit; } } } } ebitmap_destroy(&src_bitmap); } else if (tgt->fqn == CIL_KEY_OTHER) { rc = __cil_expand_type(src, &src_bitmap); if (rc != SEPOL_OK) { goto exit; } ebitmap_for_each_positive_bit(&src_bitmap, snode, s) { src = DATUM(db->val_to_type[s]); ebitmap_for_each_positive_bit(&src_bitmap, tnode, t) { if (s != t) { tgt = DATUM(db->val_to_type[t]); rc = __cil_avrule_expand(pdb, kind, src, tgt, classperms, cond_node, cond_flavor); if (rc != SEPOL_OK) { ebitmap_destroy(&src_bitmap); goto exit; } } } } ebitmap_destroy(&src_bitmap); } else { int expand_src = __cil_should_expand_attribute(db, src); int expand_tgt = __cil_should_expand_attribute(db, tgt); if (!expand_src && !expand_tgt) { rc = __cil_avrule_expand(pdb, kind, src, tgt, classperms, cond_node, cond_flavor); if (rc != SEPOL_OK) { goto exit; } } else if (expand_src && expand_tgt) { rc = __cil_expand_type(src, &src_bitmap); if (rc != SEPOL_OK) { goto exit; } rc = __cil_expand_type(tgt, &tgt_bitmap); if (rc != SEPOL_OK) { ebitmap_destroy(&src_bitmap); goto exit; } ebitmap_for_each_positive_bit(&src_bitmap, snode, s) { src = DATUM(db->val_to_type[s]); ebitmap_for_each_positive_bit(&tgt_bitmap, tnode, t) { tgt = DATUM(db->val_to_type[t]); rc = __cil_avrule_expand(pdb, kind, src, tgt, classperms, cond_node, cond_flavor); if (rc != SEPOL_OK) { ebitmap_destroy(&src_bitmap); ebitmap_destroy(&tgt_bitmap); goto exit; } } } ebitmap_destroy(&src_bitmap); ebitmap_destroy(&tgt_bitmap); } else if (expand_src) { rc = __cil_expand_type(src, &src_bitmap); if (rc != SEPOL_OK) { goto exit; } ebitmap_for_each_positive_bit(&src_bitmap, snode, s) { src = DATUM(db->val_to_type[s]); rc = __cil_avrule_expand(pdb, kind, src, tgt, classperms, cond_node, cond_flavor); if (rc != SEPOL_OK) { ebitmap_destroy(&src_bitmap); goto exit; } } ebitmap_destroy(&src_bitmap); } else { /* expand_tgt */ rc = __cil_expand_type(tgt, &tgt_bitmap); if (rc != SEPOL_OK) { goto exit; } ebitmap_for_each_positive_bit(&tgt_bitmap, tnode, t) { tgt = DATUM(db->val_to_type[t]); rc = __cil_avrule_expand(pdb, kind, src, tgt, classperms, cond_node, cond_flavor); if (rc != SEPOL_OK) { ebitmap_destroy(&tgt_bitmap); goto exit; } } ebitmap_destroy(&tgt_bitmap); } } return SEPOL_OK; exit: return rc; } int cil_avrule_to_policydb(policydb_t *pdb, const struct cil_db *db, struct cil_avrule *cil_avrule) { return __cil_avrule_to_avtab(pdb, db, cil_avrule, NULL, CIL_FALSE); } // Copied from checkpolicy/policy_define.c /* index of the u32 containing the permission */ #define XPERM_IDX(x) (x >> 5) /* set bits 0 through x-1 within the u32 */ #define XPERM_SETBITS(x) ((UINT32_C(1) << (x & 0x1f)) - 1) /* low value for this u32 */ #define XPERM_LOW(x) (x << 5) /* high value for this u32 */ #define XPERM_HIGH(x) (((x + 1) << 5) - 1) static void __avrule_xperm_setrangebits(uint16_t low, uint16_t high, struct avtab_extended_perms *xperms) { unsigned int i; uint16_t h = high + 1; /* for each u32 that this low-high range touches, set driver permissions */ for (i = XPERM_IDX(low); i <= XPERM_IDX(high); i++) { /* set all bits in u32 */ if ((low <= XPERM_LOW(i)) && (high >= XPERM_HIGH(i))) xperms->perms[i] |= ~0U; /* set low bits */ else if ((low <= XPERM_LOW(i)) && (high < XPERM_HIGH(i))) xperms->perms[i] |= XPERM_SETBITS(h); /* set high bits */ else if ((low > XPERM_LOW(i)) && (high >= XPERM_HIGH(i))) xperms->perms[i] |= ~0U - XPERM_SETBITS(low); /* set middle bits */ else if ((low > XPERM_LOW(i)) && (high <= XPERM_HIGH(i))) xperms->perms[i] |= XPERM_SETBITS(h) - XPERM_SETBITS(low); } } static char* __cil_xperm_kind_to_str(uint32_t xperm_kind) { switch (xperm_kind) { case CIL_PERMX_KIND_IOCTL: return CIL_KEY_IOCTL; case CIL_PERMX_KIND_NLMSG: return CIL_KEY_NLMSG; default: return (char *) "unknown"; } } #define IOC_DRIV(x) (x >> 8) #define IOC_FUNC(x) (x & 0xff) static int __cil_permx_bitmap_to_sepol_xperms_list(uint32_t kind, ebitmap_t *xperms, struct cil_list **xperms_list) { ebitmap_node_t *node; unsigned int i; uint16_t low = 0, high = 0; struct avtab_extended_perms *partial = NULL; struct avtab_extended_perms *complete = NULL; int start_new_range; cil_list_init(xperms_list, CIL_NONE); start_new_range = 1; ebitmap_for_each_positive_bit(xperms, node, i) { if (start_new_range) { low = i; start_new_range = 0; } // continue if the current bit isn't the end of the driver function or the next bit is set if (IOC_FUNC(i) != 0xff && ebitmap_get_bit(xperms, i + 1)) { continue; } // if we got here, i is the end of this range (either because the func // is 0xff or the next bit isn't set). The next time around we are // going to need a start a new range high = i; start_new_range = 1; if (kind == CIL_PERMX_KIND_IOCTL && IOC_FUNC(low) == 0x00 && IOC_FUNC(high) == 0xff) { if (!complete) { complete = cil_calloc(1, sizeof(*complete)); complete->driver = 0x0; complete->specified = AVTAB_XPERMS_IOCTLDRIVER; } __avrule_xperm_setrangebits(IOC_DRIV(low), IOC_DRIV(low), complete); } else { if (partial && partial->driver != IOC_DRIV(low)) { cil_list_append(*xperms_list, CIL_NONE, partial); partial = NULL; } if (!partial) { partial = cil_calloc(1, sizeof(*partial)); partial->driver = IOC_DRIV(low); switch (kind) { case CIL_PERMX_KIND_IOCTL: partial->specified = AVTAB_XPERMS_IOCTLFUNCTION; break; case CIL_PERMX_KIND_NLMSG: partial->specified = AVTAB_XPERMS_NLMSG; break; } } __avrule_xperm_setrangebits(IOC_FUNC(low), IOC_FUNC(high), partial); } } if (partial) { cil_list_append(*xperms_list, CIL_NONE, partial); } if (complete) { cil_list_append(*xperms_list, CIL_NONE, complete); } return SEPOL_OK; } static int __cil_avrulex_xperm_to_policydb(hashtab_key_t k, hashtab_datum_t datum, uint32_t xperm_kind, void *args) { int rc = SEPOL_OK; struct cil_args_booleanif *booleanif_args = args; struct policydb *pdb = booleanif_args->pdb; cond_node_t *cond_node = booleanif_args->cond_node; enum cil_flavor cond_flavor = booleanif_args->cond_flavor; avtab_key_t *avtab_key; avtab_datum_t avtab_datum; struct cil_list *xperms_list = NULL; struct cil_list_item *item; class_datum_t *sepol_obj; uint32_t data = 0; char *kind = NULL; avtab_key = (avtab_key_t *)k; sepol_obj = pdb->class_val_to_struct[avtab_key->target_class - 1]; // setting the data for an extended avtab isn't really necessary because // it is ignored by the kernel. However, neverallow checking requires that // the data value be set, so set it for that to work. kind = __cil_xperm_kind_to_str(xperm_kind); rc = __perm_str_to_datum(kind, sepol_obj, &data); if (rc != SEPOL_OK) { goto exit; } avtab_datum.data = data; rc = __cil_permx_bitmap_to_sepol_xperms_list(xperm_kind, datum, &xperms_list); if (rc != SEPOL_OK) { goto exit; } cil_list_for_each(item, xperms_list) { avtab_datum.xperms = item->data; if (cond_node) { rc = __cil_cond_insert_rule(&pdb->te_cond_avtab, avtab_key, &avtab_datum, cond_node, cond_flavor); } else { rc = avtab_insert(&pdb->te_avtab, avtab_key, &avtab_datum); } if (rc != SEPOL_OK) { goto exit; } } rc = SEPOL_OK; exit: if (xperms_list != NULL) { cil_list_for_each(item, xperms_list) { free(item->data); } cil_list_destroy(&xperms_list, CIL_FALSE); } return rc; } static int __cil_avrulex_ioctl_to_policydb(hashtab_key_t k, hashtab_datum_t datum, void *args) { return __cil_avrulex_xperm_to_policydb(k, datum, CIL_PERMX_KIND_IOCTL, args); } static int __cil_avrulex_nlmsg_to_policydb(hashtab_key_t k, hashtab_datum_t datum, void *args) { return __cil_avrulex_xperm_to_policydb(k, datum, CIL_PERMX_KIND_NLMSG, args); } static int __cil_avrulex_xperm_to_hashtable(hashtab_t h, uint16_t kind, uint32_t src, uint32_t tgt, uint32_t obj, ebitmap_t *xperms) { uint16_t specified; avtab_key_t *avtab_key; ebitmap_t *hashtab_xperms; int rc = SEPOL_ERR; switch (kind) { case CIL_AVRULE_ALLOWED: specified = AVTAB_XPERMS_ALLOWED; break; case CIL_AVRULE_AUDITALLOW: specified = AVTAB_XPERMS_AUDITALLOW; break; case CIL_AVRULE_DONTAUDIT: specified = AVTAB_XPERMS_DONTAUDIT; break; default: rc = SEPOL_ERR; goto exit; } avtab_key = cil_malloc(sizeof(*avtab_key)); avtab_key->source_type = src; avtab_key->target_type = tgt; avtab_key->target_class = obj; avtab_key->specified = specified; hashtab_xperms = (ebitmap_t *)hashtab_search(h, (hashtab_key_t)avtab_key); if (!hashtab_xperms) { hashtab_xperms = cil_malloc(sizeof(*hashtab_xperms)); rc = ebitmap_cpy(hashtab_xperms, xperms); if (rc != SEPOL_OK) { free(hashtab_xperms); free(avtab_key); goto exit; } rc = hashtab_insert(h, (hashtab_key_t)avtab_key, hashtab_xperms); if (rc != SEPOL_OK) { free(hashtab_xperms); free(avtab_key); goto exit; } } else { free(avtab_key); rc = ebitmap_union(hashtab_xperms, xperms); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: return rc; } static int __cil_avrulex_to_hashtable_helper(policydb_t *pdb, uint16_t kind, struct cil_symtab_datum *src, struct cil_symtab_datum *tgt, struct cil_permissionx *permx, struct cil_args_xperm_tables *xt) { int rc = SEPOL_ERR; type_datum_t *sepol_src = NULL; type_datum_t *sepol_tgt = NULL; class_datum_t *sepol_obj = NULL; struct cil_list *class_list = NULL; struct cil_list_item *c; rc = __cil_get_sepol_type_datum(pdb, src, &sepol_src); if (rc != SEPOL_OK) goto exit; rc = __cil_get_sepol_type_datum(pdb, tgt, &sepol_tgt); if (rc != SEPOL_OK) goto exit; class_list = cil_expand_class(permx->obj); cil_list_for_each(c, class_list) { rc = __cil_get_sepol_class_datum(pdb, DATUM(c->data), &sepol_obj); if (rc != SEPOL_OK) goto exit; switch (permx->kind) { case CIL_PERMX_KIND_IOCTL: rc = __cil_avrulex_xperm_to_hashtable(xt->ioctl, kind, sepol_src->s.value, sepol_tgt->s.value, sepol_obj->s.value, permx->perms); if (rc != SEPOL_OK) goto exit; break; case CIL_PERMX_KIND_NLMSG: rc = __cil_avrulex_xperm_to_hashtable(xt->nlmsg, kind, sepol_src->s.value, sepol_tgt->s.value, sepol_obj->s.value, permx->perms); if (rc != SEPOL_OK) goto exit; break; default: rc = SEPOL_ERR; goto exit; } } rc = SEPOL_OK; exit: cil_list_destroy(&class_list, CIL_FALSE); return rc; } static int cil_avrulex_to_hashtable(policydb_t *pdb, const struct cil_db *db, struct cil_avrule *cil_avrulex, struct cil_args_xperm_tables *xt) { int rc = SEPOL_ERR; uint16_t kind; struct cil_symtab_datum *src = NULL; struct cil_symtab_datum *tgt = NULL; ebitmap_t src_bitmap, tgt_bitmap; ebitmap_node_t *snode, *tnode; unsigned int s,t; if (cil_avrulex->rule_kind == CIL_AVRULE_DONTAUDIT && db->disable_dontaudit == CIL_TRUE) { // Do not add dontaudit rules to binary rc = SEPOL_OK; goto exit; } kind = cil_avrulex->rule_kind; src = cil_avrulex->src; tgt = cil_avrulex->tgt; if (tgt->fqn == CIL_KEY_SELF) { rc = __cil_expand_type(src, &src_bitmap); if (rc != SEPOL_OK) goto exit; ebitmap_for_each_positive_bit(&src_bitmap, snode, s) { src = DATUM(db->val_to_type[s]); rc = __cil_avrulex_to_hashtable_helper(pdb, kind, src, src, cil_avrulex->perms.x.permx, xt); if (rc != SEPOL_OK) { ebitmap_destroy(&src_bitmap); goto exit; } } ebitmap_destroy(&src_bitmap); } else if (tgt->fqn == CIL_KEY_NOTSELF) { rc = __cil_expand_type(src, &src_bitmap); if (rc != SEPOL_OK) { goto exit; } ebitmap_for_each_positive_bit(&src_bitmap, snode, s) { src = DATUM(db->val_to_type[s]); for (t = 0; t < (unsigned int)db->num_types; t++) { if (s != t) { tgt = DATUM(db->val_to_type[t]); rc = __cil_avrulex_to_hashtable_helper(pdb, kind, src, tgt, cil_avrulex->perms.x.permx, xt); if (rc != SEPOL_OK) { ebitmap_destroy(&src_bitmap); goto exit; } } } } ebitmap_destroy(&src_bitmap); } else if (tgt->fqn == CIL_KEY_OTHER) { rc = __cil_expand_type(src, &src_bitmap); if (rc != SEPOL_OK) { goto exit; } ebitmap_for_each_positive_bit(&src_bitmap, snode, s) { src = DATUM(db->val_to_type[s]); ebitmap_for_each_positive_bit(&src_bitmap, tnode, t) { if (s != t) { tgt = DATUM(db->val_to_type[t]); rc = __cil_avrulex_to_hashtable_helper(pdb, kind, src, tgt, cil_avrulex->perms.x.permx, xt); if (rc != SEPOL_OK) { ebitmap_destroy(&src_bitmap); goto exit; } } } } ebitmap_destroy(&src_bitmap); } else { int expand_src = __cil_should_expand_attribute(db, src); int expand_tgt = __cil_should_expand_attribute(db, tgt); if (!expand_src && !expand_tgt) { rc = __cil_avrulex_to_hashtable_helper(pdb, kind, src, tgt, cil_avrulex->perms.x.permx, xt); if (rc != SEPOL_OK) { goto exit; } } else if (expand_src && expand_tgt) { rc = __cil_expand_type(src, &src_bitmap); if (rc != SEPOL_OK) { goto exit; } rc = __cil_expand_type(tgt, &tgt_bitmap); if (rc != SEPOL_OK) { ebitmap_destroy(&src_bitmap); goto exit; } ebitmap_for_each_positive_bit(&src_bitmap, snode, s) { src = DATUM(db->val_to_type[s]); ebitmap_for_each_positive_bit(&tgt_bitmap, tnode, t) { tgt = DATUM(db->val_to_type[t]); rc = __cil_avrulex_to_hashtable_helper(pdb, kind, src, tgt, cil_avrulex->perms.x.permx, xt); if (rc != SEPOL_OK) { ebitmap_destroy(&src_bitmap); ebitmap_destroy(&tgt_bitmap); goto exit; } } } ebitmap_destroy(&src_bitmap); ebitmap_destroy(&tgt_bitmap); } else if (expand_src) { rc = __cil_expand_type(src, &src_bitmap); if (rc != SEPOL_OK) { goto exit; } ebitmap_for_each_positive_bit(&src_bitmap, snode, s) { src = DATUM(db->val_to_type[s]); rc = __cil_avrulex_to_hashtable_helper(pdb, kind, src, tgt, cil_avrulex->perms.x.permx, xt); if (rc != SEPOL_OK) { ebitmap_destroy(&src_bitmap); goto exit; } } ebitmap_destroy(&src_bitmap); } else { /* expand_tgt */ rc = __cil_expand_type(tgt, &tgt_bitmap); if (rc != SEPOL_OK) { goto exit; } ebitmap_for_each_positive_bit(&tgt_bitmap, tnode, t) { tgt = DATUM(db->val_to_type[t]); rc = __cil_avrulex_to_hashtable_helper(pdb, kind, src, tgt, cil_avrulex->perms.x.permx, xt); if (rc != SEPOL_OK) { ebitmap_destroy(&tgt_bitmap); goto exit; } } ebitmap_destroy(&tgt_bitmap); } } return SEPOL_OK; exit: return rc; } static int __cil_avrulex_xperm_destroy(hashtab_key_t k, hashtab_datum_t datum, __attribute__((unused)) void *args) { free(k); ebitmap_destroy(datum); free(datum); return SEPOL_OK; } static 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; flavor = node->flavor; switch (flavor) { case CIL_NAMETYPETRANSITION: cil_typetrans = (struct cil_nametypetransition*)node->data; if (DATUM(cil_typetrans->name)->fqn != CIL_KEY_STAR) { cil_log(CIL_ERR, "typetransition with file name not allowed within a booleanif block.\n"); cil_tree_log(node, CIL_ERR,"Invalid typetransition statement"); goto exit; } rc = __cil_typetransition_to_avtab(pdb, db, cil_typetrans, cond_node, cond_flavor); if (rc != SEPOL_OK) { cil_tree_log(node, CIL_ERR, "Failed to insert type transition into avtab"); goto exit; } break; case CIL_TYPE_RULE: cil_type_rule = node->data; rc = __cil_type_rule_to_avtab(pdb, db, cil_type_rule, cond_node, cond_flavor); if (rc != SEPOL_OK) { cil_tree_log(node, CIL_ERR, "Failed to insert typerule into avtab"); goto exit; } break; case CIL_AVRULE: cil_avrule = node->data; rc = __cil_avrule_to_avtab(pdb, db, cil_avrule, cond_node, cond_flavor); if (rc != SEPOL_OK) { cil_tree_log(node, CIL_ERR, "Failed to insert avrule into avtab"); goto exit; } break; case CIL_AVRULEX: if (db->policy_version < POLICYDB_VERSION_COND_XPERMS) { cil_tree_log(node, CIL_ERR, "Extended permission rules are not supported in policy version %d\n", db->policy_version); rc = SEPOL_ERR; goto exit; } cil_avrule = node->data; rc = cil_avrulex_to_hashtable(pdb, db, cil_avrule, &args->avrulex_xperm_tables); if (rc != SEPOL_OK) { cil_tree_log(node, CIL_ERR, "Failed to insert avrulex into avtab"); goto exit; } break; case CIL_CALL: case CIL_TUNABLEIF: break; default: cil_tree_log(node, CIL_ERR, "Invalid statement within booleanif"); goto exit; } return SEPOL_OK; exit: return SEPOL_ERR; } static void __cil_expr_to_string(struct cil_list *expr, enum cil_flavor flavor, char **out); static void __cil_expr_to_string_helper(struct cil_list_item *curr, enum cil_flavor flavor, char **out) { char *c; if (curr->flavor == CIL_DATUM) { *out = cil_strdup(DATUM(curr->data)->fqn); } else if (curr->flavor == CIL_LIST) { __cil_expr_to_string(curr->data, flavor, &c); cil_asprintf(out, "(%s)", c); free(c); } else if (flavor == CIL_PERMISSIONX) { // permissionx expressions aren't resolved into anything, so curr->flavor // is just a CIL_STRING, not a CIL_DATUM, so just check on flavor for those *out = cil_strdup(curr->data); } } static void __cil_expr_to_string(struct cil_list *expr, enum cil_flavor flavor, char **out) { struct cil_list_item *curr; char *s1 = NULL; char *s2 = NULL; enum cil_flavor op; if (expr == NULL || expr->head == NULL) { *out = cil_strdup(""); return; } curr = expr->head; if (curr->flavor == CIL_OP) { op = (enum cil_flavor)(uintptr_t)curr->data; if (op == CIL_ALL) { *out = cil_strdup(CIL_KEY_ALL); } else if (op == CIL_RANGE) { __cil_expr_to_string_helper(curr->next, flavor, &s1); __cil_expr_to_string_helper(curr->next->next, flavor, &s2); cil_asprintf(out, "%s %s %s", CIL_KEY_RANGE, s1, s2); free(s1); free(s2); } else { __cil_expr_to_string_helper(curr->next, flavor, &s1); if (op == CIL_NOT) { cil_asprintf(out, "%s %s", CIL_KEY_NOT, s1); free(s1); } else { const char *opstr = ""; __cil_expr_to_string_helper(curr->next->next, flavor, &s2); if (op == CIL_OR) { opstr = CIL_KEY_OR; } else if (op == CIL_AND) { opstr = CIL_KEY_AND; } else if (op == CIL_XOR) { opstr = CIL_KEY_XOR; } cil_asprintf(out, "%s %s %s", opstr, s1, s2); free(s1); free(s2); } } } else { char *c1 = NULL; char *c2 = NULL; __cil_expr_to_string_helper(curr, flavor, &c1); for (curr = curr->next; curr; curr = curr->next) { s1 = NULL; __cil_expr_to_string_helper(curr, flavor, &s1); cil_asprintf(&c2, "%s %s", c1, s1); free(c1); free(s1); c1 = c2; } *out = c1; } } static int __cil_cond_expr_to_sepol_expr_helper(policydb_t *pdb, struct cil_list *cil_expr, cond_expr_t **head, cond_expr_t **tail); static int __cil_cond_item_to_sepol_expr(policydb_t *pdb, struct cil_list_item *item, cond_expr_t **head, cond_expr_t **tail) { if (item == NULL) { goto exit; } else if (item->flavor == CIL_DATUM) { char *key = DATUM(item->data)->fqn; cond_bool_datum_t *sepol_bool = hashtab_search(pdb->p_bools.table, key); if (sepol_bool == NULL) { cil_log(CIL_INFO, "Failed to find boolean\n"); goto exit; } *head = cil_malloc(sizeof(cond_expr_t)); (*head)->next = NULL; (*head)->expr_type = COND_BOOL; (*head)->boolean = 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)(uintptr_t)item->data; op = cil_malloc(sizeof(*op)); op->boolean = 0; op->next = NULL; switch (cil_op) { case CIL_NOT: op->expr_type = COND_NOT; break; case CIL_OR: op->expr_type = COND_OR; break; case CIL_AND: op->expr_type = COND_AND; break; case CIL_XOR: op->expr_type = COND_XOR; break; case CIL_EQ: op->expr_type = COND_EQ; break; case CIL_NEQ: op->expr_type = COND_NEQ; break; default: free(op); goto exit; } rc = __cil_cond_item_to_sepol_expr(pdb, item->next, &h1, &t1); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "Failed to get first operand of conditional expression\n"); free(op); goto exit; } if (cil_op == CIL_NOT) { *head = h1; t1->next = op; *tail = op; } else { rc = __cil_cond_item_to_sepol_expr(pdb, item->next->next, &h2, &t2); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "Failed to get second operand of conditional expression\n"); free(op); cond_expr_destroy(h1); goto exit; } *head = h1; t1->next = h2; t2->next = op; *tail = op; } } else { rc = __cil_cond_item_to_sepol_expr(pdb, item, &h1, &t1); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "Failed to get initial item in conditional list\n"); goto exit; } *head = h1; for (item = item->next; item; item = item->next) { rc = __cil_cond_item_to_sepol_expr(pdb, item, &h2, &t2); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "Failed to get item in conditional list\n"); cond_expr_destroy(*head); goto exit; } op = cil_malloc(sizeof(*op)); op->boolean = 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; } static int __cil_validate_cond_expr(cond_expr_t *cond_expr) { cond_expr_t *e; int depth = -1; for (e = cond_expr; e != NULL; e = e->next) { switch (e->expr_type) { case COND_BOOL: if (depth == (COND_EXPR_MAXDEPTH - 1)) { cil_log(CIL_ERR,"Conditional expression exceeded max allowable depth\n"); return SEPOL_ERR; } depth++; break; case COND_NOT: if (depth < 0) { cil_log(CIL_ERR,"Invalid conditional expression\n"); return SEPOL_ERR; } break; case COND_OR: case COND_AND: case COND_XOR: case COND_EQ: case COND_NEQ: if (depth < 1) { cil_log(CIL_ERR,"Invalid conditional expression\n"); return SEPOL_ERR; } depth--; break; default: cil_log(CIL_ERR,"Invalid conditional expression\n"); return SEPOL_ERR; } } if (depth != 0) { cil_log(CIL_ERR,"Invalid conditional expression\n"); return SEPOL_ERR; } return SEPOL_OK; } int cil_booleanif_to_policydb(policydb_t *pdb, const struct cil_db *db, struct cil_tree_node *node) { 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; 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; hashtab_t avrulex_ioctl_table = NULL; hashtab_t avrulex_nlmsg_table = NULL; tmp_cond = cond_node_create(pdb, NULL); if (tmp_cond == NULL) { rc = SEPOL_ERR; cil_tree_log(node, CIL_INFO, "Failed to create sepol conditional node"); goto exit; } rc = __cil_cond_expr_to_sepol_expr(pdb, cil_boolif->datum_expr, &tmp_cond->expr); if (rc != SEPOL_OK) { cil_tree_log(node, CIL_INFO, "Failed to convert CIL conditional expression to sepol expression"); goto exit; } rc = __cil_validate_cond_expr(tmp_cond->expr); if (rc != SEPOL_OK) { goto exit; } tmp_cond->true_list = &tmp_cl; rc = cond_normalize_expr(pdb, tmp_cond); if (rc != SEPOL_OK) { goto exit; } if (tmp_cond->false_list != NULL) { tmp_cond->true_list = NULL; swapped = CIL_TRUE; } cond_node = cond_node_find(pdb, tmp_cond, pdb->cond_list, &was_created); if (cond_node == NULL) { rc = SEPOL_ERR; goto exit; } if (was_created) { cond_node->next = pdb->cond_list; pdb->cond_list = cond_node; } cond_expr_destroy(tmp_cond->expr); free(tmp_cond); tmp_cond = NULL; for (cb_node = node->cl_head; cb_node != NULL; cb_node = cb_node->next) { if (cb_node->flavor == CIL_CONDBLOCK) { struct cil_condblock *cb = cb_node->data; if (cb->flavor == CIL_CONDTRUE) { true_node = cb_node; } else if (cb->flavor == CIL_CONDFALSE) { false_node = cb_node; } } } if (swapped) { tmp_node = true_node; true_node = false_node; false_node = tmp_node; } bool_args.db = db; bool_args.pdb = pdb; bool_args.cond_node = cond_node; if (true_node != NULL) { avrulex_ioctl_table = hashtab_create(avrulex_hash, avrulex_compare, AVRULEX_TABLE_SIZE); if (!avrulex_ioctl_table) { cil_log(CIL_INFO, "Failure to create hashtab for avrulex\n"); goto exit; } avrulex_nlmsg_table = hashtab_create(avrulex_hash, avrulex_compare, AVRULEX_TABLE_SIZE); if (!avrulex_nlmsg_table) { cil_log(CIL_INFO, "Failure to create hashtab for avrulex\n"); goto exit; } bool_args.cond_flavor = CIL_CONDTRUE; bool_args.avrulex_xperm_tables.ioctl = avrulex_ioctl_table; bool_args.avrulex_xperm_tables.nlmsg = avrulex_nlmsg_table; rc = cil_tree_walk(true_node, __cil_cond_to_policydb_helper, NULL, NULL, &bool_args); if (rc != SEPOL_OK) { cil_tree_log(true_node, CIL_ERR, "Failure while walking true conditional block"); goto exit; } rc = hashtab_map(avrulex_ioctl_table, __cil_avrulex_ioctl_to_policydb, &bool_args); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "Failure creating avrulex rules\n"); goto exit; } rc = hashtab_map(avrulex_nlmsg_table, __cil_avrulex_nlmsg_to_policydb, &bool_args); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "Failure creating avrulex rules\n"); goto exit; } hashtab_map(avrulex_nlmsg_table, __cil_avrulex_xperm_destroy, NULL); hashtab_destroy(avrulex_nlmsg_table); avrulex_nlmsg_table = NULL; hashtab_map(avrulex_ioctl_table, __cil_avrulex_xperm_destroy, NULL); hashtab_destroy(avrulex_ioctl_table); avrulex_ioctl_table = NULL; } if (false_node != NULL) { avrulex_ioctl_table = hashtab_create(avrulex_hash, avrulex_compare, AVRULEX_TABLE_SIZE); if (!avrulex_ioctl_table) { cil_log(CIL_INFO, "Failure to create hashtab for avrulex\n"); goto exit; } avrulex_nlmsg_table = hashtab_create(avrulex_hash, avrulex_compare, AVRULEX_TABLE_SIZE); if (!avrulex_nlmsg_table) { cil_log(CIL_INFO, "Failure to create hashtab for avrulex\n"); goto exit; } bool_args.cond_flavor = CIL_CONDFALSE; bool_args.avrulex_xperm_tables.ioctl = avrulex_ioctl_table; bool_args.avrulex_xperm_tables.nlmsg = avrulex_nlmsg_table; rc = cil_tree_walk(false_node, __cil_cond_to_policydb_helper, NULL, NULL, &bool_args); if (rc != SEPOL_OK) { cil_tree_log(false_node, CIL_ERR, "Failure while walking false conditional block"); goto exit; } rc = hashtab_map(avrulex_ioctl_table, __cil_avrulex_ioctl_to_policydb, &bool_args); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "Failure creating avrulex rules\n"); goto exit; } rc = hashtab_map(avrulex_nlmsg_table, __cil_avrulex_nlmsg_to_policydb, &bool_args); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "Failure creating avrulex rules\n"); goto exit; } hashtab_map(avrulex_nlmsg_table, __cil_avrulex_xperm_destroy, NULL); hashtab_destroy(avrulex_nlmsg_table); avrulex_nlmsg_table = NULL; hashtab_map(avrulex_ioctl_table, __cil_avrulex_xperm_destroy, NULL); hashtab_destroy(avrulex_ioctl_table); avrulex_ioctl_table = NULL; } return SEPOL_OK; exit: hashtab_map(avrulex_nlmsg_table, __cil_avrulex_xperm_destroy, NULL); hashtab_destroy(avrulex_nlmsg_table); hashtab_map(avrulex_ioctl_table, __cil_avrulex_xperm_destroy, NULL); hashtab_destroy(avrulex_ioctl_table); if (tmp_cond) { if (tmp_cond->expr) cond_expr_destroy(tmp_cond->expr); free(tmp_cond); } return rc; } int cil_roletrans_to_policydb(policydb_t *pdb, const struct cil_db *db, struct cil_roletransition *roletrans, hashtab_t role_trans_table) { int rc = SEPOL_ERR; role_datum_t *sepol_src = NULL; type_datum_t *sepol_tgt = NULL; class_datum_t *sepol_obj = NULL; struct cil_list *class_list = NULL; 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_positive_bit(&role_bitmap, rnode, i) { rc = __cil_get_sepol_role_datum(pdb, DATUM(db->val_to_role[i]), &sepol_src); if (rc != SEPOL_OK) goto exit; ebitmap_for_each_positive_bit(&type_bitmap, tnode, j) { rc = __cil_get_sepol_type_datum(pdb, DATUM(db->val_to_type[j]), &sepol_tgt); if (rc != SEPOL_OK) goto exit; cil_list_for_each(c, class_list) { int add = CIL_TRUE; rc = __cil_get_sepol_class_datum(pdb, DATUM(c->data), &sepol_obj); if (rc != SEPOL_OK) goto exit; new = cil_malloc(sizeof(*new)); memset(new, 0, sizeof(*new)); new->role = sepol_src->s.value; new->type = sepol_tgt->s.value; new->tclass = sepol_obj->s.value; new->new_role = sepol_result->s.value; rc = hashtab_insert(role_trans_table, (hashtab_key_t)new, &(new->new_role)); if (rc != SEPOL_OK) { if (rc == SEPOL_EEXIST) { add = CIL_FALSE; new_role = hashtab_search(role_trans_table, (hashtab_key_t)new); if (new->new_role != *new_role) { cil_log(CIL_ERR, "Conflicting role transition rules\n"); } else { rc = SEPOL_OK; } } else { cil_log(CIL_ERR, "Out of memory\n"); } } if (add == CIL_TRUE) { new->next = pdb->role_tr; pdb->role_tr = new; } else { free(new); if (rc != SEPOL_OK) { goto exit; } } } } } rc = SEPOL_OK; exit: ebitmap_destroy(&role_bitmap); ebitmap_destroy(&type_bitmap); cil_list_destroy(&class_list, CIL_FALSE); return rc; } int cil_roleallow_to_policydb(policydb_t *pdb, const struct cil_db *db, struct cil_roleallow *roleallow) { int rc = SEPOL_ERR; role_datum_t *sepol_src = NULL; role_datum_t *sepol_tgt = NULL; role_allow_t *sepol_roleallow = NULL; ebitmap_t src_bitmap, tgt_bitmap; ebitmap_node_t *node1, *node2; unsigned int i, j; rc = __cil_expand_role(roleallow->src, &src_bitmap); if (rc != SEPOL_OK) goto exit; rc = __cil_expand_role(roleallow->tgt, &tgt_bitmap); if (rc != SEPOL_OK) goto exit; ebitmap_for_each_positive_bit(&src_bitmap, node1, i) { rc = __cil_get_sepol_role_datum(pdb, DATUM(db->val_to_role[i]), &sepol_src); if (rc != SEPOL_OK) goto exit; ebitmap_for_each_positive_bit(&tgt_bitmap, node2, j) { 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; } static int __cil_constrain_expr_datum_to_sepol_expr(policydb_t *pdb, const struct cil_db *db, struct cil_list_item *item, enum cil_flavor expr_flavor, constraint_expr_t *expr) { int rc = SEPOL_ERR; if (expr_flavor == CIL_USER) { user_datum_t *sepol_user = NULL; ebitmap_t user_bitmap; ebitmap_node_t *unode; unsigned int i; rc = __cil_expand_user(item->data, &user_bitmap); if (rc != SEPOL_OK) goto exit; ebitmap_for_each_positive_bit(&user_bitmap, unode, i) { rc = __cil_get_sepol_user_datum(pdb, DATUM(db->val_to_user[i]), &sepol_user); if (rc != SEPOL_OK) { ebitmap_destroy(&user_bitmap); goto exit; } if (ebitmap_set_bit(&expr->names, sepol_user->s.value - 1, 1)) { ebitmap_destroy(&user_bitmap); goto exit; } } ebitmap_destroy(&user_bitmap); } else if (expr_flavor == CIL_ROLE) { role_datum_t *sepol_role = NULL; ebitmap_t role_bitmap; ebitmap_node_t *rnode; unsigned int i; rc = __cil_expand_role(item->data, &role_bitmap); if (rc != SEPOL_OK) goto exit; ebitmap_for_each_positive_bit(&role_bitmap, rnode, i) { rc = __cil_get_sepol_role_datum(pdb, DATUM(db->val_to_role[i]), &sepol_role); if (rc != SEPOL_OK) { ebitmap_destroy(&role_bitmap); goto exit; } if (ebitmap_set_bit(&expr->names, sepol_role->s.value - 1, 1)) { ebitmap_destroy(&role_bitmap); goto exit; } } ebitmap_destroy(&role_bitmap); } else if (expr_flavor == CIL_TYPE) { type_datum_t *sepol_type = NULL; ebitmap_t type_bitmap; ebitmap_node_t *tnode; unsigned int i; if (pdb->policyvers >= POLICYDB_VERSION_CONSTRAINT_NAMES) { rc = __cil_get_sepol_type_datum(pdb, item->data, &sepol_type); if (rc != SEPOL_OK) { if (FLAVOR(item->data) == CIL_TYPEATTRIBUTE) { struct cil_typeattribute *attr = item->data; if (!attr->keep) { rc = 0; } } } if (sepol_type) { rc = ebitmap_set_bit(&expr->type_names->types, sepol_type->s.value - 1, 1); } if (rc != SEPOL_OK) { goto exit; } } rc = __cil_expand_type(item->data, &type_bitmap); if (rc != SEPOL_OK) goto exit; ebitmap_for_each_positive_bit(&type_bitmap, tnode, i) { 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; } static 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)(uintptr_t)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)(uintptr_t)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)(uintptr_t)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; } static 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; enum cil_flavor cil_op; 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; } cil_op = (enum cil_flavor)(uintptr_t)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; } static 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; } static int __cil_validate_constrain_expr(constraint_expr_t *sepol_expr) { constraint_expr_t *e; int depth = -1; for (e = sepol_expr; e != NULL; e = e->next) { switch (e->expr_type) { case CEXPR_NOT: if (depth < 0) { cil_log(CIL_ERR,"Invalid constraint expression\n"); return SEPOL_ERR; } break; case CEXPR_AND: case CEXPR_OR: if (depth < 1) { cil_log(CIL_ERR,"Invalid constraint expression\n"); return SEPOL_ERR; } depth--; break; case CEXPR_ATTR: case CEXPR_NAMES: if (depth == (CEXPR_MAXDEPTH - 1)) { cil_log(CIL_ERR,"Constraint expression exceeded max allowable depth\n"); return SEPOL_ERR; } depth++; break; default: cil_log(CIL_ERR,"Invalid constraint expression\n"); return SEPOL_ERR; } } if (depth != 0) { cil_log(CIL_ERR,"Invalid constraint expression\n"); return SEPOL_ERR; } return SEPOL_OK; } static 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; } if (sepol_constrain->permissions == 0) { /* No permissions, so don't insert rule. */ free(sepol_constrain); return SEPOL_OK; } rc = __cil_constrain_expr_to_sepol_expr(pdb, db, expr, &sepol_expr); if (rc != SEPOL_OK) { goto exit; } rc = __cil_validate_constrain_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: constraint_expr_destroy(sepol_expr); free(sepol_constrain); return rc; } static 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; } static 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; } static 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 = NODE(i->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; } } } 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; } static 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; } static 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; } static 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; } static 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; /* even if no context, we must preserve initial SID values */ count++; if (cil_context != NULL) { ocontext_t *new_ocon = cil_add_ocontext(&pdb->ocontexts[OCON_ISID], &tail); new_ocon->sid[0] = count; new_ocon->u.name = cil_strdup(cil_sid->datum.fqn); rc = __cil_context_to_sepol_context(pdb, cil_context, &new_ocon->context[0]); if (rc != SEPOL_OK) { cil_log(CIL_ERR,"Problem with context for SID %s\n",cil_sid->datum.fqn); goto exit; } } } return SEPOL_OK; exit: return rc; } int cil_rangetransition_to_policydb(policydb_t *pdb, const struct cil_db *db, struct cil_rangetransition *rangetrans) { 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 = NULL; range_trans_t *newkey = NULL; struct mls_range *newdatum = NULL; ebitmap_t src_bitmap, tgt_bitmap; ebitmap_node_t *node1, *node2; unsigned int i, j; struct cil_list_item *c; struct mls_range *o_range = NULL; rc = __cil_expand_type(rangetrans->src, &src_bitmap); if (rc != SEPOL_OK) goto exit; rc = __cil_expand_type(rangetrans->exec, &tgt_bitmap); if (rc != SEPOL_OK) goto exit; class_list = cil_expand_class(rangetrans->obj); ebitmap_for_each_positive_bit(&src_bitmap, node1, i) { rc = __cil_get_sepol_type_datum(pdb, DATUM(db->val_to_type[i]), &sepol_src); if (rc != SEPOL_OK) goto exit; ebitmap_for_each_positive_bit(&tgt_bitmap, node2, j) { 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_class); if (rc != SEPOL_OK) goto exit; newkey = cil_calloc(1, sizeof(*newkey)); newdatum = cil_calloc(1, sizeof(*newdatum)); newkey->source_type = sepol_src->s.value; newkey->target_type = sepol_tgt->s.value; newkey->target_class = sepol_class->s.value; rc = __cil_levelrange_to_mls_range(pdb, rangetrans->range, newdatum); if (rc != SEPOL_OK) { free(newkey); free(newdatum); goto exit; } rc = hashtab_insert(pdb->range_tr, (hashtab_key_t)newkey, newdatum); if (rc != SEPOL_OK) { if (rc == SEPOL_EEXIST) { o_range = hashtab_search(pdb->range_tr, (hashtab_key_t)newkey); if (!mls_range_eq(newdatum, o_range)) { cil_log(CIL_ERR, "Conflicting Range transition rules\n"); } else { rc = SEPOL_OK; } } else { cil_log(CIL_ERR, "Out of memory\n"); } // TODO: add upper version bound once fixed in upstream GCC #if defined(__GNUC__) && (__GNUC__ >= 12) # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Warray-bounds" # pragma GCC diagnostic ignored "-Wstringop-overflow" #endif mls_range_destroy(newdatum); #if defined(__GNUC__) && (__GNUC__ >= 12) # pragma GCC diagnostic pop #endif free(newdatum); free(newkey); if (rc != SEPOL_OK) { goto exit; } } } } } rc = SEPOL_OK; exit: ebitmap_destroy(&src_bitmap); ebitmap_destroy(&tgt_bitmap); cil_list_destroy(&class_list, CIL_FALSE); return rc; } int cil_ibpkeycon_to_policydb(policydb_t *pdb, struct cil_sort *ibpkeycons) { int rc = SEPOL_ERR; uint32_t i = 0; ocontext_t *tail = NULL; struct in6_addr subnet_prefix; for (i = 0; i < ibpkeycons->count; i++) { struct cil_ibpkeycon *cil_ibpkeycon = ibpkeycons->array[i]; ocontext_t *new_ocon = cil_add_ocontext(&pdb->ocontexts[OCON_IBPKEY], &tail); rc = inet_pton(AF_INET6, cil_ibpkeycon->subnet_prefix_str, &subnet_prefix); if (rc != 1) { cil_log(CIL_ERR, "ibpkeycon subnet prefix not in valid IPV6 format\n"); rc = SEPOL_ERR; goto exit; } memcpy(&new_ocon->u.ibpkey.subnet_prefix, &subnet_prefix.s6_addr[0], sizeof(new_ocon->u.ibpkey.subnet_prefix)); new_ocon->u.ibpkey.low_pkey = cil_ibpkeycon->pkey_low; new_ocon->u.ibpkey.high_pkey = cil_ibpkeycon->pkey_high; rc = __cil_context_to_sepol_context(pdb, cil_ibpkeycon->context, &new_ocon->context[0]); if (rc != SEPOL_OK) goto exit; } return SEPOL_OK; exit: return rc; } int cil_portcon_to_policydb(policydb_t *pdb, struct cil_sort *portcons) { int rc = SEPOL_ERR; uint32_t i = 0; ocontext_t *tail = NULL; for (i = 0; i < portcons->count; i++) { struct cil_portcon *cil_portcon = portcons->array[i]; ocontext_t *new_ocon = cil_add_ocontext(&pdb->ocontexts[OCON_PORT], &tail); switch (cil_portcon->proto) { case CIL_PROTOCOL_UDP: new_ocon->u.port.protocol = IPPROTO_UDP; break; case CIL_PROTOCOL_TCP: new_ocon->u.port.protocol = IPPROTO_TCP; break; case CIL_PROTOCOL_DCCP: new_ocon->u.port.protocol = IPPROTO_DCCP; break; case CIL_PROTOCOL_SCTP: new_ocon->u.port.protocol = IPPROTO_SCTP; break; default: /* should not get here */ rc = SEPOL_ERR; goto exit; } new_ocon->u.port.low_port = cil_portcon->port_low; new_ocon->u.port.high_port = cil_portcon->port_high; rc = __cil_context_to_sepol_context(pdb, cil_portcon->context, &new_ocon->context[0]); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: return rc; } int cil_netifcon_to_policydb(policydb_t *pdb, struct cil_sort *netifcons) { int rc = SEPOL_ERR; uint32_t i = 0; ocontext_t *tail = NULL; for (i = 0; i < netifcons->count; i++) { ocontext_t *new_ocon = cil_add_ocontext(&pdb->ocontexts[OCON_NETIF], &tail); struct cil_netifcon *cil_netifcon = netifcons->array[i]; new_ocon->u.name = cil_strdup(cil_netifcon->interface_str); rc = __cil_context_to_sepol_context(pdb, cil_netifcon->if_context, &new_ocon->context[0]); if (rc != SEPOL_OK) { goto exit; } rc = __cil_context_to_sepol_context(pdb, cil_netifcon->packet_context, &new_ocon->context[1]); if (rc != SEPOL_OK) { context_destroy(&new_ocon->context[0]); goto exit; } } return SEPOL_OK; exit: return rc; } int cil_ibendportcon_to_policydb(policydb_t *pdb, struct cil_sort *ibendportcons) { int rc = SEPOL_ERR; uint32_t i; ocontext_t *tail = NULL; for (i = 0; i < ibendportcons->count; i++) { ocontext_t *new_ocon = cil_add_ocontext(&pdb->ocontexts[OCON_IBENDPORT], &tail); struct cil_ibendportcon *cil_ibendportcon = ibendportcons->array[i]; new_ocon->u.ibendport.dev_name = cil_strdup(cil_ibendportcon->dev_name_str); new_ocon->u.ibendport.port = cil_ibendportcon->port; rc = __cil_context_to_sepol_context(pdb, cil_ibendportcon->context, &new_ocon->context[0]); if (rc != SEPOL_OK) goto exit; } return SEPOL_OK; exit: return rc; } int cil_nodecon_to_policydb(policydb_t *pdb, struct cil_sort *nodecons) { int rc = SEPOL_ERR; uint32_t i = 0; ocontext_t *tail = NULL; ocontext_t *tail6 = NULL; for (i = 0; i < nodecons->count; i++) { ocontext_t *new_ocon = NULL; struct cil_nodecon *cil_nodecon = nodecons->array[i]; if (cil_nodecon->addr->family == AF_INET) { new_ocon = cil_add_ocontext(&pdb->ocontexts[OCON_NODE], &tail); new_ocon->u.node.addr = cil_nodecon->addr->ip.v4.s_addr; new_ocon->u.node.mask = cil_nodecon->mask->ip.v4.s_addr; } else if (cil_nodecon->addr->family == AF_INET6) { new_ocon = cil_add_ocontext(&pdb->ocontexts[OCON_NODE6], &tail6); memcpy(new_ocon->u.node6.addr, &cil_nodecon->addr->ip.v6.s6_addr[0], 16); memcpy(new_ocon->u.node6.mask, &cil_nodecon->mask->ip.v6.s6_addr[0], 16); } else { /* should not get here */ rc = SEPOL_ERR; goto exit; } rc = __cil_context_to_sepol_context(pdb, cil_nodecon->context, &new_ocon->context[0]); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: return rc; } int cil_fsuse_to_policydb(policydb_t *pdb, struct cil_sort *fsuses) { int rc = SEPOL_ERR; uint32_t i = 0; ocontext_t *tail = NULL; for (i = 0; i < fsuses->count; i++) { ocontext_t *new_ocon = cil_add_ocontext(&pdb->ocontexts[OCON_FSUSE], &tail); struct cil_fsuse *cil_fsuse = fsuses->array[i]; new_ocon->u.name = cil_strdup(cil_fsuse->fs_str); new_ocon->v.behavior = cil_fsuse->type; rc = __cil_context_to_sepol_context(pdb, cil_fsuse->context, &new_ocon->context[0]); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: return rc; } int cil_genfscon_to_policydb(policydb_t *pdb, struct cil_sort *genfscons) { int rc = SEPOL_ERR; uint32_t i = 0; genfs_t *genfs_tail = NULL; ocontext_t *ocon_tail = NULL; for (i = 0; i < genfscons->count; i++) { struct cil_genfscon *cil_genfscon = genfscons->array[i]; ocontext_t *new_ocon = cil_malloc(sizeof(ocontext_t)); memset(new_ocon, 0, sizeof(ocontext_t)); if (genfs_tail && strcmp(genfs_tail->fstype, cil_genfscon->fs_str) == 0) { ocon_tail->next = new_ocon; } else { genfs_t *new_genfs = cil_malloc(sizeof(genfs_t)); memset(new_genfs, 0, sizeof(genfs_t)); new_genfs->fstype = cil_strdup(cil_genfscon->fs_str); new_genfs->head = new_ocon; if (genfs_tail) { genfs_tail->next = new_genfs; } else { pdb->genfs = new_genfs; } genfs_tail = new_genfs; } ocon_tail = new_ocon; new_ocon->u.name = cil_strdup(cil_genfscon->path_str); if (cil_genfscon->file_type != CIL_FILECON_ANY) { class_datum_t *class_datum; const char *class_name; switch (cil_genfscon->file_type) { case CIL_FILECON_FILE: class_name = "file"; break; case CIL_FILECON_DIR: class_name = "dir"; break; case CIL_FILECON_CHAR: class_name = "chr_file"; break; case CIL_FILECON_BLOCK: class_name = "blk_file"; break; case CIL_FILECON_SOCKET: class_name = "sock_file"; break; case CIL_FILECON_PIPE: class_name = "fifo_file"; break; case CIL_FILECON_SYMLINK: class_name = "lnk_file"; break; default: rc = SEPOL_ERR; goto exit; } class_datum = hashtab_search(pdb->p_classes.table, class_name); if (!class_datum) { rc = SEPOL_ERR; goto exit; } new_ocon->v.sclass = class_datum->s.value; } 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; } static int cil_devicetreecon_to_policydb(policydb_t *pdb, struct cil_sort *devicetreecons) { int rc = SEPOL_ERR; uint32_t i = 0; ocontext_t *tail = NULL; for (i = 0; i < devicetreecons->count; i++) { ocontext_t *new_ocon = cil_add_ocontext(&pdb->ocontexts[OCON_XEN_DEVICETREE], &tail); struct cil_devicetreecon *cil_devicetreecon = devicetreecons->array[i]; new_ocon->u.name = cil_strdup(cil_devicetreecon->path); rc = __cil_context_to_sepol_context(pdb, cil_devicetreecon->context, &new_ocon->context[0]); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: return rc; } static 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 = NULL; cil_list_for_each(curr, def->class_datums) { struct cil_list_item *c; class_list = cil_expand_class(curr->data); cil_list_for_each(c, class_list) { int rc = __cil_get_sepol_class_datum(pdb, DATUM(c->data), &sepol_class); if (rc != SEPOL_OK) goto exit; switch (def->flavor) { case CIL_DEFAULTUSER: if (!sepol_class->default_user) { sepol_class->default_user = def->object; } else if (sepol_class->default_user != (char)def->object) { cil_log(CIL_ERR,"User default labeling for class %s already specified\n",DATUM(c->data)->fqn); goto exit; } break; case CIL_DEFAULTROLE: if (!sepol_class->default_role) { sepol_class->default_role = def->object; } else if (sepol_class->default_role != (char)def->object) { cil_log(CIL_ERR,"Role default labeling for class %s already specified\n",DATUM(c->data)->fqn); goto exit; } break; case CIL_DEFAULTTYPE: if (!sepol_class->default_type) { sepol_class->default_type = def->object; } else if (sepol_class->default_type != (char)def->object) { cil_log(CIL_ERR,"Type default labeling for class %s already specified\n",DATUM(c->data)->fqn); goto exit; } break; default: goto exit; } } cil_list_destroy(&class_list, CIL_FALSE); } return SEPOL_OK; exit: cil_list_destroy(&class_list, CIL_FALSE); return SEPOL_ERR; } static 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 = NULL; cil_list_for_each(curr, def->class_datums) { struct cil_list_item *c; class_list = cil_expand_class(curr->data); cil_list_for_each(c, class_list) { int rc = __cil_get_sepol_class_datum(pdb, DATUM(c->data), &sepol_class); if (rc != SEPOL_OK) goto exit; if (!sepol_class->default_range) { sepol_class->default_range = def->object_range; } else if (sepol_class->default_range != (char)def->object_range) { cil_log(CIL_ERR,"Range default labeling for class %s already specified\n", DATUM(curr->data)->fqn); goto exit; } } cil_list_destroy(&class_list, CIL_FALSE); } return SEPOL_OK; exit: cil_list_destroy(&class_list, CIL_FALSE); return SEPOL_ERR; } static 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 role_trans_table; void **type_value_to_cil; db = args->db; pdb = args->pdb; pass = args->pass; role_trans_table = args->role_trans_table; type_value_to_cil = args->type_value_to_cil; if (node->flavor >= CIL_MIN_DECLARATIVE) { if (node != NODE(node->data)) { goto exit; } } switch (pass) { case 1: switch (node->flavor) { case CIL_ROLE: rc = cil_role_to_policydb(pdb, node->data); break; case CIL_TYPE: rc = cil_type_to_policydb(pdb, node->data, type_value_to_cil); break; case CIL_TYPEATTRIBUTE: rc = cil_typeattribute_to_policydb(pdb, node->data, type_value_to_cil); break; case CIL_POLICYCAP: rc = cil_policycap_to_policydb(pdb, node->data); break; case CIL_USER: rc = cil_user_to_policydb(pdb, node->data); break; case CIL_BOOL: rc = cil_bool_to_policydb(pdb, node->data); break; case CIL_CATALIAS: if (pdb->mls == CIL_TRUE) { rc = cil_catalias_to_policydb(pdb, node->data); } break; case CIL_SENS: if (pdb->mls == CIL_TRUE) { rc = cil_sepol_level_define(pdb, node->data); } break; default: break; } break; case 2: switch (node->flavor) { case CIL_TYPE: rc = cil_type_bounds_to_policydb(pdb, node->data); break; case CIL_TYPEALIAS: rc = cil_typealias_to_policydb(pdb, node->data); break; case CIL_TYPEPERMISSIVE: rc = cil_typepermissive_to_policydb(pdb, node->data); break; case CIL_TYPEATTRIBUTE: rc = cil_typeattribute_to_bitmap(pdb, db, node->data); break; case CIL_SENSALIAS: if (pdb->mls == CIL_TRUE) { rc = cil_sensalias_to_policydb(pdb, node->data); } break; case CIL_ROLE: rc = cil_role_bounds_to_policydb(pdb, node->data); if (rc != SEPOL_OK) goto exit; rc = cil_roletype_to_policydb(pdb, db, node->data); break; case CIL_USER: rc = cil_user_bounds_to_policydb(pdb, node->data); if (rc != SEPOL_OK) goto exit; if (pdb->mls == CIL_TRUE) { rc = cil_userlevel_userrange_to_policydb(pdb, node->data); if (rc != SEPOL_OK) { goto exit; } } rc = cil_userrole_to_policydb(pdb, db, node->data); break; case CIL_TYPE_RULE: rc = cil_type_rule_to_policydb(pdb, db, node->data); break; case CIL_AVRULE: case CIL_AVRULEX: { struct cil_avrule *rule = node->data; if (db->disable_neverallow != CIL_TRUE && rule->rule_kind == CIL_AVRULE_NEVERALLOW) { struct cil_list *neverallows = args->neverallows; cil_list_prepend(neverallows, CIL_LIST_ITEM, node); } break; } case CIL_ROLETRANSITION: rc = cil_roletrans_to_policydb(pdb, db, node->data, role_trans_table); break; case CIL_ROLEATTRIBUTESET: /*rc = cil_roleattributeset_to_policydb(pdb, node->data);*/ break; case CIL_NAMETYPETRANSITION: rc = cil_typetransition_to_policydb(pdb, db, node->data); 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); } 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); break; case CIL_AVRULE: { struct cil_avrule *rule = node->data; if (rule->rule_kind != CIL_AVRULE_NEVERALLOW) { rc = cil_avrule_to_policydb(pdb, db, node->data); } } break; case CIL_AVRULEX: { struct cil_avrule *rule = node->data; if (rule->rule_kind != CIL_AVRULE_NEVERALLOW) { rc = cil_avrulex_to_hashtable(pdb, db, node->data, &args->avrulex_xperm_tables); } } break; case CIL_ROLEALLOW: rc = cil_roleallow_to_policydb(pdb, db, node->data); break; default: break; } default: break; } exit: if (rc != SEPOL_OK) { cil_tree_log(node, CIL_ERR, "Binary policy creation failed"); } return rc; } static int __cil_binary_create_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args) { int rc = SEPOL_ERR; if (node->flavor == CIL_BLOCK) { struct cil_block *blk = node->data; if (blk->is_abstract == CIL_TRUE) { *finished = CIL_TREE_SKIP_HEAD; rc = SEPOL_OK; goto exit; } } else if (node->flavor == CIL_MACRO) { *finished = CIL_TREE_SKIP_HEAD; rc = SEPOL_OK; goto exit; } else if (node->flavor == CIL_BOOLEANIF) { *finished = CIL_TREE_SKIP_HEAD; } rc = __cil_node_to_policydb(node, extra_args); if (rc != SEPOL_OK) { goto exit; } exit: return rc; } static int __cil_contexts_to_policydb(policydb_t *pdb, const struct cil_db *db) { int rc = SEPOL_ERR; rc = cil_portcon_to_policydb(pdb, db->portcon); if (rc != SEPOL_OK) { goto exit; } rc = cil_netifcon_to_policydb(pdb, db->netifcon); if (rc != SEPOL_OK) { goto exit; } rc = cil_nodecon_to_policydb(pdb, db->nodecon); if (rc != SEPOL_OK) { goto exit; } rc = cil_fsuse_to_policydb(pdb, db->fsuse); if (rc != SEPOL_OK) { goto exit; } rc = cil_genfscon_to_policydb(pdb, db->genfscon); if (rc != SEPOL_OK) { goto exit; } rc = cil_ibpkeycon_to_policydb(pdb, db->ibpkeycon); if (rc != SEPOL_OK) { goto exit; } rc = cil_ibendportcon_to_policydb(pdb, db->ibendportcon); if (rc != SEPOL_OK) { goto exit; } if (db->target_platform == SEPOL_TARGET_XEN) { rc = cil_pirqcon_to_policydb(pdb, db->pirqcon); if (rc != SEPOL_OK) { goto exit; } rc = cil_iomemcon_to_policydb(pdb, db->iomemcon); if (rc != SEPOL_OK) { goto exit; } rc = cil_ioportcon_to_policydb(pdb, db->ioportcon); if (rc != SEPOL_OK) { goto exit; } rc = cil_pcidevicecon_to_policydb(pdb, db->pcidevicecon); if (rc != SEPOL_OK) { goto exit; } rc = cil_devicetreecon_to_policydb(pdb, db->devicetreecon); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: return rc; } static 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; } static 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; } static 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; } static 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; } static 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; } static int __cil_bool_val_array_insert(hashtab_key_t key, hashtab_datum_t datum, void *data) { policydb_t *pdb = data; cond_bool_datum_t *boolean = (cond_bool_datum_t *)datum; if (boolean->s.value < 1 || boolean->s.value > pdb->p_bools.nprim) { return -EINVAL; } pdb->p_bool_val_to_name[boolean->s.value - 1] = (char *)key; pdb->bool_val_to_struct[boolean->s.value - 1] = boolean; return 0; } static 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; } static 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; } static 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; } } } } static int __cil_policydb_create(const struct cil_db *db, struct sepol_policydb **spdb) { int rc; struct policydb *pdb = NULL; rc = sepol_policydb_create(spdb); if (rc < 0) { cil_log(CIL_ERR, "Failed to create policy db\n"); // spdb could be a dangling pointer at this point, so reset it so // callers of this function don't need to worry about freeing garbage *spdb = NULL; goto exit; } pdb = &(*spdb)->p; pdb->policy_type = POLICY_KERN; pdb->target_platform = db->target_platform; pdb->policyvers = db->policy_version; pdb->handle_unknown = db->handle_unknown; pdb->mls = db->mls; return SEPOL_OK; exit: return rc; } static int __cil_policydb_init(policydb_t *pdb, const struct cil_db *db, struct cil_class *class_value_to_cil[], struct cil_perm **perm_value_to_cil[]) { int rc = SEPOL_ERR; // these flags should get set in __cil_policydb_create. However, for // backwards compatibility, it is possible that __cil_policydb_create is // never called. So, they must also be set here. pdb->handle_unknown = db->handle_unknown; pdb->mls = db->mls; rc = cil_classorder_to_policydb(pdb, db, class_value_to_cil, perm_value_to_cil); if (rc != SEPOL_OK) { goto exit; } if (pdb->mls == CIL_TRUE) { rc = cil_catorder_to_policydb(pdb, db); if (rc != SEPOL_OK) { goto exit; } rc = cil_sensitivityorder_to_policydb(pdb, db); if (rc != SEPOL_OK) { goto exit; } } rc = avtab_alloc(&pdb->te_avtab, MAX_AVTAB_SIZE); if (rc != SEPOL_OK) { goto exit; } rc = avtab_alloc(&pdb->te_cond_avtab, MAX_AVTAB_SIZE); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: return rc; } static unsigned int role_trans_hash(hashtab_t h, const_hashtab_key_t key) { const role_trans_t *k = (const role_trans_t *)key; return ((k->role + (k->type << 2) + (k->tclass << 5)) & (h->size - 1)); } static int role_trans_compare(hashtab_t h __attribute__ ((unused)), const_hashtab_key_t key1, const_hashtab_key_t key2) { const role_trans_t *a = (const role_trans_t *)key1; const role_trans_t *b = (const role_trans_t *)key2; return a->role != b->role || a->type != b->type || a->tclass != b->tclass; } /* Based on MurmurHash3, written by Austin Appleby and placed in the * public domain. */ static unsigned int avrulex_hash(__attribute__((unused)) hashtab_t h, const_hashtab_key_t key) { const avtab_key_t *k = (const avtab_key_t *)key; static const uint32_t c1 = 0xcc9e2d51; static const uint32_t c2 = 0x1b873593; static const uint32_t r1 = 15; static const uint32_t r2 = 13; static const uint32_t m = 5; static const uint32_t n = 0xe6546b64; uint32_t hash = 0; #define mix(input) do { \ 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; \ } while (0) mix(k->target_class); mix(k->target_type); mix(k->source_type); mix(k->specified); #undef mix hash ^= hash >> 16; hash *= 0x85ebca6b; hash ^= hash >> 13; hash *= 0xc2b2ae35; hash ^= hash >> 16; return hash & (AVRULEX_TABLE_SIZE - 1); } static int avrulex_compare(hashtab_t h __attribute__ ((unused)), const_hashtab_key_t key1, const_hashtab_key_t key2) { const avtab_key_t *a = (const avtab_key_t *)key1; const avtab_key_t *b = (const avtab_key_t *)key2; return a->source_type != b->source_type || a->target_type != b->target_type || a->target_class != b->target_class || a->specified != b->specified; } int cil_binary_create(const struct cil_db *db, sepol_policydb_t **policydb) { int rc = SEPOL_ERR; struct sepol_policydb *pdb = NULL; rc = __cil_policydb_create(db, &pdb); if (rc != SEPOL_OK) { goto exit; } rc = cil_binary_create_allocated_pdb(db, pdb); if (rc != SEPOL_OK) { goto exit; } *policydb = pdb; return SEPOL_OK; exit: sepol_policydb_free(pdb); return rc; } static void __cil_destroy_sepol_class_perms(class_perm_node_t *curr) { class_perm_node_t *next; while (curr) { next = curr->next; free(curr); curr = next; } } static int __cil_rule_to_sepol_class_perms(policydb_t *pdb, struct cil_list *classperms, class_perm_node_t **sepol_class_perms) { int rc = SEPOL_ERR; struct cil_list_item *i; cil_list_for_each(i, classperms) { if (i->flavor == CIL_CLASSPERMS) { struct cil_classperms *cp = i->data; if (FLAVOR(cp->class) == CIL_CLASS) { class_perm_node_t *cpn = NULL; class_datum_t *sepol_class = NULL; uint32_t data = 0; rc = __cil_get_sepol_class_datum(pdb, DATUM(cp->class), &sepol_class); if (rc != SEPOL_OK) goto exit; rc = __cil_perms_to_datum(cp->perms, sepol_class, &data); if (rc != SEPOL_OK) goto exit; if (data != 0) { /* Only add if there are permissions */ cpn = cil_malloc(sizeof(class_perm_node_t)); cpn->tclass = sepol_class->s.value; cpn->data = data; cpn->next = *sepol_class_perms; *sepol_class_perms = cpn; } } else { /* MAP */ struct cil_list_item *j = NULL; cil_list_for_each(j, cp->perms) { struct cil_perm *cmp = j->data; rc = __cil_rule_to_sepol_class_perms(pdb, cmp->classperms, sepol_class_perms); if (rc != SEPOL_OK) { goto exit; } } } } else { /* SET */ struct cil_classperms_set *cp_set = i->data; struct cil_classpermission *cp = cp_set->set; rc = __cil_rule_to_sepol_class_perms(pdb, cp->classperms, sepol_class_perms); if (rc != SEPOL_OK) { goto exit; } } } return SEPOL_OK; exit: return rc; } static int __cil_permx_to_sepol_class_perms(policydb_t *pdb, struct cil_permissionx *permx, class_perm_node_t **sepol_class_perms) { int rc = SEPOL_OK; struct cil_list *class_list = NULL; struct cil_list_item *c; class_datum_t *sepol_obj = NULL; class_perm_node_t *cpn; uint32_t data = 0; char *perm_str = NULL; class_list = cil_expand_class(permx->obj); cil_list_for_each(c, class_list) { rc = __cil_get_sepol_class_datum(pdb, DATUM(c->data), &sepol_obj); if (rc != SEPOL_OK) { goto exit; } switch (permx->kind) { case CIL_PERMX_KIND_IOCTL: perm_str = CIL_KEY_IOCTL; break; case CIL_PERMX_KIND_NLMSG: perm_str = CIL_KEY_NLMSG; break; default: rc = SEPOL_ERR; goto exit; } rc = __perm_str_to_datum(perm_str, sepol_obj, &data); if (rc != SEPOL_OK) { goto exit; } cpn = cil_malloc(sizeof(*cpn)); cpn->tclass = sepol_obj->s.value; cpn->data = data; cpn->next = *sepol_class_perms; *sepol_class_perms = cpn; } exit: cil_list_destroy(&class_list, CIL_FALSE); return rc; } static void __cil_init_sepol_type_set(type_set_t *t) { ebitmap_init(&t->types); ebitmap_init(&t->negset); t->flags = 0; } static int __cil_add_sepol_type(policydb_t *pdb, const struct cil_db *db, struct cil_symtab_datum *datum, ebitmap_t *map) { int rc = SEPOL_ERR; struct cil_tree_node *n = NODE(datum); type_datum_t *sepol_datum = NULL; if (n->flavor == CIL_TYPEATTRIBUTE) { ebitmap_node_t *tnode; unsigned int i; struct cil_typeattribute *attr = (struct cil_typeattribute *)datum; ebitmap_for_each_positive_bit(attr->types, tnode, i) { datum = DATUM(db->val_to_type[i]); rc = __cil_get_sepol_type_datum(pdb, datum, &sepol_datum); if (rc != SEPOL_OK) goto exit; ebitmap_set_bit(map, sepol_datum->s.value - 1, 1); } } else { rc = __cil_get_sepol_type_datum(pdb, datum, &sepol_datum); if (rc != SEPOL_OK) goto exit; ebitmap_set_bit(map, sepol_datum->s.value - 1, 1); } return SEPOL_OK; exit: return rc; } static avrule_t *__cil_init_sepol_avrule(uint32_t kind, struct cil_tree_node *node) { avrule_t *avrule; struct cil_tree_node *source_node; char *source_path; char *lm_kind; uint32_t hll_line; avrule = cil_malloc(sizeof(avrule_t)); avrule->specified = kind; avrule->flags = 0; __cil_init_sepol_type_set(&avrule->stypes); __cil_init_sepol_type_set(&avrule->ttypes); avrule->perms = NULL; avrule->line = node->line; avrule->source_filename = NULL; avrule->source_line = node->line; source_node = cil_tree_get_next_path(node, &lm_kind, &hll_line, &source_path); if (source_node) { avrule->source_filename = source_path; if (lm_kind != CIL_KEY_SRC_CIL) { avrule->source_line = hll_line + node->hll_offset - source_node->hll_offset - 1; } } avrule->next = NULL; return avrule; } static void __cil_destroy_sepol_avrules(avrule_t *curr) { avrule_t *next; while (curr) { next = curr->next; ebitmap_destroy(&curr->stypes.types); ebitmap_destroy(&curr->stypes.negset); ebitmap_destroy(&curr->ttypes.types); ebitmap_destroy(&curr->ttypes.negset); __cil_destroy_sepol_class_perms(curr->perms); free(curr); curr = next; } } static void __cil_print_parents(const char *pad, struct cil_tree_node *n) { if (!n) return; __cil_print_parents(pad, n->parent); if (n->flavor != CIL_SRC_INFO) { cil_tree_log(n, CIL_ERR,"%s%s", pad, cil_node_to_string(n)); } } static void __cil_print_classperm(struct cil_list *cp_list) { struct cil_list_item *i1, *i2; i1 = cp_list->head; if (i1->flavor == CIL_CLASSPERMS) { struct cil_classperms *cp = i1->data; cil_log(CIL_ERR,"(%s (", DATUM(cp->class)->fqn); cil_list_for_each(i2, cp->perms) { cil_log(CIL_ERR,"%s",DATUM(i2->data)->fqn); if (i2 != cp->perms->tail) { cil_log(CIL_ERR," "); } else { cil_log(CIL_ERR,"))"); } } } else { struct cil_classperms_set *cp_set = i1->data; cil_log(CIL_ERR,"%s", DATUM(cp_set->set)->fqn); } } static void __cil_print_permissionx(struct cil_permissionx *px) { const char *kind_str = NULL; char *expr_str; kind_str = __cil_xperm_kind_to_str(px->kind); __cil_expr_to_string(px->expr_str, CIL_PERMISSIONX, &expr_str); cil_log(CIL_ERR, "%s %s (%s)", kind_str, DATUM(px->obj)->fqn, expr_str); free(expr_str); } static void __cil_print_rule(const char *pad, const char *kind, struct cil_avrule *avrule) { cil_log(CIL_ERR,"%s(%s ", pad, kind); cil_log(CIL_ERR,"%s %s ", DATUM(avrule->src)->fqn, DATUM(avrule->tgt)->fqn); if (!avrule->is_extended) { __cil_print_classperm(avrule->perms.classperms); } else { cil_log(CIL_ERR, "("); __cil_print_permissionx(avrule->perms.x.permx); cil_log(CIL_ERR, ")"); } cil_log(CIL_ERR,")\n"); } static int __cil_print_neverallow_failure(const struct cil_db *db, struct cil_tree_node *node) { int rc; struct cil_list_item *i2; struct cil_list *matching; struct cil_avrule *cil_rule = node->data; struct cil_avrule target; struct cil_tree_node *n2; struct cil_avrule *r2; char *neverallow_str; char *allow_str; enum cil_flavor avrule_flavor; int num_matching = 0; int count_matching = 0; enum cil_log_level log_level = cil_get_log_level(); target.rule_kind = CIL_AVRULE_ALLOWED; target.is_extended = cil_rule->is_extended; target.src = cil_rule->src; target.tgt = cil_rule->tgt; target.perms = cil_rule->perms; if (!cil_rule->is_extended) { neverallow_str = CIL_KEY_NEVERALLOW; allow_str = CIL_KEY_ALLOW; avrule_flavor = CIL_AVRULE; } else { neverallow_str = CIL_KEY_NEVERALLOWX; allow_str = CIL_KEY_ALLOWX; avrule_flavor = CIL_AVRULEX; } cil_tree_log(node, CIL_ERR, "%s check failed", neverallow_str); __cil_print_rule(" ", neverallow_str, cil_rule); cil_list_init(&matching, CIL_NODE); rc = cil_find_matching_avrule_in_ast(db->ast->root, avrule_flavor, &target, matching, CIL_FALSE); if (rc) { cil_log(CIL_ERR, "Error occurred while checking %s rules\n", neverallow_str); cil_list_destroy(&matching, CIL_FALSE); goto exit; } cil_list_for_each(i2, matching) { num_matching++; } cil_list_for_each(i2, matching) { n2 = i2->data; r2 = n2->data; __cil_print_parents(" ", n2); __cil_print_rule(" ", allow_str, r2); count_matching++; if (count_matching >= 4 && num_matching > 4 && log_level == CIL_ERR) { cil_log(CIL_ERR, " Only first 4 of %d matching rules shown (use \"-v\" to show all)\n", num_matching); break; } } cil_log(CIL_ERR,"\n"); cil_list_destroy(&matching, CIL_FALSE); exit: return rc; } static int cil_check_neverallow(const struct cil_db *db, policydb_t *pdb, struct cil_tree_node *node, int *violation) { int rc = SEPOL_OK; struct cil_avrule *cil_rule = node->data; struct cil_symtab_datum *tgt = cil_rule->tgt; uint32_t kind; avrule_t *rule; struct cil_list *xperms = NULL; struct cil_list_item *item; if (!cil_rule->is_extended) { kind = AVRULE_NEVERALLOW; } else { kind = AVRULE_XPERMS_NEVERALLOW; } rule = __cil_init_sepol_avrule(kind, node); rule->next = NULL; rc = __cil_add_sepol_type(pdb, db, cil_rule->src, &rule->stypes.types); if (rc != SEPOL_OK) { goto exit; } if (tgt->fqn == CIL_KEY_SELF) { rule->flags = RULE_SELF; } else if (tgt->fqn == CIL_KEY_NOTSELF) { rule->flags = RULE_NOTSELF; } else if (tgt->fqn == CIL_KEY_OTHER) { rule->flags = RULE_NOTSELF; rc = __cil_add_sepol_type(pdb, db, cil_rule->src, &rule->ttypes.types); if (rc != SEPOL_OK) { goto exit; } } else { rc = __cil_add_sepol_type(pdb, db, tgt, &rule->ttypes.types); if (rc != SEPOL_OK) { goto exit; } } if (!cil_rule->is_extended) { rc = __cil_rule_to_sepol_class_perms(pdb, cil_rule->perms.classperms, &rule->perms); if (rc != SEPOL_OK) { goto exit; } rc = check_assertion(pdb, rule); if (rc == CIL_TRUE) { *violation = CIL_TRUE; rc = __cil_print_neverallow_failure(db, node); if (rc != SEPOL_OK) { goto exit; } } } else { rc = __cil_permx_to_sepol_class_perms(pdb, cil_rule->perms.x.permx, &rule->perms); if (rc != SEPOL_OK) { goto exit; } rc = __cil_permx_bitmap_to_sepol_xperms_list(cil_rule->perms.x.permx->kind, cil_rule->perms.x.permx->perms, &xperms); if (rc != SEPOL_OK) { goto exit; } cil_list_for_each(item, xperms) { rule->xperms = item->data; rc = check_assertion(pdb, rule); if (rc == CIL_TRUE) { *violation = CIL_TRUE; rc = __cil_print_neverallow_failure(db, node); if (rc != SEPOL_OK) { goto exit; } } } } exit: if (xperms != NULL) { cil_list_for_each(item, xperms) { free(item->data); item->data = NULL; } cil_list_destroy(&xperms, CIL_FALSE); } rule->xperms = NULL; __cil_destroy_sepol_avrules(rule); return rc; } static int cil_check_neverallows(const struct cil_db *db, policydb_t *pdb, struct cil_list *neverallows, int *violation) { int rc = SEPOL_OK; struct cil_list_item *item; cil_list_for_each(item, neverallows) { rc = cil_check_neverallow(db, pdb, item->data, violation); if (rc != SEPOL_OK) { goto exit; } } exit: return rc; } static struct cil_list *cil_classperms_from_sepol(policydb_t *pdb, uint16_t class, uint32_t data, struct cil_class *class_value_to_cil[], struct cil_perm **perm_value_to_cil[]) { struct cil_classperms *cp; struct cil_list *cp_list; class_datum_t *sepol_class = pdb->class_val_to_struct[class - 1]; unsigned i; cil_classperms_init(&cp); cp->class = class_value_to_cil[class]; if (!cp->class) goto exit; cil_list_init(&cp->perms, CIL_PERM); for (i = 0; i < sepol_class->permissions.nprim; i++) { struct cil_perm *perm; if ((data & (UINT32_C(1) << i)) == 0) continue; perm = perm_value_to_cil[class][i+1]; if (!perm) goto exit; cil_list_append(cp->perms, CIL_PERM, perm); } cil_list_init(&cp_list, CIL_CLASSPERMS); cil_list_append(cp_list, CIL_CLASSPERMS, cp); return cp_list; exit: cil_destroy_classperms(cp); cil_log(CIL_ERR,"Failed to create CIL class-permissions from sepol values\n"); return NULL; } static int cil_avrule_from_sepol(policydb_t *pdb, avtab_ptr_t sepol_rule, struct cil_avrule *cil_rule, void *type_value_to_cil[], struct cil_class *class_value_to_cil[], struct cil_perm **perm_value_to_cil[]) { int rc = SEPOL_ERR; avtab_key_t *k = &sepol_rule->key; avtab_datum_t *d = &sepol_rule->datum; cil_rule->src = type_value_to_cil[k->source_type]; if (!cil_rule->src) goto exit; cil_rule->tgt = type_value_to_cil[k->target_type]; if (!cil_rule->tgt) goto exit; cil_rule->perms.classperms = cil_classperms_from_sepol(pdb, k->target_class, d->data, class_value_to_cil, perm_value_to_cil); if (!cil_rule->perms.classperms) goto exit; return SEPOL_OK; exit: cil_log(CIL_ERR,"Failed to create CIL AV rule from sepol values\n"); return rc; } static int cil_check_type_bounds(const struct cil_db *db, policydb_t *pdb, void *type_value_to_cil, struct cil_class *class_value_to_cil[], struct cil_perm **perm_value_to_cil[], int *violation) { int rc = SEPOL_OK; int i; for (i = 0; i < db->num_types; i++) { type_datum_t *child; type_datum_t *parent; avtab_ptr_t bad = NULL; int numbad = 0; struct cil_type *t = db->val_to_type[i]; if (!t->bounds) continue; rc = __cil_get_sepol_type_datum(pdb, DATUM(t), &child); if (rc != SEPOL_OK) goto exit; rc = __cil_get_sepol_type_datum(pdb, DATUM(t->bounds), &parent); if (rc != SEPOL_OK) goto exit; rc = bounds_check_type(NULL, pdb, child->s.value, parent->s.value, &bad, &numbad); if (rc != SEPOL_OK) goto exit; if (bad) { avtab_ptr_t cur; struct cil_avrule target; struct cil_tree_node *n1 = NULL; int count_bad = 0; enum cil_log_level log_level = cil_get_log_level(); *violation = CIL_TRUE; target.is_extended = 0; target.rule_kind = CIL_AVRULE_ALLOWED; target.src_str = NULL; target.tgt_str = NULL; cil_log(CIL_ERR, "Child type %s exceeds bounds of parent %s\n", t->datum.fqn, t->bounds->datum.fqn); for (cur = bad; cur; cur = cur->next) { struct cil_list_item *i2; struct cil_list *matching; int num_matching = 0; int count_matching = 0; rc = cil_avrule_from_sepol(pdb, cur, &target, type_value_to_cil, class_value_to_cil, perm_value_to_cil); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Failed to convert sepol avrule to CIL\n"); bounds_destroy_bad(bad); goto exit; } __cil_print_rule(" ", "allow", &target); cil_list_init(&matching, CIL_NODE); rc = cil_find_matching_avrule_in_ast(db->ast->root, CIL_AVRULE, &target, matching, CIL_TRUE); if (rc) { cil_log(CIL_ERR, "Error occurred while checking type bounds\n"); cil_list_destroy(&matching, CIL_FALSE); cil_list_destroy(&target.perms.classperms, CIL_TRUE); bounds_destroy_bad(bad); goto exit; } cil_list_for_each(i2, matching) { num_matching++; } cil_list_for_each(i2, matching) { struct cil_tree_node *n2 = i2->data; struct cil_avrule *r2 = n2->data; if (n1 == n2) { cil_log(CIL_ERR, " \n"); } else { n1 = n2; __cil_print_parents(" ", n2); __cil_print_rule(" ", "allow", r2); } count_matching++; if (count_matching >= 2 && num_matching > 2 && log_level == CIL_ERR) { cil_log(CIL_ERR, " Only first 2 of %d matching rules shown (use \"-v\" to show all)\n", num_matching); break; } } cil_list_destroy(&matching, CIL_FALSE); cil_list_destroy(&target.perms.classperms, CIL_TRUE); count_bad++; if (count_bad >= 4 && numbad > 4 && log_level == CIL_ERR) { cil_log(CIL_ERR, " Only first 4 of %d bad rules shown (use \"-v\" to show all)\n", numbad); break; } } bounds_destroy_bad(bad); } } exit: return rc; } // assumes policydb is already allocated and initialized properly with things // like policy type set to kernel and version set appropriately int cil_binary_create_allocated_pdb(const struct cil_db *db, sepol_policydb_t *policydb) { int rc = SEPOL_ERR; int i; struct cil_args_binary extra_args; struct cil_args_booleanif booleanif_args; policydb_t *pdb = &policydb->p; struct cil_list *neverallows = NULL; hashtab_t role_trans_table = NULL; hashtab_t avrulex_ioctl_table = NULL; hashtab_t avrulex_nlmsg_table = NULL; void **type_value_to_cil = NULL; struct cil_class **class_value_to_cil = NULL; struct cil_perm ***perm_value_to_cil = NULL; if (db == NULL || policydb == NULL) { if (db == NULL) { cil_log(CIL_ERR,"db == NULL\n"); } else if (policydb == NULL) { cil_log(CIL_ERR,"policydb == NULL\n"); } return SEPOL_ERR; } /* libsepol values start at 1. Just allocate extra memory rather than * subtract 1 from the sepol value. */ type_value_to_cil = calloc(db->num_types_and_attrs+1, sizeof(*type_value_to_cil)); if (!type_value_to_cil) goto exit; class_value_to_cil = calloc(db->num_classes+1, sizeof(*class_value_to_cil)); if (!class_value_to_cil) goto exit; perm_value_to_cil = calloc(db->num_classes+1, sizeof(*perm_value_to_cil)); if (!perm_value_to_cil) goto exit; for (i=1; i < db->num_classes+1; i++) { perm_value_to_cil[i] = calloc(PERMS_PER_CLASS+1, sizeof(*perm_value_to_cil[i])); if (!perm_value_to_cil[i]) goto exit; } rc = __cil_policydb_init(pdb, db, class_value_to_cil, perm_value_to_cil); if (rc != SEPOL_OK) { cil_log(CIL_ERR,"Problem in policydb_init\n"); goto exit; } role_trans_table = hashtab_create(role_trans_hash, role_trans_compare, ROLE_TRANS_TABLE_SIZE); if (!role_trans_table) { cil_log(CIL_INFO, "Failure to create hashtab for role_trans\n"); goto exit; } avrulex_ioctl_table = hashtab_create(avrulex_hash, avrulex_compare, AVRULEX_TABLE_SIZE); if (!avrulex_ioctl_table) { cil_log(CIL_INFO, "Failure to create hashtab for avrulex\n"); goto exit; } avrulex_nlmsg_table = hashtab_create(avrulex_hash, avrulex_compare, AVRULEX_TABLE_SIZE); if (!avrulex_nlmsg_table) { cil_log(CIL_INFO, "Failure to create hashtab for avrulex\n"); goto exit; } cil_list_init(&neverallows, CIL_LIST_ITEM); extra_args.db = db; extra_args.pdb = pdb; extra_args.neverallows = neverallows; extra_args.role_trans_table = role_trans_table; extra_args.avrulex_xperm_tables.ioctl = avrulex_ioctl_table; extra_args.avrulex_xperm_tables.nlmsg = avrulex_nlmsg_table; extra_args.type_value_to_cil = type_value_to_cil; booleanif_args.db = db; booleanif_args.pdb = pdb; booleanif_args.cond_node = NULL; booleanif_args.cond_flavor = CIL_NONE; for (i = 1; i <= 3; i++) { extra_args.pass = i; rc = cil_tree_walk(db->ast->root, __cil_binary_create_helper, NULL, NULL, &extra_args); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "Failure while walking cil database\n"); goto exit; } if (i == 1) { rc = __cil_policydb_val_arrays_create(pdb); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "Failure creating val_to_{struct,name} arrays\n"); goto exit; } } if (i == 3) { rc = hashtab_map(avrulex_ioctl_table, __cil_avrulex_ioctl_to_policydb, &booleanif_args); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "Failure creating avrulex rules\n"); goto exit; } rc = hashtab_map(avrulex_nlmsg_table, __cil_avrulex_nlmsg_to_policydb, &booleanif_args); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "Failure creating avrulex rules\n"); goto exit; } } } rc = cil_sidorder_to_policydb(pdb, db); if (rc != SEPOL_OK) { goto exit; } rc = __cil_contexts_to_policydb(pdb, db); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "Failure while inserting cil contexts into sepol policydb\n"); goto exit; } if (pdb->type_attr_map == NULL) { rc = __cil_typeattr_bitmap_init(pdb); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "Failure while initializing typeattribute bitmap\n"); goto exit; } } cond_optimize_lists(pdb->cond_list); __cil_set_conditional_state_and_flags(pdb); if (db->disable_neverallow != CIL_TRUE) { int violation = CIL_FALSE; cil_log(CIL_INFO, "Checking Neverallows\n"); rc = cil_check_neverallows(db, pdb, neverallows, &violation); if (rc != SEPOL_OK) goto exit; cil_log(CIL_INFO, "Checking User Bounds\n"); rc = bounds_check_users(NULL, pdb); if (rc) { violation = CIL_TRUE; } cil_log(CIL_INFO, "Checking Role Bounds\n"); rc = bounds_check_roles(NULL, pdb); if (rc) { violation = CIL_TRUE; } cil_log(CIL_INFO, "Checking Type Bounds\n"); rc = cil_check_type_bounds(db, pdb, type_value_to_cil, class_value_to_cil, perm_value_to_cil, &violation); if (rc != SEPOL_OK) goto exit; if (violation == CIL_TRUE) { rc = SEPOL_ERR; goto exit; } } /* This pre-expands the roles and users for context validity checking */ if (hashtab_map(pdb->p_roles.table, policydb_role_cache, pdb)) { cil_log(CIL_INFO, "Failure creating roles cache"); rc = SEPOL_ERR; goto exit; } if (hashtab_map(pdb->p_users.table, policydb_user_cache, pdb)) { cil_log(CIL_INFO, "Failure creating users cache"); rc = SEPOL_ERR; goto exit; } rc = SEPOL_OK; exit: hashtab_destroy(role_trans_table); hashtab_map(avrulex_ioctl_table, __cil_avrulex_xperm_destroy, NULL); hashtab_destroy(avrulex_ioctl_table); hashtab_map(avrulex_nlmsg_table, __cil_avrulex_xperm_destroy, NULL); hashtab_destroy(avrulex_nlmsg_table); free(type_value_to_cil); free(class_value_to_cil); if (perm_value_to_cil != NULL) { /* Range is because libsepol values start at 1. */ for (i=1; i < db->num_classes+1; i++) { free(perm_value_to_cil[i]); } free(perm_value_to_cil); } cil_list_destroy(&neverallows, CIL_FALSE); return rc; } libsepol-3.8.1/cil/src/cil_binary.h000066400000000000000000000433451476211737200172010ustar00rootroot00000000000000/* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #ifndef _CIL_BINARY_H_ #define _CIL_BINARY_H_ #include #include "cil_internal.h" #include "cil_tree.h" #include "cil_list.h" /** * Create a binary policydb from the cil db. * * @param[in] db The cil database. * @param[in] pdb The policy database. * * @return SEPOL_OK upon success or an error otherwise. */ int cil_binary_create(const struct cil_db *db, sepol_policydb_t **pdb); /** * Create a pre allocated binary policydb from the cil db. * * It is assumed that pdb has been allocated and initialized so that fields such * as policy type and version are set appropriately. It is recommended that * instead of calling this, one instead calls cil_binary_create, which will * properly allocate and initialize the pdb and then calls this function. This * function is used to maintain binary backwards compatibility. * * @param[in] db The cil database. * @param[in] pdb The policy database. * * @return SEPOL_OK upon success or an error otherwise. */ int cil_binary_create_allocated_pdb(const struct cil_db *db, sepol_policydb_t *pdb); /** * Insert cil common structure into sepol policydb. * * @param[in] pdb The policy database to insert the common into. * @param[in] datum The cil_common datum. * @param[out] common_out The sepol common to send back. * * @return SEPOL_OK upon success or an error otherwise. */ int cil_common_to_policydb(policydb_t *pdb, struct cil_class *cil_common, common_datum_t **common_out); /** * Insert cil class structure into sepol policydb. * * @param[in] pdb The policy database to insert the class into. * @param[in] datum The cil_class datum. * * @return SEPOL_OK upon success or an error otherwise. */ int cil_class_to_policydb(policydb_t *pdb, struct cil_class *cil_class); /** * Insert cil role structure into sepol policydb. * * @param[in] pdb The policy database to insert the role into. * @param[in] datum The cil_role datum. * * @return SEPOL_OK upon success or an error otherwise. */ int cil_role_to_policydb(policydb_t *pdb, struct cil_role *cil_role); /** * Insert cil roletype structure into sepol policydb. * * @param[in] pdb The policy database to insert the roletype into. * @param[in] db The cil database * @param[in] datum The cil_roletype datum. * * @return SEPOL_OK upon success or SEPOL_ERR otherwise. */ int cil_roletype_to_policydb(policydb_t *pdb, const struct cil_db *db, struct cil_role *role); /** * Insert cil type structure into sepol policydb. * * @param[in] pdb The policy database to insert the type into. * @param[in] datum The cil_type datum. * * @return SEPOL_OK upon success or an error otherwise. */ int cil_type_to_policydb(policydb_t *pdb, struct cil_type *cil_type, void *type_value_to_cil[]); /** * Insert cil typealias structure into sepol policydb. * * @param[in] pdb The policy database to insert the typealias into. * @param[in] datum The cil_typealias datum. * * @return SEPOL_OK upon success or an error otherwise. */ int cil_typealias_to_policydb(policydb_t *pdb, struct cil_alias *cil_alias); /** * Insert cil typepermissive structure into sepol policydb. * The function looks up the previously inserted type and flips the bit * in the permssive types bitmap that corresponds to that type's value. * * @param[in] pdb The policy database to insert the typepermissive into. * @param[in] datum The cil_typepermissive datum. * * @return SEPOL_OK upon success or an error otherwise. */ int cil_typepermissive_to_policydb(policydb_t *pdb, struct cil_typepermissive *cil_typeperm); /** * Insert cil attribute structure into sepol policydb. * * @param[in] pdb The policy database to insert the attribute into. * @param[in] datum The cil_attribute datum. * * @return SEPOL_OK upon success or an error otherwise. */ int cil_typeattribute_to_policydb(policydb_t *pdb, struct cil_typeattribute *cil_attr, void *type_value_to_cil[]); /** * Insert cil attribute structure into sepol type->attribute bitmap. * The function calls helper functions to loop over the attributes lists * of types and negative types. If either of the lists contain an attribute, * the helper functions will recurse into the attribute and record the * attribute's types and negative types. There is no minimum depth. * * @param[in] pdb The policy database that contains the type->attribute bitmap. * @param[in] db The cil database * @param[in] node The tree node that contains the cil_attribute. * * @return SEPOL_OK upon success or an error otherwise. */ int cil_typeattribute_to_bitmap(policydb_t *pdb, const struct cil_db *cdb, struct cil_typeattribute *cil_attr); /** * Insert cil policycap structure into sepol policydb. * * @param[in] pdb The policy database to insert the policycap into. * @param[in] node The tree node that contains the cil_policycap. * * @return SEPOL_OK upon success or SEPOL_ERR upon error. */ int cil_policycap_to_policydb(policydb_t *pdb, struct cil_policycap *cil_polcap); /** * Insert cil user structure into sepol policydb. * * @param[in] pdb THe policy database to insert the user into. * @param[in] node The tree node that contains the cil_user. * * @return SEPOL_OK upon success or an error otherwise. */ int cil_user_to_policydb(policydb_t *pdb, struct cil_user *cil_user); /** * Insert cil userrole structure into sepol policydb. * * @param[in] pdb The policy database to insert the userrole into. * @param[in] db The cil database * @param[in] datum The cil_user * * @return SEPOL_OK upon success or SEPOL_ERR otherwise. */ int cil_userrole_to_policydb(policydb_t *pdb, const struct cil_db *db, struct cil_user *user); /** * Insert cil bool structure into sepol policydb. * * @param[in] pdb THe policy database to insert the bool into. * @param[in] datum The cil_bool datum. * * @return SEPOL_OK upon success or an error otherwise. */ int cil_bool_to_policydb(policydb_t *pdb, struct cil_bool *cil_bool); /** * Insert all ordered cil category structures into sepol policydb. * * @param[in] pdb The policy database to insert the categories into. * @param[in] db The cil database that contains the category order list. * * @return SEPOL_OK upon success or an error otherwise. */ int cil_catorder_to_policydb(policydb_t *pdb, const struct cil_db *db); /** * Insert cil category alias structure into sepol policydb. * * @param[in] pdb The policy database to insert the category alias into. * @param[in] datum The cil_catalias datum. * * @return SEPOL_OK upon success or an error otherwise. */ int cil_catalias_to_policydb(policydb_t *pdb, struct cil_alias *cil_alias); /** * Insert the cil sensitivityorder into sepol policydb. * * @param[in] pdb The policy database to insert the sensitivityorder into. * @param[in] db the cil database that contains the sensitivityorder list. * * @return SEPOL_OK upon success or an error otherwise. */ int cil_sensitivityorder_to_policydb(policydb_t *pdb, const struct cil_db *db); /** * Insert cil type rule structure into sepol policydb. This includes * typetransition, typechange, and typemember. * * @param[in] pdb The policy database to insert the type rule into. * @param[in] datum The cil_type_rule datum. * * @return SEPOL_OK upon success or an error otherwise. */ int cil_type_rule_to_policydb(policydb_t *pdb, const struct cil_db *db, struct cil_type_rule *cil_rule); /** * Insert cil avrule structure into sepol policydb. * * @param[in] pdb The policy database to insert the avrule into. * @param[in] datum The cil_avrule datum. * * @return SEPOL_OK upon success or an error otherwise. */ int cil_avrule_to_policydb(policydb_t *pdb, const struct cil_db *db, struct cil_avrule *cil_avrule); /** * Insert cil booleanif structure into sepol policydb. This populates the * policydb conditional list. Each conditional node contains an expression * and true/false avtab_ptr lists that point into te_cond_avtab. * * @param[in] pdb The policy database to insert the booleanif into. * @param[in] node The cil_booleanif node. * * @return SEPOL_OK upon success or an error otherwise. */ int cil_booleanif_to_policydb(policydb_t *pdb, const struct cil_db *db, struct cil_tree_node *node); /** * 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); /** * 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); /** * Insert cil ibpkeycon structure into sepol policydb. * The function is given a structure containing the sorted ibpkeycons and * loops over this structure inserting them into the policy database. * * @param[in] pdb The policy database to insert the ibpkeycon into. * @param[in] node The cil_sort structure that contains the sorted ibpkeycons. * * @return SEPOL_OK upon success or an error otherwise. */ int cil_ibpkeycon_to_policydb(policydb_t *pdb, struct cil_sort *ibpkeycons); /** * Insert cil idbev structure into sepol policydb. * The function is given a structure containing the sorted ibendportcons and * loops over this structure inserting them into the policy database. * * @param[in] pdb The policy database to insert the pkeycon into. * @param[in] node The cil_sort structure that contains the sorted ibendportcons. * * @return SEPOL_OK upon success or an error otherwise. */ int cil_ibendportcon_to_policydb(policydb_t *pdb, struct cil_sort *pkeycons); /** * Insert cil portcon structure into sepol policydb. * The function is given a structure containing the sorted portcons and * loops over this structure inserting them into the policy database. * * @param[in] pdb The policy database to insert the portcon into. * @param[in] node The cil_sort structure that contains the sorted portcons. * * @return SEPOL_OK upon success or an error otherwise. */ int cil_portcon_to_policydb(policydb_t *pdb, struct cil_sort *portcons); /** * Insert cil netifcon structure into sepol policydb. * The function is given a structure containing the sorted netifcons and * loops over this structure inserting them into the policy database. * * @param[in] pdb The policy database to insert the netifcon into. * @param[in] node The cil_sort structure that contains the sorted netifcons. * * @return SEPOL_OK upon success or an error otherwise. */ int cil_netifcon_to_policydb(policydb_t *pdb, struct cil_sort *netifcons); /** * Insert cil nodecon structure into sepol policydb. * The function is given a structure containing the sorted nodecons and * loops over this structure inserting them into the policy database. * * @param[in] pdb The policy database to insert the nodecon into. * @param[in] node The cil_sort structure that contains the sorted nodecons. * * @return SEPOL_OK upon success or an error otherwise. */ int cil_nodecon_to_policydb(policydb_t *pdb, struct cil_sort *nodecons); /** * Insert cil fsuse structure into sepol policydb. * The function is given a structure containing the sorted fsuses and * loops over this structure inserting them into the policy database. * * @param[in] pdb The policy database to insert the fsuse into. * @param[in] node The cil_sort structure that contains the sorted fsuses. * * @return SEPOL_OK upon success or an error otherwise. */ int cil_fsuse_to_policydb(policydb_t *pdb, struct cil_sort *fsuses); /** * Insert cil genfscon structure into sepol policydb. * The function is given a structure containing the sorted genfscons and * loops over this structure inserting them into the policy database. * * @param[in] pdb The policy database to insert the genfscon into. * @param[in] node The cil_sort structure that contains the sorted genfscons. * * @return SEPOL_OK upon success or an error otherwise. */ int cil_genfscon_to_policydb(policydb_t *pdb, struct cil_sort *genfscons); /** * Insert cil pirqcon structure into sepol policydb. * The function is given a structure containing the sorted pirqcons and * loops over this structure inserting them into the policy database. * * @param[in] pdb The policy database to insert the pirqcon into. * @param[in] node The cil_sort structure that contains the sorted pirqcons. * * @return SEPOL_OK upon success or an error otherwise. */ int cil_pirqcon_to_policydb(policydb_t *pdb, struct cil_sort *pirqcons); /** * Insert cil iomemcon structure into sepol policydb. * The function is given a structure containing the sorted iomemcons and * loops over this structure inserting them into the policy database. * * @param[in] pdb The policy database to insert the iomemcon into. * @param[in] node The cil_sort structure that contains the sorted iomemcons. * * @return SEPOL_OK upon success or an error otherwise. */ int cil_iomemcon_to_policydb(policydb_t *pdb, struct cil_sort *iomemcons); /** * Insert cil ioportcon structure into sepol policydb. * The function is given a structure containing the sorted ioportcons and * loops over this structure inserting them into the policy database. * * @param[in] pdb The policy database to insert the ioportcon into. * @param[in] node The cil_sort structure that contains the sorted ioportcons. * * @return SEPOL_OK upon success or an error otherwise. */ int cil_ioportcon_to_policydb(policydb_t *pdb, struct cil_sort *ioportcons); /** * Insert cil pcidevicecon structure into sepol policydb. * The function is given a structure containing the sorted pcidevicecons and * loops over this structure inserting them into the policy database. * * @param[in] pdb The policy database to insert the pcidevicecon into. * @param[in] node The cil_sort structure that contains the sorted pcidevicecons. * * @return SEPOL_OK upon success or an error otherwise. */ int cil_pcidevicecon_to_policydb(policydb_t *pdb, struct cil_sort *pcidevicecons); /** * Create an mls level using a cil level. * The function is given a structure containing the a cil_level and * outputs a created mls_level_t. * * @param[in] pdb The policy database to use to get sepol level from cil_level's sensitivity. * @param[in] cil_level The cil_level that will be used to create an mls_level_t. * @param[out] mls_level The mls_level that is created. * * @return SEPOL_OK upon success or an error otherwise. */ int cil_level_to_mls_level(policydb_t *pdb, struct cil_level *cil_level, mls_level_t *mls_level); #endif //_CIL_BINARY_H_ libsepol-3.8.1/cil/src/cil_build_ast.c000066400000000000000000004743501476211737200176620ustar00rootroot00000000000000/* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #include #include #include #include #include #include "cil_internal.h" #include "cil_flavor.h" #include "cil_log.h" #include "cil_mem.h" #include "cil_tree.h" #include "cil_list.h" #include "cil_parser.h" #include "cil_build_ast.h" #include "cil_copy_ast.h" #include "cil_verify.h" #include "cil_strpool.h" struct cil_args_build { struct cil_tree_node *ast; struct cil_db *db; struct cil_tree_node *tunif; struct cil_tree_node *in; struct cil_tree_node *macro; struct cil_tree_node *optional; struct cil_tree_node *boolif; }; static 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 }; size_t 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; } struct cil_symtab_datum *cil_gen_declared_string(struct cil_db *db, hashtab_key_t key, struct cil_tree_node *ast_node) { struct cil_tree_node *parent = ast_node->parent; struct cil_macro *macro = NULL; symtab_t *symtab; struct cil_symtab_datum *datum; while (parent) { if (parent->flavor == CIL_MACRO) { /* This condition is only reached in the build phase */ macro = parent->data; break; } else if (parent->flavor == CIL_CALL) { /* This condition is only reached in the resolve phase */ struct cil_call *call = parent->data; macro = call->macro; break; } parent = parent->parent; } if (macro && macro->params) { struct cil_list_item *item; cil_list_for_each(item, macro->params) { struct cil_param *param = item->data; if (param->flavor == CIL_DECLARED_STRING && param->str == key) { return NULL; } } } symtab = &((struct cil_root *)db->ast->root->data)->symtab[CIL_SYM_STRINGS]; cil_symtab_get_datum(symtab, key, &datum); if (datum != NULL) { return datum; } datum = cil_malloc(sizeof(*datum)); cil_symtab_datum_init(datum); cil_symtab_insert(symtab, key, datum, ast_node); cil_list_append(db->declared_strings, CIL_DATUM, datum); return datum; } static int cil_allow_multiple_decls(struct cil_db *db, enum cil_flavor f_new, enum cil_flavor f_old) { if (f_new != f_old) { return CIL_FALSE; } switch (f_new) { case CIL_TYPE: case CIL_TYPEATTRIBUTE: case CIL_ROLE: if (db->multiple_decls) { return CIL_TRUE; } break; case CIL_OPTIONAL: return CIL_TRUE; break; default: break; } return CIL_FALSE; } int cil_add_decl_to_symtab(struct cil_db *db, symtab_t *symtab, hashtab_key_t key, struct cil_symtab_datum *datum, struct cil_tree_node *node) { int rc; if (symtab == NULL || datum == NULL || node == NULL) { return SEPOL_ERR; } rc = cil_symtab_insert(symtab, key, datum, node); if (rc == SEPOL_EEXIST) { struct cil_symtab_datum *prev; rc = cil_symtab_get_datum(symtab, key, &prev); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Re-declaration of %s %s, but previous declaration could not be found\n",cil_node_to_string(node), key); return SEPOL_ERR; } if (!cil_allow_multiple_decls(db, node->flavor, FLAVOR(prev))) { /* multiple_decls not ok, ret error */ struct cil_tree_node *n = NODE(prev); cil_log(CIL_ERR, "Re-declaration of %s %s\n", cil_node_to_string(node), key); cil_tree_log(node, CIL_ERR, "Previous declaration of %s", cil_node_to_string(n)); return SEPOL_ERR; } /* multiple_decls is enabled and works for this datum type, add node */ cil_list_append(prev->nodes, CIL_NODE, node); node->data = prev; return SEPOL_EEXIST; } return SEPOL_OK; } int cil_gen_node(struct cil_db *db, struct cil_tree_node *ast_node, struct cil_symtab_datum *datum, hashtab_key_t key, enum cil_sym_index sflavor, enum cil_flavor nflavor) { int rc = SEPOL_ERR; symtab_t *symtab = NULL; rc = cil_verify_name(db, (const char*)key, nflavor); 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; rc = cil_add_decl_to_symtab(db, symtab, key, datum, ast_node); if (rc != SEPOL_OK) { goto exit; } if (ast_node->parent->flavor == CIL_MACRO) { rc = cil_verify_decl_does_not_shadow_macro_parameter(ast_node->parent->data, ast_node, key); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: return rc; } static 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_ordered(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_LIST, CIL_SYN_END }; size_t syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_ordered *ordered = NULL; struct cil_list_item *curr = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_ordered_init(&ordered); rc = cil_fill_list(parse_current->next->cl_head, flavor, &ordered->strs); if (rc != SEPOL_OK) { goto exit; } cil_list_for_each(curr, ordered->strs) { if (curr->data == CIL_KEY_UNORDERED) { if (flavor == CIL_CLASSORDER) { if (curr == ordered->strs->head && curr->next == NULL) { cil_log(CIL_ERR, "classorder 'unordered' keyword must be followed by one or more class.\n"); rc = SEPOL_ERR; goto exit; } else if (curr != ordered->strs->head) { cil_log(CIL_ERR, "classorder can only use 'unordered' keyword as the first item in the list.\n"); rc = SEPOL_ERR; goto exit; } } else { cil_log(CIL_ERR, "The 'unordered' keyword can only be used with classorder rules.\n"); rc = SEPOL_ERR; goto exit; } } } ast_node->data = ordered; ast_node->flavor = flavor; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad ordered declaration"); cil_destroy_ordered(ordered); return rc; } void cil_destroy_ordered(struct cil_ordered *ordered) { if (ordered == NULL) { return; } if (ordered->strs != NULL) { cil_list_destroy(&ordered->strs, CIL_FALSE); } if (ordered->datums != NULL) { cil_list_destroy(&ordered->datums, CIL_FALSE); } free(ordered); } int cil_gen_block(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, uint16_t is_abstract) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_N_LISTS | CIL_SYN_END, CIL_SYN_END }; size_t 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; } if (db->qualified_names) { cil_log(CIL_ERR, "Blocks are not allowed when the option for qualified names is used\n"); goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_block_init(&block); block->is_abstract = is_abstract; key = parse_current->next->data; rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)block, (hashtab_key_t)key, CIL_SYM_BLOCKS, CIL_BLOCK); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad block declaration"); cil_destroy_block(block); cil_clear_node(ast_node); return rc; } void cil_destroy_block(struct cil_block *block) { struct cil_list_item *item; struct cil_tree_node *bi_node; struct cil_blockinherit *inherit; if (block == NULL) { return; } cil_symtab_datum_destroy(&block->datum); cil_symtab_array_destroy(block->symtab); if (block->bi_nodes != NULL) { /* unlink blockinherit->block */ cil_list_for_each(item, block->bi_nodes) { bi_node = item->data; /* the conditions should always be true, but better be sure */ if (bi_node->flavor == CIL_BLOCKINHERIT) { inherit = bi_node->data; if (inherit->block == block) { inherit->block = NULL; } } } cil_list_destroy(&block->bi_nodes, CIL_FALSE); } free(block); } int cil_gen_blockinherit(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_END }; size_t 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; } if (db->qualified_names) { cil_log(CIL_ERR, "Block inherit rules are not allowed when the option for qualified names is used\n"); goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_blockinherit_init(&inherit); inherit->block_str = parse_current->next->data; ast_node->data = inherit; ast_node->flavor = CIL_BLOCKINHERIT; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad blockinherit declaration"); cil_destroy_blockinherit(inherit); return rc; } void cil_destroy_blockinherit(struct cil_blockinherit *inherit) { if (inherit == NULL) { return; } if (inherit->block != NULL && inherit->block->bi_nodes != NULL) { struct cil_tree_node *node; struct cil_list_item *item; cil_list_for_each(item, inherit->block->bi_nodes) { node = item->data; if (node->data == inherit) { cil_list_remove(inherit->block->bi_nodes, CIL_NODE, node, CIL_FALSE); break; } } } free(inherit); } int cil_gen_blockabstract(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_END }; size_t 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; } if (db->qualified_names) { cil_log(CIL_ERR, "Block abstract rules are not allowed when the option for qualified names is used\n"); goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_blockabstract_init(&abstract); abstract->block_str = parse_current->next->data; ast_node->data = abstract; ast_node->flavor = CIL_BLOCKABSTRACT; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad blockabstract declaration"); cil_destroy_blockabstract(abstract); return rc; } void cil_destroy_blockabstract(struct cil_blockabstract *abstract) { if (abstract == NULL) { return; } free(abstract); } int cil_gen_in(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_N_LISTS, CIL_SYN_N_LISTS | CIL_SYN_END, CIL_SYN_END }; size_t 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; } if (db->qualified_names) { cil_log(CIL_ERR, "In-statements are not allowed when the option for qualified names is used\n"); goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_in_init(&in); if (parse_current->next->next->data) { char *is_after_str = parse_current->next->data; if (is_after_str == CIL_KEY_IN_BEFORE) { in->is_after = CIL_FALSE; } else if (is_after_str == CIL_KEY_IN_AFTER) { in->is_after = CIL_TRUE; } else { cil_log(CIL_ERR, "Value must be either \'before\' or \'after\'\n"); rc = SEPOL_ERR; goto exit; } in->block_str = parse_current->next->next->data; } else { in->is_after = CIL_FALSE; in->block_str = parse_current->next->data; } ast_node->data = in; ast_node->flavor = CIL_IN; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad in-statement"); cil_destroy_in(in); return rc; } void cil_destroy_in(struct cil_in *in) { if (in == NULL) { return; } cil_symtab_array_destroy(in->symtab); free(in); } int cil_gen_class(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_LIST | CIL_SYN_EMPTY_LIST, CIL_SYN_END }; size_t syntax_len = sizeof(syntax)/sizeof(*syntax); char *key = NULL; struct cil_class *class = NULL; struct cil_tree_node *perms = NULL; int rc = SEPOL_ERR; rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_class_init(&class); key = parse_current->next->data; if (key == CIL_KEY_UNORDERED) { cil_log(CIL_ERR, "'unordered' keyword is reserved and not a valid class name.\n"); rc = SEPOL_ERR; goto exit; } rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)class, (hashtab_key_t)key, CIL_SYM_CLASSES, CIL_CLASS); if (rc != SEPOL_OK) { goto exit; } if (parse_current->next->next != NULL) { perms = parse_current->next->next->cl_head; rc = cil_gen_perm_nodes(db, perms, ast_node, CIL_PERM, &class->num_perms); if (rc != SEPOL_OK) { goto exit; } if (class->num_perms > CIL_PERMS_PER_CLASS) { cil_tree_log(parse_current, CIL_ERR, "Too many permissions in class '%s'", class->datum.name); cil_tree_children_destroy(ast_node); rc = SEPOL_ERR; goto exit; } } return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad class declaration"); cil_destroy_class(class); cil_clear_node(ast_node); return rc; } void cil_destroy_class(struct cil_class *class) { if (class == NULL) { return; } cil_symtab_datum_destroy(&class->datum); cil_symtab_destroy(&class->perms); free(class); } int cil_gen_perm(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor, unsigned int *num_perms) { char *key = NULL; struct cil_perm *perm = NULL; int rc = SEPOL_ERR; cil_perm_init(&perm); key = parse_current->data; if (key == NULL) { cil_log(CIL_ERR, "Bad permission\n"); goto exit; } rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)perm, (hashtab_key_t)key, CIL_SYM_PERMS, flavor); if (rc != SEPOL_OK) { goto exit; } perm->value = *num_perms; (*num_perms)++; return SEPOL_OK; exit: cil_destroy_perm(perm); cil_clear_node(ast_node); return rc; } void cil_destroy_perm(struct cil_perm *perm) { if (perm == NULL) { return; } cil_symtab_datum_destroy(&perm->datum); cil_list_destroy(&perm->classperms, CIL_FALSE); free(perm); } int cil_gen_perm_nodes(struct cil_db *db, struct cil_tree_node *current_perm, struct cil_tree_node *ast_node, enum cil_flavor flavor, unsigned int *num_perms) { int rc = SEPOL_ERR; struct cil_tree_node *new_ast = NULL; while(current_perm != NULL) { if (current_perm->cl_head != NULL) { rc = SEPOL_ERR; goto exit; } cil_tree_node_init(&new_ast); new_ast->parent = ast_node; new_ast->line = current_perm->line; new_ast->hll_offset = current_perm->hll_offset; rc = cil_gen_perm(db, current_perm, new_ast, flavor, num_perms); if (rc != SEPOL_OK) { cil_tree_node_destroy(&new_ast); goto exit; } if (ast_node->cl_head == NULL) { ast_node->cl_head = new_ast; } else { ast_node->cl_tail->next = new_ast; } ast_node->cl_tail = new_ast; current_perm = current_perm->next; } return SEPOL_OK; exit: cil_log(CIL_ERR, "Bad permissions\n"); cil_tree_children_destroy(ast_node); cil_clear_node(ast_node); return rc; } int cil_fill_perms(struct cil_tree_node *start_perm, struct cil_list **perms) { int rc = SEPOL_ERR; enum cil_syntax syntax[] = { CIL_SYN_N_STRINGS | CIL_SYN_N_LISTS, CIL_SYN_END }; size_t 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 }; size_t 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; if (parse_current == NULL || cp_list == NULL) { goto exit; } cil_list_init(cp_list, CIL_CLASSPERMS); curr = parse_current->cl_head; if (curr == NULL) { /* Class-perms form: SET1 */ struct cil_classperms_set *new_cp_set; cil_fill_classperms_set(parse_current, &new_cp_set); cil_list_append(*cp_list, CIL_CLASSPERMS_SET, new_cp_set); } else if (curr->cl_head == NULL) { /* Class-perms form: (CLASS1 (PERM1 ...)) */ struct cil_classperms *new_cp; rc = cil_fill_classperms(curr, &new_cp); if (rc != SEPOL_OK) { goto exit; } cil_list_append(*cp_list, CIL_CLASSPERMS, new_cp); } else { cil_log(CIL_ERR, "Bad class-permissions list syntax\n"); rc = SEPOL_ERR; goto exit; } return SEPOL_OK; exit: cil_log(CIL_ERR, "Problem filling class-permissions list\n"); cil_list_destroy(cp_list, CIL_TRUE); return rc; } void cil_destroy_classperms_list(struct cil_list **cp_list) { struct cil_list_item *curr; if (cp_list == NULL || *cp_list == NULL) { return; } cil_list_for_each(curr, *cp_list) { if (curr->flavor == CIL_CLASSPERMS) { cil_destroy_classperms(curr->data); } else { cil_destroy_classperms_set(curr->data); } } cil_list_destroy(cp_list, CIL_FALSE); } int cil_gen_classpermission(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { int rc = SEPOL_ERR; char *key = NULL; struct cil_classpermission *cp = NULL; enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_END }; size_t syntax_len = sizeof(syntax)/sizeof(*syntax); if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_classpermission_init(&cp); key = parse_current->next->data; rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)cp, (hashtab_key_t)key, CIL_SYM_CLASSPERMSETS, CIL_CLASSPERMISSION); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad classpermission declaration"); cil_destroy_classpermission(cp); cil_clear_node(ast_node); return rc; } void cil_destroy_classpermission(struct cil_classpermission *cp) { if (cp == NULL) { return; } if (cp->datum.name != NULL) { cil_list_destroy(&cp->classperms, CIL_FALSE); } else { /* anonymous classpermission from call */ cil_destroy_classperms_list(&cp->classperms); } cil_symtab_datum_destroy(&cp->datum); free(cp); } int cil_gen_classpermissionset(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { int rc = SEPOL_ERR; struct cil_classpermissionset *cps = NULL; enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; size_t syntax_len = sizeof(syntax)/sizeof(*syntax); if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_classpermissionset_init(&cps); cps->set_str = parse_current->next->data; rc = cil_fill_classperms_list(parse_current->next->next, &cps->classperms); if (rc != SEPOL_OK) { goto exit; } ast_node->data = cps; ast_node->flavor = CIL_CLASSPERMISSIONSET; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad classpermissionset"); cil_destroy_classpermissionset(cps); return rc; } void cil_destroy_classpermissionset(struct cil_classpermissionset *cps) { if (cps == NULL) { return; } cil_destroy_classperms_list(&cps->classperms); free(cps); } int cil_gen_map_class(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_LIST, CIL_SYN_END }; size_t syntax_len = sizeof(syntax)/sizeof(*syntax); char *key = NULL; struct cil_class *map = NULL; int rc = SEPOL_ERR; rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_class_init(&map); key = parse_current->next->data; rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)map, (hashtab_key_t)key, CIL_SYM_CLASSES, CIL_MAP_CLASS); if (rc != SEPOL_OK) { goto exit; } rc = cil_gen_perm_nodes(db, parse_current->next->next->cl_head, ast_node, CIL_MAP_PERM, &map->num_perms); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad map class declaration"); cil_destroy_class(map); cil_clear_node(ast_node); return rc; } int cil_gen_classmapping(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { int rc = SEPOL_ERR; struct cil_classmapping *mapping = NULL; enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; size_t syntax_len = sizeof(syntax)/sizeof(*syntax); if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_classmapping_init(&mapping); mapping->map_class_str = parse_current->next->data; mapping->map_perm_str = parse_current->next->next->data; rc = cil_fill_classperms_list(parse_current->next->next->next, &mapping->classperms); if (rc != SEPOL_OK) { goto exit; } ast_node->data = mapping; ast_node->flavor = CIL_CLASSMAPPING; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad classmapping declaration"); cil_destroy_classmapping(mapping); return rc; } void cil_destroy_classmapping(struct cil_classmapping *mapping) { if (mapping == NULL) { return; } cil_destroy_classperms_list(&mapping->classperms); free(mapping); } // TODO try to merge some of this with cil_gen_class (helper function for both) int cil_gen_common(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_LIST, CIL_SYN_END }; size_t syntax_len = sizeof(syntax)/sizeof(*syntax); char *key = NULL; struct cil_class *common = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_class_init(&common); key = parse_current->next->data; rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)common, (hashtab_key_t)key, CIL_SYM_COMMONS, CIL_COMMON); if (rc != SEPOL_OK) { goto exit; } rc = cil_gen_perm_nodes(db, parse_current->next->next->cl_head, ast_node, CIL_PERM, &common->num_perms); if (rc != SEPOL_OK) { goto exit; } if (common->num_perms > CIL_PERMS_PER_CLASS) { cil_tree_log(parse_current, CIL_ERR, "Too many permissions in common '%s'", common->datum.name); cil_tree_children_destroy(ast_node); rc = SEPOL_ERR; goto exit; } return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad common declaration"); cil_destroy_class(common); cil_clear_node(ast_node); return rc; } int cil_gen_classcommon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_END }; size_t syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_classcommon *clscom = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_classcommon_init(&clscom); clscom->class_str = parse_current->next->data; clscom->common_str = parse_current->next->next->data; ast_node->data = clscom; ast_node->flavor = CIL_CLASSCOMMON; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad classcommon declaration"); cil_destroy_classcommon(clscom); return rc; } void cil_destroy_classcommon(struct cil_classcommon *clscom) { if (clscom == NULL) { return; } free(clscom); } int cil_gen_sid(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_END }; size_t syntax_len = sizeof(syntax)/sizeof(*syntax); char *key = NULL; struct cil_sid *sid = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_sid_init(&sid); key = parse_current->next->data; rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)sid, (hashtab_key_t)key, CIL_SYM_SIDS, CIL_SID); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad sid declaration"); cil_destroy_sid(sid); cil_clear_node(ast_node); return rc; } void cil_destroy_sid(struct cil_sid *sid) { if (sid == NULL) { return; } cil_symtab_datum_destroy(&sid->datum); free(sid); } int cil_gen_sidcontext(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; size_t syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_sidcontext *sidcon = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_sidcontext_init(&sidcon); sidcon->sid_str = parse_current->next->data; if (parse_current->next->next->cl_head == NULL) { sidcon->context_str = parse_current->next->next->data; } else { cil_context_init(&sidcon->context); rc = cil_fill_context(parse_current->next->next->cl_head, sidcon->context); if (rc != SEPOL_OK) { goto exit; } } ast_node->data = sidcon; ast_node->flavor = CIL_SIDCONTEXT; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad sidcontext declaration"); cil_destroy_sidcontext(sidcon); return rc; } void cil_destroy_sidcontext(struct cil_sidcontext *sidcon) { if (sidcon == NULL) { return; } if (sidcon->context_str == NULL && sidcon->context != NULL) { cil_destroy_context(sidcon->context); } free(sidcon); } int cil_gen_user(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_END }; size_t syntax_len = sizeof(syntax)/sizeof(*syntax); char *key = NULL; struct cil_user *user = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_user_init(&user); key = parse_current->next->data; rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)user, (hashtab_key_t)key, CIL_SYM_USERS, CIL_USER); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad user declaration"); cil_destroy_user(user); cil_clear_node(ast_node); return rc; } void cil_destroy_user(struct cil_user *user) { if (user == NULL) { return; } cil_symtab_datum_destroy(&user->datum); ebitmap_destroy(user->roles); free(user->roles); free(user); } int cil_gen_userattribute(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_END }; size_t syntax_len = sizeof(syntax)/sizeof(*syntax); char *key = NULL; struct cil_userattribute *attr = NULL; int rc = SEPOL_ERR; if (parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_userattribute_init(&attr); key = parse_current->next->data; rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)attr, (hashtab_key_t)key, CIL_SYM_USERS, CIL_USERATTRIBUTE); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad userattribute declaration"); cil_destroy_userattribute(attr); cil_clear_node(ast_node); return rc; } void cil_destroy_userattribute(struct cil_userattribute *attr) { struct cil_list_item *expr = NULL; struct cil_list_item *next = NULL; if (attr == NULL) { return; } if (attr->expr_list != NULL) { /* we don't want to destroy the expression stacks (cil_list) inside * this list cil_list_destroy destroys sublists, so we need to do it * manually */ expr = attr->expr_list->head; while (expr != NULL) { next = expr->next; cil_list_item_destroy(&expr, CIL_FALSE); expr = next; } free(attr->expr_list); attr->expr_list = NULL; } cil_symtab_datum_destroy(&attr->datum); ebitmap_destroy(attr->users); free(attr->users); free(attr); } int cil_gen_userattributeset(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; size_t syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_userattributeset *attrset = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_userattributeset_init(&attrset); attrset->attr_str = parse_current->next->data; rc = cil_gen_expr(parse_current->next->next, CIL_USER, &attrset->str_expr); if (rc != SEPOL_OK) { goto exit; } ast_node->data = attrset; ast_node->flavor = CIL_USERATTRIBUTESET; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad userattributeset declaration"); cil_destroy_userattributeset(attrset); return rc; } void cil_destroy_userattributeset(struct cil_userattributeset *attrset) { if (attrset == NULL) { return; } cil_list_destroy(&attrset->str_expr, CIL_TRUE); cil_list_destroy(&attrset->datum_expr, CIL_FALSE); free(attrset); } int cil_gen_userlevel(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; size_t syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_userlevel *usrlvl = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_userlevel_init(&usrlvl); usrlvl->user_str = parse_current->next->data; if (parse_current->next->next->cl_head == NULL) { usrlvl->level_str = parse_current->next->next->data; } else { cil_level_init(&usrlvl->level); rc = cil_fill_level(parse_current->next->next->cl_head, usrlvl->level); if (rc != SEPOL_OK) { goto exit; } } ast_node->data = usrlvl; ast_node->flavor = CIL_USERLEVEL; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad userlevel declaration"); cil_destroy_userlevel(usrlvl); return rc; } void cil_destroy_userlevel(struct cil_userlevel *usrlvl) { if (usrlvl == NULL) { return; } if (usrlvl->level_str == NULL && usrlvl->level != NULL) { cil_destroy_level(usrlvl->level); } free(usrlvl); } int cil_gen_userrange(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; size_t syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_userrange *userrange = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_userrange_init(&userrange); userrange->user_str = parse_current->next->data; if (parse_current->next->next->cl_head == NULL) { userrange->range_str = parse_current->next->next->data; } else { cil_levelrange_init(&userrange->range); rc = cil_fill_levelrange(parse_current->next->next->cl_head, userrange->range); if (rc != SEPOL_OK) { goto exit; } } ast_node->data = userrange; ast_node->flavor = CIL_USERRANGE; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad userrange declaration"); cil_destroy_userrange(userrange); return rc; } void cil_destroy_userrange(struct cil_userrange *userrange) { if (userrange == NULL) { return; } if (userrange->range_str == NULL && userrange->range != NULL) { cil_destroy_levelrange(userrange->range); } free(userrange); } int cil_gen_userprefix(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_END }; size_t syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_userprefix *userprefix = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_userprefix_init(&userprefix); userprefix->user_str = parse_current->next->data; userprefix->prefix_str = parse_current->next->next->data; ast_node->data = userprefix; ast_node->flavor = CIL_USERPREFIX; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad userprefix declaration"); cil_destroy_userprefix(userprefix); return rc; } void cil_destroy_userprefix(struct cil_userprefix *userprefix) { if (userprefix == NULL) { return; } free(userprefix); } int cil_gen_selinuxuser(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; size_t syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_selinuxuser *selinuxuser = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_selinuxuser_init(&selinuxuser); selinuxuser->name_str = parse_current->next->data; selinuxuser->user_str = parse_current->next->next->data; if (parse_current->next->next->next->cl_head == NULL) { selinuxuser->range_str = parse_current->next->next->next->data; } else { cil_levelrange_init(&selinuxuser->range); rc = cil_fill_levelrange(parse_current->next->next->next->cl_head, selinuxuser->range); if (rc != SEPOL_OK) { goto exit; } } ast_node->data = selinuxuser; ast_node->flavor = CIL_SELINUXUSER; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad selinuxuser declaration"); cil_destroy_selinuxuser(selinuxuser); return rc; } int cil_gen_selinuxuserdefault(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; size_t syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_selinuxuser *selinuxuser = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_selinuxuser_init(&selinuxuser); selinuxuser->name_str = cil_strpool_add("__default__"); selinuxuser->user_str = parse_current->next->data; if (parse_current->next->next->cl_head == NULL) { selinuxuser->range_str = parse_current->next->next->data; } else { cil_levelrange_init(&selinuxuser->range); rc = cil_fill_levelrange(parse_current->next->next->cl_head, selinuxuser->range); if (rc != SEPOL_OK) { goto exit; } } ast_node->data = selinuxuser; ast_node->flavor = CIL_SELINUXUSERDEFAULT; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad selinuxuserdefault declaration"); cil_destroy_selinuxuser(selinuxuser); return rc; } void cil_destroy_selinuxuser(struct cil_selinuxuser *selinuxuser) { if (selinuxuser == NULL) { return; } if (selinuxuser->range_str == NULL && selinuxuser->range != NULL) { cil_destroy_levelrange(selinuxuser->range); } free(selinuxuser); } int cil_gen_role(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_END }; size_t 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) { if (rc == SEPOL_EEXIST) { cil_destroy_role(role); role = NULL; } else { goto exit; } } return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad role declaration"); cil_destroy_role(role); cil_clear_node(ast_node); return rc; } void cil_destroy_role(struct cil_role *role) { if (role == NULL) { return; } cil_symtab_datum_destroy(&role->datum); ebitmap_destroy(role->types); free(role->types); free(role); } int cil_gen_roletype(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_END }; size_t syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_roletype *roletype = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_roletype_init(&roletype); roletype->role_str = parse_current->next->data; roletype->type_str = parse_current->next->next->data; ast_node->data = roletype; ast_node->flavor = CIL_ROLETYPE; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad roletype declaration"); cil_destroy_roletype(roletype); return rc; } void cil_destroy_roletype(struct cil_roletype *roletype) { if (roletype == NULL) { return; } free(roletype); } int cil_gen_userrole(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_END }; size_t syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_userrole *userrole = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_userrole_init(&userrole); userrole->user_str = parse_current->next->data; userrole->role_str = parse_current->next->next->data; ast_node->data = userrole; ast_node->flavor = CIL_USERROLE; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad userrole declaration"); cil_destroy_userrole(userrole); return rc; } void cil_destroy_userrole(struct cil_userrole *userrole) { if (userrole == NULL) { return; } free(userrole); } int cil_gen_roletransition(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_END }; size_t syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_roletransition *roletrans = NULL; int rc = SEPOL_ERR; if (parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_roletransition_init(&roletrans); roletrans->src_str = parse_current->next->data; roletrans->tgt_str = parse_current->next->next->data; roletrans->obj_str = parse_current->next->next->next->data; roletrans->result_str = parse_current->next->next->next->next->data; ast_node->data = roletrans; ast_node->flavor = CIL_ROLETRANSITION; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad roletransition rule"); cil_destroy_roletransition(roletrans); return rc; } void cil_destroy_roletransition(struct cil_roletransition *roletrans) { if (roletrans == NULL) { return; } free(roletrans); } int cil_gen_roleallow(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_END }; size_t syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_roleallow *roleallow = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_roleallow_init(&roleallow); roleallow->src_str = parse_current->next->data; roleallow->tgt_str = parse_current->next->next->data; ast_node->data = roleallow; ast_node->flavor = CIL_ROLEALLOW; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad roleallow rule"); cil_destroy_roleallow(roleallow); return rc; } void cil_destroy_roleallow(struct cil_roleallow *roleallow) { if (roleallow == NULL) { return; } free(roleallow); } int cil_gen_roleattribute(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_END }; size_t 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; } cil_roleattribute_init(&attr); key = parse_current->next->data; rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)attr, (hashtab_key_t)key, CIL_SYM_ROLES, CIL_ROLEATTRIBUTE); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad roleattribute declaration"); cil_destroy_roleattribute(attr); cil_clear_node(ast_node); return rc; } void cil_destroy_roleattribute(struct cil_roleattribute *attr) { if (attr == NULL) { return; } if (attr->expr_list != NULL) { /* we don't want to destroy the expression stacks (cil_list) inside * this list cil_list_destroy destroys sublists, so we need to do it * manually */ struct cil_list_item *expr = attr->expr_list->head; while (expr != NULL) { struct cil_list_item *next = expr->next; cil_list_item_destroy(&expr, CIL_FALSE); expr = next; } free(attr->expr_list); attr->expr_list = NULL; } cil_symtab_datum_destroy(&attr->datum); ebitmap_destroy(attr->roles); free(attr->roles); free(attr); } int cil_gen_roleattributeset(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; size_t syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_roleattributeset *attrset = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_roleattributeset_init(&attrset); attrset->attr_str = parse_current->next->data; rc = cil_gen_expr(parse_current->next->next, CIL_ROLE, &attrset->str_expr); if (rc != SEPOL_OK) { goto exit; } ast_node->data = attrset; ast_node->flavor = CIL_ROLEATTRIBUTESET; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad roleattributeset declaration"); cil_destroy_roleattributeset(attrset); return rc; } void cil_destroy_roleattributeset(struct cil_roleattributeset *attrset) { if (attrset == NULL) { return; } cil_list_destroy(&attrset->str_expr, CIL_TRUE); cil_list_destroy(&attrset->datum_expr, CIL_FALSE); free(attrset); } int cil_gen_avrule(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, uint32_t rule_kind) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; size_t syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_avrule *rule = NULL; int rc = SEPOL_ERR; if (parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_avrule_init(&rule); rule->is_extended = 0; rule->rule_kind = rule_kind; rule->src_str = parse_current->next->data; rule->tgt_str = parse_current->next->next->data; rc = cil_fill_classperms_list(parse_current->next->next->next, &rule->perms.classperms); if (rc != SEPOL_OK) { goto exit; } ast_node->data = rule; ast_node->flavor = CIL_AVRULE; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad allow rule"); cil_destroy_avrule(rule); return rc; } void cil_destroy_avrule(struct cil_avrule *rule) { if (rule == NULL) { return; } if (!rule->is_extended) { cil_destroy_classperms_list(&rule->perms.classperms); } else { if (rule->perms.x.permx_str == NULL && rule->perms.x.permx != NULL) { cil_destroy_permissionx(rule->perms.x.permx); } } free(rule); } static int cil_fill_permissionx(struct cil_tree_node *parse_current, struct cil_permissionx *permx) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_LIST, CIL_SYN_END }; size_t syntax_len = sizeof(syntax)/sizeof(*syntax); int rc = SEPOL_ERR; rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } if (parse_current->data == CIL_KEY_IOCTL) { permx->kind = CIL_PERMX_KIND_IOCTL; } else if (parse_current->data == CIL_KEY_NLMSG) { permx->kind = CIL_PERMX_KIND_NLMSG; } else { cil_log(CIL_ERR, "Unknown permissionx kind, %s. Must be \"ioctl\" or \"nlmsg\"\n", (char *)parse_current->data); rc = SEPOL_ERR; goto exit; } permx->obj_str = parse_current->next->data; rc = cil_gen_expr(parse_current->next->next, CIL_PERMISSIONX, &permx->expr_str); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad permissionx content"); return rc; } int cil_gen_permissionx(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_LIST, CIL_SYN_END }; size_t syntax_len = sizeof(syntax)/sizeof(*syntax); char *key = NULL; struct cil_permissionx *permx = NULL; int rc = SEPOL_ERR; if (parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_permissionx_init(&permx); key = parse_current->next->data; rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)permx, (hashtab_key_t)key, CIL_SYM_PERMX, CIL_PERMISSIONX); if (rc != SEPOL_OK) { goto exit; } rc = cil_fill_permissionx(parse_current->next->next->cl_head, permx); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad permissionx statement"); cil_destroy_permissionx(permx); cil_clear_node(ast_node); return rc; } void cil_destroy_permissionx(struct cil_permissionx *permx) { if (permx == NULL) { return; } cil_symtab_datum_destroy(&permx->datum); cil_list_destroy(&permx->expr_str, CIL_TRUE); ebitmap_destroy(permx->perms); free(permx->perms); free(permx); } int cil_gen_avrulex(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, uint32_t rule_kind) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; size_t syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_avrule *rule = NULL; int rc = SEPOL_ERR; if (parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_avrule_init(&rule); rule->is_extended = 1; rule->rule_kind = rule_kind; rule->src_str = parse_current->next->data; rule->tgt_str = parse_current->next->next->data; if (parse_current->next->next->next->cl_head == NULL) { rule->perms.x.permx_str = parse_current->next->next->next->data; } else { cil_permissionx_init(&rule->perms.x.permx); rc = cil_fill_permissionx(parse_current->next->next->next->cl_head, rule->perms.x.permx); if (rc != SEPOL_OK) { goto exit; } } ast_node->data = rule; ast_node->flavor = CIL_AVRULEX; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad allowx rule"); cil_destroy_avrule(rule); return rc; } int cil_gen_deny_rule(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 }; size_t syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_deny_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_deny_rule_init(&rule); 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_DENY_RULE; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad deny rule"); cil_destroy_deny_rule(rule); return rc; } void cil_destroy_deny_rule(struct cil_deny_rule *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 }; size_t syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_type_rule *rule = NULL; int rc = SEPOL_ERR; if (parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_type_rule_init(&rule); rule->rule_kind = rule_kind; rule->src_str = parse_current->next->data; rule->tgt_str = parse_current->next->next->data; rule->obj_str = parse_current->next->next->next->data; rule->result_str = parse_current->next->next->next->next->data; ast_node->data = rule; ast_node->flavor = CIL_TYPE_RULE; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad type rule"); cil_destroy_type_rule(rule); return rc; } void cil_destroy_type_rule(struct cil_type_rule *rule) { if (rule == NULL) { return; } free(rule); } int cil_gen_type(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_END }; size_t 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; } 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) { if (rc == SEPOL_EEXIST) { cil_destroy_type(type); type = NULL; } else { goto exit; } } return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad type declaration"); cil_destroy_type(type); cil_clear_node(ast_node); return rc; } void cil_destroy_type(struct cil_type *type) { if (type == NULL) { return; } cil_symtab_datum_destroy(&type->datum); free(type); } int cil_gen_typeattribute(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_END }; size_t 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; } 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) { if (rc == SEPOL_EEXIST) { cil_destroy_typeattribute(attr); attr = NULL; } else { goto exit; } } return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad typeattribute declaration"); cil_destroy_typeattribute(attr); cil_clear_node(ast_node); return rc; } void cil_destroy_typeattribute(struct cil_typeattribute *attr) { if (attr == NULL) { return; } cil_symtab_datum_destroy(&attr->datum); if (attr->expr_list != NULL) { /* we don't want to destroy the expression stacks (cil_list) inside * this list cil_list_destroy destroys sublists, so we need to do it * manually */ struct cil_list_item *expr = attr->expr_list->head; while (expr != NULL) { struct cil_list_item *next = expr->next; cil_list_item_destroy(&expr, CIL_FALSE); expr = next; } free(attr->expr_list); attr->expr_list = NULL; } ebitmap_destroy(attr->types); free(attr->types); free(attr); } int cil_gen_bool(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, int tunableif) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_END }; size_t syntax_len = sizeof(syntax)/sizeof(*syntax); char *key = NULL; struct cil_bool *boolean = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_bool_init(&boolean); key = parse_current->next->data; if (parse_current->next->next->data == CIL_KEY_CONDTRUE) { boolean->value = CIL_TRUE; } else if (parse_current->next->next->data == CIL_KEY_CONDFALSE) { boolean->value = CIL_FALSE; } else { cil_log(CIL_ERR, "Value must be either \'true\' or \'false\'"); rc = SEPOL_ERR; goto exit; } rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)boolean, (hashtab_key_t)key, CIL_SYM_BOOLS, CIL_BOOL); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: if (tunableif) { cil_tree_log(parse_current, CIL_ERR, "Bad tunable (treated as a boolean due to preserve-tunables) declaration"); } else { cil_tree_log(parse_current, CIL_ERR, "Bad boolean declaration"); } cil_destroy_bool(boolean); cil_clear_node(ast_node); return rc; } void cil_destroy_bool(struct cil_bool *boolean) { if (boolean == NULL) { return; } cil_symtab_datum_destroy(&boolean->datum); free(boolean); } int cil_gen_tunable(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_END }; size_t syntax_len = sizeof(syntax)/sizeof(*syntax); char *key = NULL; struct cil_tunable *tunable = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_tunable_init(&tunable); key = parse_current->next->data; if (parse_current->next->next->data == CIL_KEY_CONDTRUE) { tunable->value = CIL_TRUE; } else if (parse_current->next->next->data == CIL_KEY_CONDFALSE) { tunable->value = CIL_FALSE; } else { cil_log(CIL_ERR, "Value must be either \'true\' or \'false\'"); rc = SEPOL_ERR; goto exit; } rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)tunable, (hashtab_key_t)key, CIL_SYM_TUNABLES, CIL_TUNABLE); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad tunable declaration"); cil_destroy_tunable(tunable); cil_clear_node(ast_node); return rc; } void cil_destroy_tunable(struct cil_tunable *tunable) { if (tunable == NULL) { return; } cil_symtab_datum_destroy(&tunable->datum); free(tunable); } static enum cil_flavor __cil_get_expr_operator_flavor(const char *op) { if (op == NULL) return CIL_NONE; else if (op == CIL_KEY_AND) return CIL_AND; else if (op == CIL_KEY_OR) return CIL_OR; else if (op == CIL_KEY_NOT) return CIL_NOT; else if (op == CIL_KEY_EQ) return CIL_EQ; /* Only conditional */ else if (op == CIL_KEY_NEQ) return CIL_NEQ; /* Only conditional */ else if (op == CIL_KEY_XOR) return CIL_XOR; else if (op == CIL_KEY_ALL) return CIL_ALL; /* Only set and permissionx */ else if (op == CIL_KEY_RANGE) return CIL_RANGE; /* Only catset and permissionx */ else return CIL_NONE; } static int __cil_fill_expr(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list *expr); static int __cil_fill_expr_helper(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list *expr) { int rc = SEPOL_ERR; enum cil_flavor op; 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; } for (;current != NULL; current = current->next) { rc = __cil_fill_expr(current, flavor, expr); if (rc != SEPOL_OK) { goto exit; } } 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 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); if (rc != SEPOL_OK) { cil_list_destroy(&sub_expr, CIL_TRUE); goto exit; } cil_list_append(expr, CIL_LIST, sub_expr); } return SEPOL_OK; exit: return rc; } int cil_gen_expr(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list **expr) { int rc = SEPOL_ERR; cil_list_init(expr, flavor); if (current->cl_head == NULL) { rc = __cil_fill_expr(current, flavor, *expr); } else { rc = __cil_fill_expr_helper(current->cl_head, flavor, *expr); } 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; rc = cil_fill_list(current->next->next->cl_head, leaf_expr_flavor, &sub_list); if (rc != SEPOL_OK) { cil_list_destroy(leaf_expr, CIL_TRUE); goto exit; } 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 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; } 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: 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); 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); if (rc != SEPOL_OK) { goto exit; } rc = __cil_fill_constraint_expr(current->next->next->cl_head, flavor, &rexpr); if (rc != SEPOL_OK) { cil_list_destroy(&lexpr, CIL_TRUE); goto exit; } cil_list_init(expr, flavor); cil_list_append(*expr, CIL_OP, (void *)op); cil_list_append(*expr, CIL_LIST, lexpr); cil_list_append(*expr, CIL_LIST, rexpr); break; } return SEPOL_OK; exit: return rc; } static int cil_gen_constraint_expr(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list **expr) { int rc = SEPOL_ERR; if (current->cl_head == NULL) { goto exit; } rc = __cil_fill_constraint_expr(current->cl_head, flavor, expr); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: cil_log(CIL_ERR, "Bad expression tree for constraint\n"); return rc; } int cil_gen_boolif(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, int tunableif) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_LIST, CIL_SYN_LIST | CIL_SYN_END, CIL_SYN_END }; size_t syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_booleanif *bif = NULL; struct cil_tree_node *next = 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; } rc = cil_verify_conditional_blocks(parse_current->next->next); if (rc != SEPOL_OK) { goto exit; } /* Destroying expr tree */ next = parse_current->next->next; cil_tree_subtree_destroy(parse_current->next); parse_current->next = next; ast_node->flavor = CIL_BOOLEANIF; ast_node->data = bif; return SEPOL_OK; exit: if (tunableif) { cil_tree_log(parse_current, CIL_ERR, "Bad tunableif (treated as a booleanif due to preserve-tunables) declaration"); } else { cil_tree_log(parse_current, CIL_ERR, "Bad booleanif declaration"); } cil_destroy_boolif(bif); return rc; } void cil_destroy_boolif(struct cil_booleanif *bif) { if (bif == NULL) { return; } cil_list_destroy(&bif->str_expr, CIL_TRUE); cil_list_destroy(&bif->datum_expr, CIL_FALSE); free(bif); } int cil_gen_tunif(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_LIST, CIL_SYN_LIST | CIL_SYN_END, CIL_SYN_END }; size_t syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_tunableif *tif = NULL; struct cil_tree_node *next = 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; } rc = cil_verify_conditional_blocks(parse_current->next->next); if (rc != SEPOL_OK) { goto exit; } /* Destroying expr tree */ next = parse_current->next->next; cil_tree_subtree_destroy(parse_current->next); parse_current->next = next; ast_node->flavor = CIL_TUNABLEIF; ast_node->data = tif; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad tunableif declaration"); cil_destroy_tunif(tif); return rc; } void cil_destroy_tunif(struct cil_tunableif *tif) { if (tif == NULL) { return; } cil_list_destroy(&tif->str_expr, CIL_TRUE); cil_list_destroy(&tif->datum_expr, CIL_FALSE); free(tif); } int cil_gen_condblock(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_N_LISTS, CIL_SYN_END }; size_t syntax_len = sizeof(syntax)/sizeof(*syntax); int rc = SEPOL_ERR; struct cil_condblock *cb = NULL; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } if (ast_node->parent->flavor != CIL_BOOLEANIF && ast_node->parent->flavor != CIL_TUNABLEIF) { rc = SEPOL_ERR; cil_log(CIL_ERR, "Conditional statements must be a direct child of a tunableif or booleanif statement.\n"); goto exit; } ast_node->flavor = CIL_CONDBLOCK; cil_condblock_init(&cb); cb->flavor = flavor; ast_node->data = cb; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad %s condition declaration", (char*)parse_current->data); cil_destroy_condblock(cb); return rc; } void cil_destroy_condblock(struct cil_condblock *cb) { if (cb == NULL) { return; } cil_symtab_array_destroy(cb->symtab); free(cb); } int cil_gen_alias(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_END }; size_t 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; } cil_alias_init(&alias); key = parse_current->next->data; rc = cil_flavor_to_symtab_index(flavor, &sym_index); if (rc != SEPOL_OK) { goto exit; } rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)alias, (hashtab_key_t)key, sym_index, flavor); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad %s declaration", (char*)parse_current->data); cil_destroy_alias(alias); cil_clear_node(ast_node); return rc; } void cil_destroy_alias(struct cil_alias *alias) { if (alias == NULL) { return; } cil_symtab_datum_destroy(&alias->datum); alias->actual = NULL; free(alias); } int cil_gen_aliasactual(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor) { int rc = SEPOL_ERR; enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_END }; size_t 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; } cil_aliasactual_init(&aliasactual); aliasactual->alias_str = parse_current->next->data; aliasactual->actual_str = parse_current->next->next->data; ast_node->data = aliasactual; ast_node->flavor = flavor; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad %s association", cil_node_to_string(parse_current)); cil_clear_node(ast_node); return rc; } void cil_destroy_aliasactual(struct cil_aliasactual *aliasactual) { if (aliasactual == NULL) { return; } free(aliasactual); } int cil_gen_typeattributeset(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; size_t syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_typeattributeset *attrset = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_typeattributeset_init(&attrset); attrset->attr_str = parse_current->next->data; rc = cil_gen_expr(parse_current->next->next, CIL_TYPE, &attrset->str_expr); if (rc != SEPOL_OK) { goto exit; } ast_node->data = attrset; ast_node->flavor = CIL_TYPEATTRIBUTESET; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad typeattributeset statement"); cil_destroy_typeattributeset(attrset); return rc; } void cil_destroy_typeattributeset(struct cil_typeattributeset *attrset) { if (attrset == NULL) { return; } cil_list_destroy(&attrset->str_expr, CIL_TRUE); cil_list_destroy(&attrset->datum_expr, CIL_FALSE); free(attrset); } int cil_gen_expandtypeattribute(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_STRING, CIL_SYN_END }; char *expand_str; size_t syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_expandtypeattribute *expandattr = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_expandtypeattribute_init(&expandattr); if (parse_current->next->cl_head == NULL) { cil_list_init(&expandattr->attr_strs, CIL_TYPE); cil_list_append(expandattr->attr_strs, CIL_STRING, parse_current->next->data); } else { rc = cil_fill_list(parse_current->next->cl_head, CIL_TYPE, &expandattr->attr_strs); if (rc != SEPOL_OK) { goto exit; } } expand_str = parse_current->next->next->data; if (expand_str == CIL_KEY_CONDTRUE) { expandattr->expand = CIL_TRUE; } else if (expand_str == CIL_KEY_CONDFALSE) { expandattr->expand = CIL_FALSE; } else { cil_log(CIL_ERR, "Value must be either \'true\' or \'false\'"); rc = SEPOL_ERR; goto exit; } ast_node->data = expandattr; ast_node->flavor = CIL_EXPANDTYPEATTRIBUTE; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad expandtypeattribute statement"); cil_destroy_expandtypeattribute(expandattr); return rc; } void cil_destroy_expandtypeattribute(struct cil_expandtypeattribute *expandattr) { if (expandattr == NULL) { return; } cil_list_destroy(&expandattr->attr_strs, CIL_TRUE); cil_list_destroy(&expandattr->attr_datums, CIL_FALSE); free(expandattr); } int cil_gen_typepermissive(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_END }; size_t syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_typepermissive *typeperm = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_typepermissive_init(&typeperm); typeperm->type_str = parse_current->next->data; ast_node->data = typeperm; ast_node->flavor = CIL_TYPEPERMISSIVE; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad typepermissive declaration"); cil_destroy_typepermissive(typeperm); return rc; } void cil_destroy_typepermissive(struct cil_typepermissive *typeperm) { if (typeperm == NULL) { return; } free(typeperm); } int cil_gen_typetransition(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { int rc = SEPOL_ERR; enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_END, CIL_SYN_END }; size_t 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); ast_node->data = nametypetrans; ast_node->flavor = CIL_NAMETYPETRANSITION; nametypetrans->src_str = s1; nametypetrans->tgt_str = s2; nametypetrans->obj_str = s3; nametypetrans->name_str = s4; nametypetrans->name = cil_gen_declared_string(db, s4, ast_node); nametypetrans->result_str = s5; } else { struct cil_type_rule *rule = NULL; cil_type_rule_init(&rule); ast_node->data = rule; ast_node->flavor = CIL_TYPE_RULE; rule->rule_kind = CIL_TYPE_TRANSITION; rule->src_str = s1; rule->tgt_str = s2; rule->obj_str = s3; rule->result_str = s4; } return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad typetransition declaration"); return rc; } void cil_destroy_typetransition(struct cil_nametypetransition *nametypetrans) { if (nametypetrans == NULL) { return; } free(nametypetrans); } int cil_gen_rangetransition(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; size_t syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_rangetransition *rangetrans = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL ) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_rangetransition_init(&rangetrans); rangetrans->src_str = parse_current->next->data; rangetrans->exec_str = parse_current->next->next->data; rangetrans->obj_str = parse_current->next->next->next->data; rangetrans->range_str = NULL; if (parse_current->next->next->next->next->cl_head == NULL) { rangetrans->range_str = parse_current->next->next->next->next->data; } else { cil_levelrange_init(&rangetrans->range); rc = cil_fill_levelrange(parse_current->next->next->next->next->cl_head, rangetrans->range); if (rc != SEPOL_OK) { goto exit; } } ast_node->data = rangetrans; ast_node->flavor = CIL_RANGETRANSITION; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad rangetransition declaration"); cil_destroy_rangetransition(rangetrans); return rc; } void cil_destroy_rangetransition(struct cil_rangetransition *rangetrans) { if (rangetrans == NULL) { return; } if (rangetrans->range_str == NULL && rangetrans->range != NULL) { cil_destroy_levelrange(rangetrans->range); } free(rangetrans); } int cil_gen_sensitivity(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_END }; size_t syntax_len = sizeof(syntax)/sizeof(*syntax); char *key = NULL; struct cil_sens *sens = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_sens_init(&sens); key = parse_current->next->data; rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)sens, (hashtab_key_t)key, CIL_SYM_SENS, CIL_SENS); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad sensitivity declaration"); cil_destroy_sensitivity(sens); cil_clear_node(ast_node); return rc; } void cil_destroy_sensitivity(struct cil_sens *sens) { if (sens == NULL) { return; } cil_symtab_datum_destroy(&sens->datum); cil_list_destroy(&sens->cats_list, CIL_FALSE); free(sens); } int cil_gen_category(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_END }; size_t syntax_len = sizeof(syntax)/sizeof(*syntax); char *key = NULL; struct cil_cat *cat = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_cat_init(&cat); key = parse_current->next->data; rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)cat, (hashtab_key_t)key, CIL_SYM_CATS, CIL_CAT); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad category declaration"); cil_destroy_category(cat); cil_clear_node(ast_node); return rc; } void cil_destroy_category(struct cil_cat *cat) { if (cat == NULL) { return; } cil_symtab_datum_destroy(&cat->datum); free(cat); } static int cil_gen_catset(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_LIST, CIL_SYN_END }; size_t syntax_len = sizeof(syntax)/sizeof(*syntax); char *key = NULL; struct cil_catset *catset = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_catset_init(&catset); key = parse_current->next->data; rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)catset, (hashtab_key_t)key, CIL_SYM_CATS, CIL_CATSET); if (rc != SEPOL_OK) { goto exit; } rc = cil_fill_cats(parse_current->next->next, &catset->cats); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad categoryset declaration"); cil_destroy_catset(catset); cil_clear_node(ast_node); return rc; } void cil_destroy_catset(struct cil_catset *catset) { if (catset == NULL) { return; } cil_symtab_datum_destroy(&catset->datum); cil_destroy_cats(catset->cats); free(catset); } int cil_gen_senscat(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; size_t syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_senscat *senscat = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_senscat_init(&senscat); senscat->sens_str = parse_current->next->data; rc = cil_fill_cats(parse_current->next->next, &senscat->cats); if (rc != SEPOL_OK) { goto exit; } ast_node->data = senscat; ast_node->flavor = CIL_SENSCAT; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad sensitivitycategory declaration"); cil_destroy_senscat(senscat); return rc; } void cil_destroy_senscat(struct cil_senscat *senscat) { if (senscat == NULL) { return; } cil_destroy_cats(senscat->cats); free(senscat); } int cil_gen_level(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_LIST, CIL_SYN_END }; size_t syntax_len = sizeof(syntax)/sizeof(*syntax); char *key = NULL; struct cil_level *level = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_level_init(&level); key = parse_current->next->data; rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)level, (hashtab_key_t)key, CIL_SYM_LEVELS, CIL_LEVEL); if (rc != SEPOL_OK) { goto exit; } rc = cil_fill_level(parse_current->next->next->cl_head, level); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad level declaration"); cil_destroy_level(level); cil_clear_node(ast_node); return rc; } void cil_destroy_level(struct cil_level *level) { if (level == NULL) { return; } cil_symtab_datum_destroy(&level->datum); cil_destroy_cats(level->cats); free(level); } /* low should be pointing to either the name of the low level or to an open paren for an anonymous low level */ int cil_fill_levelrange(struct cil_tree_node *low, struct cil_levelrange *lvlrange) { enum cil_syntax syntax[] = { CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; size_t syntax_len = sizeof(syntax)/sizeof(*syntax); int rc = SEPOL_ERR; if (low == NULL || lvlrange == NULL) { goto exit; } rc = __cil_verify_syntax(low, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } if (low->cl_head == NULL) { lvlrange->low_str = low->data; } else { cil_level_init(&lvlrange->low); rc = cil_fill_level(low->cl_head, lvlrange->low); if (rc != SEPOL_OK) { goto exit; } } if (low->next->cl_head == NULL) { lvlrange->high_str = low->next->data; } else { cil_level_init(&lvlrange->high); rc = cil_fill_level(low->next->cl_head, lvlrange->high); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: cil_log(CIL_ERR, "Bad levelrange\n"); return rc; } int cil_gen_levelrange(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_LIST, CIL_SYN_END }; size_t syntax_len = sizeof(syntax)/sizeof(*syntax); char *key = NULL; struct cil_levelrange *lvlrange = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_levelrange_init(&lvlrange); key = parse_current->next->data; rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)lvlrange, (hashtab_key_t)key, CIL_SYM_LEVELRANGES, CIL_LEVELRANGE); if (rc != SEPOL_OK) { goto exit; } rc = cil_fill_levelrange(parse_current->next->next->cl_head, lvlrange); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad levelrange declaration"); cil_destroy_levelrange(lvlrange); cil_clear_node(ast_node); return rc; } void cil_destroy_levelrange(struct cil_levelrange *lvlrange) { if (lvlrange == NULL) { return; } cil_symtab_datum_destroy(&lvlrange->datum); if (lvlrange->low_str == NULL) { cil_destroy_level(lvlrange->low); } if (lvlrange->high_str == NULL) { cil_destroy_level(lvlrange->high); } free(lvlrange); } int cil_gen_constrain(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_LIST, CIL_SYN_END }; size_t syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_constrain *cons = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_constrain_init(&cons); rc = cil_fill_classperms_list(parse_current->next, &cons->classperms); if (rc != SEPOL_OK) { goto exit; } rc = cil_gen_constraint_expr(parse_current->next->next, flavor, &cons->str_expr); if (rc != SEPOL_OK) { goto exit; } ast_node->data = cons; ast_node->flavor = flavor; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad constrain declaration"); cil_destroy_constrain(cons); return rc; } void cil_destroy_constrain(struct cil_constrain *cons) { if (cons == NULL) { return; } cil_destroy_classperms_list(&cons->classperms); cil_list_destroy(&cons->str_expr, CIL_TRUE); cil_list_destroy(&cons->datum_expr, CIL_FALSE); free(cons); } int cil_gen_validatetrans(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_LIST, CIL_SYN_END }; size_t syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_validatetrans *validtrans = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_validatetrans_init(&validtrans); validtrans->class_str = parse_current->next->data; rc = cil_gen_constraint_expr(parse_current->next->next, flavor, &validtrans->str_expr); if (rc != SEPOL_OK) { goto exit; } ast_node->data = validtrans; ast_node->flavor = flavor; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad validatetrans declaration"); cil_destroy_validatetrans(validtrans); return rc; } void cil_destroy_validatetrans(struct cil_validatetrans *validtrans) { if (validtrans == NULL) { return; } cil_list_destroy(&validtrans->str_expr, CIL_TRUE); cil_list_destroy(&validtrans->datum_expr, CIL_FALSE); free(validtrans); } /* Fills in context starting from user */ int cil_fill_context(struct cil_tree_node *user_node, struct cil_context *context) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; size_t syntax_len = sizeof(syntax)/sizeof(*syntax); int rc = SEPOL_ERR; if (user_node == NULL || context == NULL) { goto exit; } rc = __cil_verify_syntax(user_node, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } context->user_str = user_node->data; context->role_str = user_node->next->data; context->type_str = user_node->next->next->data; context->range_str = NULL; if (user_node->next->next->next->cl_head == NULL) { context->range_str = user_node->next->next->next->data; } else { cil_levelrange_init(&context->range); rc = cil_fill_levelrange(user_node->next->next->next->cl_head, context->range); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: cil_log(CIL_ERR, "Bad context\n"); return rc; } int cil_gen_context(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_LIST, CIL_SYN_END }; size_t syntax_len = sizeof(syntax)/sizeof(*syntax); char *key = NULL; struct cil_context *context = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_context_init(&context); key = parse_current->next->data; rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)context, (hashtab_key_t)key, CIL_SYM_CONTEXTS, CIL_CONTEXT); if (rc != SEPOL_OK) { goto exit; } rc = cil_fill_context(parse_current->next->next->cl_head, context); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad context declaration"); cil_destroy_context(context); cil_clear_node(ast_node); return SEPOL_ERR; } void cil_destroy_context(struct cil_context *context) { if (context == NULL) { return; } cil_symtab_datum_destroy(&context->datum); if (context->range_str == NULL && context->range != NULL) { cil_destroy_levelrange(context->range); } free(context); } int cil_gen_filecon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST | CIL_SYN_EMPTY_LIST, CIL_SYN_END }; size_t 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); ast_node->data = filecon; ast_node->flavor = CIL_FILECON; filecon->path_str = parse_current->next->data; /* filecon->path will be NULL if in a macro and the path is an argument */ filecon->path = cil_gen_declared_string(db, filecon->path_str, ast_node); if (type == CIL_KEY_ANY) { filecon->type = CIL_FILECON_ANY; } else 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 { 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; } } } return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad filecon declaration"); cil_destroy_filecon(filecon); cil_clear_node(ast_node); return rc; } //TODO: Should we be checking if the pointer is NULL when passed in? void cil_destroy_filecon(struct cil_filecon *filecon) { if (filecon == NULL) { return; } if (filecon->context_str == NULL && filecon->context != NULL) { cil_destroy_context(filecon->context); } free(filecon); } int cil_gen_ibpkeycon(__attribute__((unused)) struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; size_t syntax_len = sizeof(syntax) / sizeof(*syntax); int rc = SEPOL_ERR; struct cil_ibpkeycon *ibpkeycon = NULL; if (!parse_current || !ast_node) goto exit; rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) goto exit; cil_ibpkeycon_init(&ibpkeycon); ibpkeycon->subnet_prefix_str = parse_current->next->data; if (parse_current->next->next->cl_head) { if (parse_current->next->next->cl_head->next && !parse_current->next->next->cl_head->next->next) { rc = cil_fill_integer(parse_current->next->next->cl_head, &ibpkeycon->pkey_low, 0); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Improper ibpkey specified\n"); goto exit; } rc = cil_fill_integer(parse_current->next->next->cl_head->next, &ibpkeycon->pkey_high, 0); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Improper ibpkey specified\n"); goto exit; } } else { cil_log(CIL_ERR, "Improper ibpkey range specified\n"); rc = SEPOL_ERR; goto exit; } } else { rc = cil_fill_integer(parse_current->next->next, &ibpkeycon->pkey_low, 0); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Improper ibpkey specified\n"); goto exit; } ibpkeycon->pkey_high = ibpkeycon->pkey_low; } if (!parse_current->next->next->next->cl_head) { ibpkeycon->context_str = parse_current->next->next->next->data; } else { cil_context_init(&ibpkeycon->context); rc = cil_fill_context(parse_current->next->next->next->cl_head, ibpkeycon->context); if (rc != SEPOL_OK) goto exit; } ast_node->data = ibpkeycon; ast_node->flavor = CIL_IBPKEYCON; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad ibpkeycon declaration"); cil_destroy_ibpkeycon(ibpkeycon); return rc; } void cil_destroy_ibpkeycon(struct cil_ibpkeycon *ibpkeycon) { if (!ibpkeycon) return; if (!ibpkeycon->context_str && ibpkeycon->context) cil_destroy_context(ibpkeycon->context); free(ibpkeycon); } int cil_gen_portcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; size_t syntax_len = sizeof(syntax)/sizeof(*syntax); int rc = SEPOL_ERR; struct cil_portcon *portcon = NULL; char *proto; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_portcon_init(&portcon); proto = parse_current->next->data; if (proto == CIL_KEY_UDP) { portcon->proto = CIL_PROTOCOL_UDP; } else if (proto == CIL_KEY_TCP) { portcon->proto = CIL_PROTOCOL_TCP; } else if (proto == CIL_KEY_DCCP) { portcon->proto = CIL_PROTOCOL_DCCP; } else if (proto == CIL_KEY_SCTP) { portcon->proto = CIL_PROTOCOL_SCTP; } else { cil_log(CIL_ERR, "Invalid protocol\n"); rc = SEPOL_ERR; goto exit; } if (parse_current->next->next->cl_head != NULL) { if (parse_current->next->next->cl_head->next != NULL && parse_current->next->next->cl_head->next->next == NULL) { rc = cil_fill_integer(parse_current->next->next->cl_head, &portcon->port_low, 10); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Improper port specified\n"); goto exit; } rc = cil_fill_integer(parse_current->next->next->cl_head->next, &portcon->port_high, 10); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Improper port specified\n"); goto exit; } } else { cil_log(CIL_ERR, "Improper port range specified\n"); rc = SEPOL_ERR; goto exit; } } else { rc = cil_fill_integer(parse_current->next->next, &portcon->port_low, 10); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Improper port specified\n"); goto exit; } portcon->port_high = portcon->port_low; } if (parse_current->next->next->next->cl_head == NULL ) { portcon->context_str = parse_current->next->next->next->data; } else { cil_context_init(&portcon->context); rc = cil_fill_context(parse_current->next->next->next->cl_head, portcon->context); if (rc != SEPOL_OK) { goto exit; } } ast_node->data = portcon; ast_node->flavor = CIL_PORTCON; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad portcon declaration"); cil_destroy_portcon(portcon); return rc; } void cil_destroy_portcon(struct cil_portcon *portcon) { if (portcon == NULL) { return; } if (portcon->context_str == NULL && portcon->context != NULL) { cil_destroy_context(portcon->context); } free(portcon); } int cil_gen_nodecon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; size_t 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) { cil_ipaddr_init(&nodecon->addr); rc = cil_fill_ipaddr(parse_current->next->cl_head, nodecon->addr); if (rc != SEPOL_OK) { goto exit; } } else { char *addr = parse_current->next->data; if (strchr(addr, ':') || (strchr(addr, '.') && isdigit(addr[0]))) { cil_ipaddr_init(&nodecon->addr); rc = cil_fill_ipaddr(parse_current->next, nodecon->addr); if (rc != SEPOL_OK) { goto exit; } } else { nodecon->addr_str = addr; } } if (parse_current->next->next->cl_head) { cil_ipaddr_init(&nodecon->mask); rc = cil_fill_ipaddr(parse_current->next->next->cl_head, nodecon->mask); if (rc != SEPOL_OK) { goto exit; } } else { char *mask = parse_current->next->next->data; if (strchr(mask, ':') || (strchr(mask, '.') && isdigit(mask[0]))) { cil_ipaddr_init(&nodecon->mask); rc = cil_fill_ipaddr(parse_current->next->next, nodecon->mask); if (rc != SEPOL_OK) { goto exit; } } else { nodecon->mask_str = mask; } } if (parse_current->next->next->next->cl_head == NULL ) { nodecon->context_str = parse_current->next->next->next->data; } else { cil_context_init(&nodecon->context); rc = cil_fill_context(parse_current->next->next->next->cl_head, nodecon->context); if (rc != SEPOL_OK) { goto exit; } } ast_node->data = nodecon; ast_node->flavor = CIL_NODECON; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad nodecon declaration"); cil_destroy_nodecon(nodecon); return rc; } void cil_destroy_nodecon(struct cil_nodecon *nodecon) { if (nodecon == NULL) { return; } if (nodecon->addr_str == NULL && nodecon->addr != NULL) { cil_destroy_ipaddr(nodecon->addr); } if (nodecon->mask_str == NULL && nodecon->mask != NULL) { cil_destroy_ipaddr(nodecon->mask); } if (nodecon->context_str == NULL && nodecon->context != NULL) { cil_destroy_context(nodecon->context); } free(nodecon); } int cil_gen_genfscon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_STRING | CIL_SYN_LIST | CIL_SYN_END, CIL_SYN_END }; size_t syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_tree_node *context_node; 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->next) { /* (genfscon ... */ char *file_type = parse_current->next->next->next->data; if (file_type == CIL_KEY_ANY) { genfscon->file_type = CIL_FILECON_ANY; } else if (file_type == CIL_KEY_FILE) { genfscon->file_type = CIL_FILECON_FILE; } else if (file_type == CIL_KEY_DIR) { genfscon->file_type = CIL_FILECON_DIR; } else if (file_type == CIL_KEY_CHAR) { genfscon->file_type = CIL_FILECON_CHAR; } else if (file_type == CIL_KEY_BLOCK) { genfscon->file_type = CIL_FILECON_BLOCK; } else if (file_type == CIL_KEY_SOCKET) { genfscon->file_type = CIL_FILECON_SOCKET; } else if (file_type == CIL_KEY_PIPE) { genfscon->file_type = CIL_FILECON_PIPE; } else if (file_type == CIL_KEY_SYMLINK) { genfscon->file_type = CIL_FILECON_SYMLINK; } else { if (parse_current->next->next->next->cl_head) { cil_log(CIL_ERR, "Expecting file type, but found a list\n"); } else { cil_log(CIL_ERR, "Invalid file type \"%s\"\n", file_type); } goto exit; } context_node = parse_current->next->next->next->next; } else { /* (genfscon ... */ context_node = parse_current->next->next->next; } if (context_node->cl_head) { cil_context_init(&genfscon->context); rc = cil_fill_context(context_node->cl_head, genfscon->context); if (rc != SEPOL_OK) { goto exit; } } else { genfscon->context_str = context_node->data; } ast_node->data = genfscon; ast_node->flavor = CIL_GENFSCON; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad genfscon declaration"); cil_destroy_genfscon(genfscon); return SEPOL_ERR; } void cil_destroy_genfscon(struct cil_genfscon *genfscon) { if (genfscon == NULL) { return; } if (genfscon->context_str == NULL && genfscon->context != NULL) { cil_destroy_context(genfscon->context); } free(genfscon); } int cil_gen_netifcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; size_t syntax_len = sizeof(syntax)/sizeof(*syntax); int rc = SEPOL_ERR; struct cil_netifcon *netifcon = NULL; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_netifcon_init(&netifcon); netifcon->interface_str = parse_current->next->data; if (parse_current->next->next->cl_head == NULL) { netifcon->if_context_str = parse_current->next->next->data; } else { cil_context_init(&netifcon->if_context); rc = cil_fill_context(parse_current->next->next->cl_head, netifcon->if_context); if (rc != SEPOL_OK) { goto exit; } } if (parse_current->next->next->next->cl_head == NULL) { netifcon->packet_context_str = parse_current->next->next->next->data; } else { cil_context_init(&netifcon->packet_context); rc = cil_fill_context(parse_current->next->next->next->cl_head, netifcon->packet_context); if (rc != SEPOL_OK) { goto exit; } } ast_node->data = netifcon; ast_node->flavor = CIL_NETIFCON; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad netifcon declaration"); cil_destroy_netifcon(netifcon); return SEPOL_ERR; } void cil_destroy_netifcon(struct cil_netifcon *netifcon) { if (netifcon == NULL) { return; } if (netifcon->if_context_str == NULL && netifcon->if_context != NULL) { cil_destroy_context(netifcon->if_context); } if (netifcon->packet_context_str == NULL && netifcon->packet_context != NULL) { cil_destroy_context(netifcon->packet_context); } free(netifcon); } int cil_gen_ibendportcon(__attribute__((unused)) struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; size_t syntax_len = sizeof(syntax) / sizeof(*syntax); int rc = SEPOL_ERR; struct cil_ibendportcon *ibendportcon = NULL; if (!parse_current || !ast_node) goto exit; rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) goto exit; cil_ibendportcon_init(&ibendportcon); ibendportcon->dev_name_str = parse_current->next->data; rc = cil_fill_integer(parse_current->next->next, &ibendportcon->port, 10); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Improper ibendport port specified\n"); goto exit; } if (!parse_current->next->next->next->cl_head) { ibendportcon->context_str = parse_current->next->next->next->data; } else { cil_context_init(&ibendportcon->context); rc = cil_fill_context(parse_current->next->next->next->cl_head, ibendportcon->context); if (rc != SEPOL_OK) goto exit; } ast_node->data = ibendportcon; ast_node->flavor = CIL_IBENDPORTCON; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad ibendportcon declaration"); cil_destroy_ibendportcon(ibendportcon); return SEPOL_ERR; } void cil_destroy_ibendportcon(struct cil_ibendportcon *ibendportcon) { if (!ibendportcon) return; if (!ibendportcon->context_str && ibendportcon->context) cil_destroy_context(ibendportcon->context); free(ibendportcon); } int cil_gen_pirqcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; size_t syntax_len = sizeof(syntax)/sizeof(*syntax); int rc = SEPOL_ERR; struct cil_pirqcon *pirqcon = NULL; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_pirqcon_init(&pirqcon); rc = cil_fill_integer(parse_current->next, &pirqcon->pirq, 10); if (rc != SEPOL_OK) { goto exit; } if (parse_current->next->next->cl_head == NULL) { pirqcon->context_str = parse_current->next->next->data; } else { cil_context_init(&pirqcon->context); rc = cil_fill_context(parse_current->next->next->cl_head, pirqcon->context); if (rc != SEPOL_OK) { goto exit; } } ast_node->data = pirqcon; ast_node->flavor = CIL_PIRQCON; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad pirqcon declaration"); cil_destroy_pirqcon(pirqcon); return rc; } void cil_destroy_pirqcon(struct cil_pirqcon *pirqcon) { if (pirqcon == NULL) { return; } if (pirqcon->context_str == NULL && pirqcon->context != NULL) { cil_destroy_context(pirqcon->context); } free(pirqcon); } int cil_gen_iomemcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; size_t syntax_len = sizeof(syntax)/sizeof(*syntax); int rc = SEPOL_ERR; struct cil_iomemcon *iomemcon = NULL; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_iomemcon_init(&iomemcon); if (parse_current->next->cl_head != NULL) { if (parse_current->next->cl_head->next != NULL && parse_current->next->cl_head->next->next == NULL) { rc = cil_fill_integer64(parse_current->next->cl_head, &iomemcon->iomem_low, 0); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Improper iomem specified\n"); goto exit; } rc = cil_fill_integer64(parse_current->next->cl_head->next, &iomemcon->iomem_high, 0); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Improper iomem specified\n"); goto exit; } } else { cil_log(CIL_ERR, "Improper iomem range specified\n"); rc = SEPOL_ERR; goto exit; } } else { rc = cil_fill_integer64(parse_current->next, &iomemcon->iomem_low, 0); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Improper iomem specified\n"); goto exit; } iomemcon->iomem_high = iomemcon->iomem_low; } if (parse_current->next->next->cl_head == NULL ) { iomemcon->context_str = parse_current->next->next->data; } else { cil_context_init(&iomemcon->context); rc = cil_fill_context(parse_current->next->next->cl_head, iomemcon->context); if (rc != SEPOL_OK) { goto exit; } } ast_node->data = iomemcon; ast_node->flavor = CIL_IOMEMCON; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad iomemcon declaration"); cil_destroy_iomemcon(iomemcon); return rc; } void cil_destroy_iomemcon(struct cil_iomemcon *iomemcon) { if (iomemcon == NULL) { return; } if (iomemcon->context_str == NULL && iomemcon->context != NULL) { cil_destroy_context(iomemcon->context); } free(iomemcon); } int cil_gen_ioportcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; size_t syntax_len = sizeof(syntax)/sizeof(*syntax); int rc = SEPOL_ERR; struct cil_ioportcon *ioportcon = NULL; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_ioportcon_init(&ioportcon); if (parse_current->next->cl_head != NULL) { if (parse_current->next->cl_head->next != NULL && parse_current->next->cl_head->next->next == NULL) { rc = cil_fill_integer(parse_current->next->cl_head, &ioportcon->ioport_low, 0); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Improper ioport specified\n"); goto exit; } rc = cil_fill_integer(parse_current->next->cl_head->next, &ioportcon->ioport_high, 0); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Improper ioport specified\n"); goto exit; } } else { cil_log(CIL_ERR, "Improper ioport range specified\n"); rc = SEPOL_ERR; goto exit; } } else { rc = cil_fill_integer(parse_current->next, &ioportcon->ioport_low, 0); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Improper ioport specified\n"); goto exit; } ioportcon->ioport_high = ioportcon->ioport_low; } if (parse_current->next->next->cl_head == NULL ) { ioportcon->context_str = parse_current->next->next->data; } else { cil_context_init(&ioportcon->context); rc = cil_fill_context(parse_current->next->next->cl_head, ioportcon->context); if (rc != SEPOL_OK) { goto exit; } } ast_node->data = ioportcon; ast_node->flavor = CIL_IOPORTCON; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad ioportcon declaration"); cil_destroy_ioportcon(ioportcon); return rc; } void cil_destroy_ioportcon(struct cil_ioportcon *ioportcon) { if (ioportcon == NULL) { return; } if (ioportcon->context_str == NULL && ioportcon->context != NULL) { cil_destroy_context(ioportcon->context); } free(ioportcon); } int cil_gen_pcidevicecon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; size_t syntax_len = sizeof(syntax)/sizeof(*syntax); int rc = SEPOL_ERR; struct cil_pcidevicecon *pcidevicecon = NULL; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_pcidevicecon_init(&pcidevicecon); rc = cil_fill_integer(parse_current->next, &pcidevicecon->dev, 0); if (rc != SEPOL_OK) { goto exit; } if (parse_current->next->next->cl_head == NULL) { pcidevicecon->context_str = parse_current->next->next->data; } else { cil_context_init(&pcidevicecon->context); rc = cil_fill_context(parse_current->next->next->cl_head, pcidevicecon->context); if (rc != SEPOL_OK) { goto exit; } } ast_node->data = pcidevicecon; ast_node->flavor = CIL_PCIDEVICECON; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad pcidevicecon declaration"); cil_destroy_pcidevicecon(pcidevicecon); return rc; } void cil_destroy_pcidevicecon(struct cil_pcidevicecon *pcidevicecon) { if (pcidevicecon == NULL) { return; } if (pcidevicecon->context_str == NULL && pcidevicecon->context != NULL) { cil_destroy_context(pcidevicecon->context); } free(pcidevicecon); } int cil_gen_devicetreecon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; size_t syntax_len = sizeof(syntax)/sizeof(*syntax); int rc = SEPOL_ERR; struct cil_devicetreecon *devicetreecon = NULL; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_devicetreecon_init(&devicetreecon); devicetreecon->path = parse_current->next->data; if (parse_current->next->next->cl_head == NULL) { devicetreecon->context_str = parse_current->next->next->data; } else { cil_context_init(&devicetreecon->context); rc = cil_fill_context(parse_current->next->next->cl_head, devicetreecon->context); if (rc != SEPOL_OK) { goto exit; } } ast_node->data = devicetreecon; ast_node->flavor = CIL_DEVICETREECON; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad devicetreecon declaration"); cil_destroy_devicetreecon(devicetreecon); return rc; } void cil_destroy_devicetreecon(struct cil_devicetreecon *devicetreecon) { if (devicetreecon == NULL) { return; } if (devicetreecon->context_str == NULL && devicetreecon->context != NULL) { cil_destroy_context(devicetreecon->context); } free(devicetreecon); } int cil_gen_fsuse(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; size_t syntax_len = sizeof(syntax)/sizeof(*syntax); char *type = NULL; struct cil_fsuse *fsuse = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } type = parse_current->next->data; cil_fsuse_init(&fsuse); if (type == CIL_KEY_XATTR) { fsuse->type = CIL_FSUSE_XATTR; } else if (type == CIL_KEY_TASK) { fsuse->type = CIL_FSUSE_TASK; } else if (type == CIL_KEY_TRANS) { fsuse->type = CIL_FSUSE_TRANS; } else { cil_log(CIL_ERR, "Invalid fsuse type\n"); goto exit; } fsuse->fs_str = parse_current->next->next->data; if (parse_current->next->next->next->cl_head == NULL) { fsuse->context_str = parse_current->next->next->next->data; } else { cil_context_init(&fsuse->context); rc = cil_fill_context(parse_current->next->next->next->cl_head, fsuse->context); if (rc != SEPOL_OK) { goto exit; } } ast_node->data = fsuse; ast_node->flavor = CIL_FSUSE; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad fsuse declaration"); cil_destroy_fsuse(fsuse); return SEPOL_ERR; } void cil_destroy_fsuse(struct cil_fsuse *fsuse) { if (fsuse == NULL) { return; } if (fsuse->context_str == NULL && fsuse->context != NULL) { cil_destroy_context(fsuse->context); } free(fsuse); } void cil_destroy_param(struct cil_param *param) { if (param == NULL) { return; } free(param); } int cil_gen_macro(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { int rc = SEPOL_ERR; char *key = NULL; struct cil_macro *macro = NULL; struct cil_tree_node *macro_content = NULL; struct cil_tree_node *current_item; 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 }; size_t syntax_len = sizeof(syntax)/ sizeof(*syntax); if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc =__cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_macro_init(¯o); key = parse_current->next->data; 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; struct cil_list_item *curr_param; rc =__cil_verify_syntax(current_item->cl_head, param_syntax, param_syntax_len); if (rc != SEPOL_OK) { goto exit; } if (macro->params == NULL) { cil_list_init(¯o->params, CIL_LIST_ITEM); } kind = current_item->cl_head->data; cil_param_init(¶m); if (kind == CIL_KEY_TYPE) { param->flavor = CIL_TYPE; } else if (kind == CIL_KEY_ROLE) { param->flavor = CIL_ROLE; } else if (kind == CIL_KEY_USER) { param->flavor = CIL_USER; } else if (kind == CIL_KEY_SENSITIVITY) { param->flavor = CIL_SENS; } else if (kind == CIL_KEY_CATEGORY) { param->flavor = CIL_CAT; } else if (kind == CIL_KEY_CATSET) { param->flavor = CIL_CATSET; } else if (kind == CIL_KEY_LEVEL) { param->flavor = CIL_LEVEL; } else if (kind == CIL_KEY_LEVELRANGE) { param->flavor = CIL_LEVELRANGE; } else if (kind == CIL_KEY_CLASS) { param->flavor = CIL_CLASS; } else if (kind == CIL_KEY_IPADDR) { param->flavor = CIL_IPADDR; } else if (kind == CIL_KEY_MAP_CLASS) { param->flavor = CIL_MAP_CLASS; } else if (kind == CIL_KEY_CLASSPERMISSION) { param->flavor = CIL_CLASSPERMISSION; } else if (kind == CIL_KEY_BOOL) { param->flavor = CIL_BOOL; } else if (kind == CIL_KEY_STRING) { param->flavor = CIL_DECLARED_STRING; } else if (kind == CIL_KEY_NAME) { param->flavor = CIL_DECLARED_STRING; } 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(db, param->str, param->flavor); if (rc != SEPOL_OK) { cil_destroy_param(param); goto exit; } //walk current list and check for duplicate parameters cil_list_for_each(curr_param, macro->params) { if (param->str == ((struct cil_param*)curr_param->data)->str) { cil_log(CIL_ERR, "Duplicate parameter\n"); cil_destroy_param(param); goto exit; } } cil_list_append(macro->params, CIL_PARAM, param); current_item = current_item->next; } /* we don't want the tree walker to walk the macro parameters (they were just handled above), so the subtree is deleted, and the next pointer of the node containing the macro name is updated to point to the start of the macro content */ macro_content = parse_current->next->next->next; cil_tree_subtree_destroy(parse_current->next->next); parse_current->next->next = macro_content; if (macro_content == NULL) { /* No statements in macro and macro parameter list was last node */ parse_current->parent->cl_tail = parse_current->next; } rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)macro, (hashtab_key_t)key, CIL_SYM_BLOCKS, CIL_MACRO); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad macro declaration"); cil_destroy_macro(macro); cil_clear_node(ast_node); return SEPOL_ERR; } void cil_destroy_macro(struct cil_macro *macro) { if (macro == NULL) { return; } cil_symtab_datum_destroy(¯o->datum); cil_symtab_array_destroy(macro->symtab); if (macro->params != NULL) { cil_list_destroy(¯o->params, 1); } free(macro); } int cil_gen_call(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_LIST | CIL_SYN_EMPTY_LIST | CIL_SYN_END, CIL_SYN_END }; size_t syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_call *call = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_call_init(&call); call->macro_str = parse_current->next->data; if (parse_current->next->next != NULL) { cil_tree_init(&call->args_tree); cil_copy_ast(db, parse_current->next->next, call->args_tree->root); } ast_node->data = call; ast_node->flavor = CIL_CALL; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad macro call"); cil_destroy_call(call); return rc; } void cil_destroy_call(struct cil_call *call) { if (call == NULL) { return; } call->macro = NULL; if (call->args_tree != NULL) { cil_tree_destroy(&call->args_tree); } if (call->args != NULL) { cil_list_destroy(&call->args, 1); } free(call); } void cil_destroy_args(struct cil_args *args) { if (args == NULL) { return; } if (args->arg_str != NULL) { args->arg_str = NULL; } else if (args->arg != NULL) { struct cil_tree_node *node = args->arg->nodes->head->data; switch (args->flavor) { case CIL_DECLARED_STRING: break; case CIL_CATSET: cil_destroy_catset((struct cil_catset *)args->arg); free(node); break; case CIL_LEVEL: cil_destroy_level((struct cil_level *)args->arg); free(node); break; case CIL_LEVELRANGE: cil_destroy_levelrange((struct cil_levelrange *)args->arg); free(node); break; case CIL_IPADDR: cil_destroy_ipaddr((struct cil_ipaddr *)args->arg); free(node); break; case CIL_CLASSPERMISSION: cil_destroy_classpermission((struct cil_classpermission *)args->arg); free(node); break; default: cil_log(CIL_ERR, "Destroying arg with the unexpected flavor=%d\n",args->flavor); break; } } args->param_str = NULL; args->arg = NULL; free(args); } int cil_gen_optional(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_N_LISTS | CIL_SYN_END, CIL_SYN_END }; size_t 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) { if (rc == SEPOL_EEXIST) { cil_destroy_optional(optional); optional = NULL; } else { goto exit; } } return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad optional"); cil_destroy_optional(optional); cil_clear_node(ast_node); return rc; } void cil_destroy_optional(struct cil_optional *optional) { if (optional == NULL) { return; } cil_symtab_datum_destroy(&optional->datum); free(optional); } int cil_gen_policycap(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_END }; size_t syntax_len = sizeof(syntax)/sizeof(*syntax); char *key = NULL; struct cil_policycap *polcap = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_policycap_init(&polcap); key = parse_current->next->data; rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)polcap, (hashtab_key_t)key, CIL_SYM_POLICYCAPS, CIL_POLICYCAP); if (rc != SEPOL_OK) goto exit; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad policycap statement"); cil_destroy_policycap(polcap); cil_clear_node(ast_node); return rc; } void cil_destroy_policycap(struct cil_policycap *polcap) { if (polcap == NULL) { return; } cil_symtab_datum_destroy(&polcap->datum); free(polcap); } int cil_gen_ipaddr(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_END }; size_t syntax_len = sizeof(syntax)/sizeof(*syntax); char *key = NULL; struct cil_ipaddr *ipaddr = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_ipaddr_init(&ipaddr); key = parse_current->next->data; rc = cil_fill_ipaddr(parse_current->next->next, ipaddr); if (rc != SEPOL_OK) { goto exit; } rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)ipaddr, (hashtab_key_t)key, CIL_SYM_IPADDRS, CIL_IPADDR); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad ipaddr statement"); cil_destroy_ipaddr(ipaddr); cil_clear_node(ast_node); return rc; } void cil_destroy_ipaddr(struct cil_ipaddr *ipaddr) { if (ipaddr == NULL) { return; } cil_symtab_datum_destroy(&ipaddr->datum); free(ipaddr); } int cil_fill_integer(struct cil_tree_node *int_node, uint32_t *integer, int base) { int rc = SEPOL_ERR; if (int_node == NULL || int_node->data == NULL || integer == NULL) { goto exit; } rc = cil_string_to_uint32(int_node->data, integer, base); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: cil_log(CIL_ERR, "Failed to fill 32-bit integer\n"); return rc; } int cil_fill_integer64(struct cil_tree_node *int_node, uint64_t *integer, int base) { int rc = SEPOL_ERR; if (int_node == NULL || int_node->data == NULL || integer == NULL) { goto exit; } rc = cil_string_to_uint64(int_node->data, integer, base); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: cil_log(CIL_ERR, "Failed to fill 64-bit integer\n"); return rc; } int cil_fill_ipaddr(struct cil_tree_node *addr_node, struct cil_ipaddr *addr) { int rc = SEPOL_ERR; char *addr_str; if (addr_node == NULL || addr_node->data == NULL || addr == NULL) { goto exit; } addr_str = addr_node->data; if (strchr(addr_str, ':')) { addr->family = AF_INET6; } else if (strchr(addr_str, '.') && isdigit(addr_str[0])) { addr->family = AF_INET; } else { goto exit; } 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: %s\n", (addr_node && addr_node->data) ? (const char *)addr_node->data : "NULL"); 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 }; size_t syntax_len = sizeof(syntax)/sizeof(*syntax); if (curr == NULL) { goto exit; } rc = __cil_verify_syntax(curr, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } level->sens_str = curr->data; if (curr->next != NULL) { rc = cil_fill_cats(curr->next, &level->cats); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: cil_log(CIL_ERR, "Bad level\n"); return rc; } int cil_fill_cats(struct cil_tree_node *curr, struct cil_cats **cats) { int rc = SEPOL_ERR; cil_cats_init(cats); rc = cil_gen_expr(curr, CIL_CAT, &(*cats)->str_expr); if (rc != SEPOL_OK) { cil_destroy_cats(*cats); *cats = NULL; } return rc; } void cil_destroy_cats(struct cil_cats *cats) { if (cats == NULL) { return; } cil_list_destroy(&cats->str_expr, CIL_TRUE); cil_list_destroy(&cats->datum_expr, CIL_FALSE); free(cats); } int cil_gen_bounds(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor) { enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_END }; size_t syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_bounds *bounds = NULL; int rc = SEPOL_ERR; if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_bounds_init(&bounds); bounds->parent_str = parse_current->next->data; bounds->child_str = parse_current->next->next->data; ast_node->data = bounds; switch (flavor) { case CIL_USER: ast_node->flavor = CIL_USERBOUNDS; break; case CIL_ROLE: ast_node->flavor = CIL_ROLEBOUNDS; break; case CIL_TYPE: ast_node->flavor = CIL_TYPEBOUNDS; break; default: break; } return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad bounds declaration"); cil_destroy_bounds(bounds); return rc; } void cil_destroy_bounds(struct cil_bounds *bounds) { if (bounds == NULL) { return; } free(bounds); } int cil_gen_default(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor) { int rc = SEPOL_ERR; struct cil_default *def = NULL; char *object; enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_STRING, CIL_SYN_END }; size_t syntax_len = sizeof(syntax)/sizeof(*syntax); rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_default_init(&def); def->flavor = flavor; if (parse_current->next->cl_head == NULL) { cil_list_init(&def->class_strs, CIL_CLASS); cil_list_append(def->class_strs, CIL_STRING, parse_current->next->data); } else { rc = cil_fill_list(parse_current->next->cl_head, CIL_CLASS, &def->class_strs); if (rc != SEPOL_OK) { goto exit; } } object = parse_current->next->next->data; if (object == CIL_KEY_SOURCE) { def->object = CIL_DEFAULT_SOURCE; } else if (object == CIL_KEY_TARGET) { def->object = CIL_DEFAULT_TARGET; } else { cil_log(CIL_ERR,"Expected either 'source' or 'target'\n"); rc = SEPOL_ERR; goto exit; } ast_node->data = def; ast_node->flavor = flavor; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad %s declaration", cil_node_to_string(parse_current)); cil_destroy_default(def); return rc; } void cil_destroy_default(struct cil_default *def) { if (def == NULL) { return; } cil_list_destroy(&def->class_strs, CIL_TRUE); cil_list_destroy(&def->class_datums, CIL_FALSE); free(def); } int cil_gen_defaultrange(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { int rc = SEPOL_ERR; struct cil_defaultrange *def = NULL; char *object; char *range; enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_END, CIL_SYN_END }; size_t syntax_len = sizeof(syntax)/sizeof(*syntax); rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_defaultrange_init(&def); if (parse_current->next->cl_head == NULL) { cil_list_init(&def->class_strs, CIL_CLASS); cil_list_append(def->class_strs, CIL_STRING, parse_current->next->data); } else { rc = cil_fill_list(parse_current->next->cl_head, CIL_CLASS, &def->class_strs); if (rc != SEPOL_OK) { goto exit; } } object = parse_current->next->next->data; if (object == CIL_KEY_SOURCE) { if (!parse_current->next->next->next) { cil_log(CIL_ERR, "Missing 'low', 'high', or 'low-high'\n"); rc = SEPOL_ERR; goto exit; } range = parse_current->next->next->next->data; 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 (object == CIL_KEY_TARGET) { if (!parse_current->next->next->next) { cil_log(CIL_ERR, "Missing 'low', 'high', or 'low-high'\n"); rc = SEPOL_ERR; goto exit; } range = parse_current->next->next->next->data; 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 if (object == CIL_KEY_GLBLUB) { def->object_range = CIL_DEFAULT_GLBLUB; } else { cil_log(CIL_ERR,"Expected \'source\', \'target\', or \'glblub\'\n"); rc = SEPOL_ERR; goto exit; } ast_node->data = def; ast_node->flavor = CIL_DEFAULTRANGE; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad defaultrange declaration"); cil_destroy_defaultrange(def); return rc; } void cil_destroy_defaultrange(struct cil_defaultrange *def) { if (def == NULL) { return; } cil_list_destroy(&def->class_strs, CIL_TRUE); cil_list_destroy(&def->class_datums, CIL_FALSE); free(def); } int cil_gen_handleunknown(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { int rc = SEPOL_ERR; enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_END }; size_t syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_handleunknown *unknown = NULL; char *unknown_key; if (parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_handleunknown_init(&unknown); unknown_key = parse_current->next->data; if (unknown_key == CIL_KEY_HANDLEUNKNOWN_ALLOW) { unknown->handle_unknown = SEPOL_ALLOW_UNKNOWN; } else if (unknown_key == CIL_KEY_HANDLEUNKNOWN_DENY) { unknown->handle_unknown = SEPOL_DENY_UNKNOWN; } else if (unknown_key == CIL_KEY_HANDLEUNKNOWN_REJECT) { unknown->handle_unknown = SEPOL_REJECT_UNKNOWN; } else { cil_log(CIL_ERR, "Expected either \'%s\', \'%s\', or \'%s\'\n", CIL_KEY_HANDLEUNKNOWN_ALLOW, CIL_KEY_HANDLEUNKNOWN_DENY, CIL_KEY_HANDLEUNKNOWN_REJECT); rc = SEPOL_ERR; goto exit; } ast_node->data = unknown; ast_node->flavor = CIL_HANDLEUNKNOWN; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad handleunknown"); cil_destroy_handleunknown(unknown); return rc; } void cil_destroy_handleunknown(struct cil_handleunknown *unk) { free(unk); } int cil_gen_mls(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { int rc = SEPOL_ERR; enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_END }; size_t syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_mls *mls = NULL; if (parse_current == NULL || ast_node == NULL) { goto exit; } rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } cil_mls_init(&mls); if (parse_current->next->data == CIL_KEY_CONDTRUE) { mls->value = CIL_TRUE; } else if (parse_current->next->data == CIL_KEY_CONDFALSE) { mls->value = CIL_FALSE; } else { cil_log(CIL_ERR, "Value must be either \'true\' or \'false\'"); rc = SEPOL_ERR; goto exit; } ast_node->data = mls; ast_node->flavor = CIL_MLS; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad mls"); cil_destroy_mls(mls); return rc; } void cil_destroy_mls(struct cil_mls *mls) { free(mls); } int cil_gen_src_info(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { int rc = SEPOL_ERR; enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_N_LISTS | CIL_SYN_END, CIL_SYN_END }; size_t syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_src_info *info = 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_src_info_init(&info); info->kind = parse_current->next->data; if (info->kind != CIL_KEY_SRC_CIL && info->kind != CIL_KEY_SRC_HLL_LMS && info->kind != CIL_KEY_SRC_HLL_LMX) { cil_log(CIL_ERR, "Invalid src info kind\n"); rc = SEPOL_ERR; goto exit; } rc = cil_string_to_uint32(parse_current->next->next->data, &info->hll_line, 10); if (rc != SEPOL_OK) { goto exit; } info->path = parse_current->next->next->next->data; ast_node->data = info; ast_node->flavor = CIL_SRC_INFO; return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad src info"); cil_destroy_src_info(info); return rc; } void cil_destroy_src_info(struct cil_src_info *info) { free(info); } static int check_for_illegal_statement(struct cil_tree_node *parse_current, struct cil_args_build *args) { if (args->tunif != NULL) { if (parse_current->data == CIL_KEY_TUNABLE) { cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in tunableif", (char *)parse_current->data); return SEPOL_ERR; } } if (args->in != NULL) { struct cil_in *in_block = args->in->data; if (parse_current->data == CIL_KEY_TUNABLE || parse_current->data == CIL_KEY_IN) { cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in in-statement", (char *)parse_current->data); return SEPOL_ERR; } if (in_block->is_after == CIL_TRUE) { if (parse_current->data == CIL_KEY_BLOCKINHERIT || parse_current->data == CIL_KEY_BLOCKABSTRACT) { cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in an after in-statement", (char *)parse_current->data); return SEPOL_ERR; } } } if (args->macro != NULL) { if (parse_current->data == CIL_KEY_TUNABLE || parse_current->data == CIL_KEY_IN || parse_current->data == CIL_KEY_BLOCK || parse_current->data == CIL_KEY_BLOCKINHERIT || parse_current->data == CIL_KEY_BLOCKABSTRACT || parse_current->data == CIL_KEY_MACRO) { cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in macro", (char *)parse_current->data); return SEPOL_ERR; } } if (args->optional != NULL) { if (parse_current->data == CIL_KEY_TUNABLE || parse_current->data == CIL_KEY_IN || parse_current->data == CIL_KEY_BLOCK || parse_current->data == CIL_KEY_BLOCKABSTRACT || parse_current->data == CIL_KEY_MACRO) { cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in optional", (char *)parse_current->data); return SEPOL_ERR; } } if (args->boolif != NULL) { if (parse_current->data != CIL_KEY_TUNABLEIF && parse_current->data != CIL_KEY_CALL && parse_current->data != CIL_KEY_CONDTRUE && parse_current->data != CIL_KEY_CONDFALSE && parse_current->data != CIL_KEY_ALLOW && parse_current->data != CIL_KEY_DONTAUDIT && parse_current->data != CIL_KEY_AUDITALLOW && parse_current->data != CIL_KEY_TYPETRANSITION && parse_current->data != CIL_KEY_TYPECHANGE && parse_current->data != CIL_KEY_TYPEMEMBER && ((args->db->policy_version < POLICYDB_VERSION_COND_XPERMS) || (parse_current->data != CIL_KEY_ALLOWX && parse_current->data != CIL_KEY_DONTAUDITX && parse_current->data != CIL_KEY_AUDITALLOWX))) { if (((struct cil_booleanif*)args->boolif->data)->preserved_tunable) { cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in tunableif being treated as a booleanif", (char *)parse_current->data); } else { cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in booleanif", (char *)parse_current->data); } return SEPOL_ERR; } } return SEPOL_OK; } static struct cil_tree_node * parse_statement(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_parent) { struct cil_tree_node *new_ast_node = NULL; int rc = SEPOL_ERR; cil_tree_node_init(&new_ast_node); new_ast_node->parent = ast_parent; new_ast_node->line = parse_current->line; new_ast_node->hll_offset = parse_current->hll_offset; if (parse_current->data == CIL_KEY_BLOCK) { rc = cil_gen_block(db, parse_current, new_ast_node, 0); } else if (parse_current->data == CIL_KEY_BLOCKINHERIT) { rc = cil_gen_blockinherit(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_BLOCKABSTRACT) { rc = cil_gen_blockabstract(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_IN) { rc = cil_gen_in(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_CLASS) { rc = cil_gen_class(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_CLASSORDER) { rc = cil_gen_ordered(db, parse_current, new_ast_node, CIL_CLASSORDER); } else if (parse_current->data == CIL_KEY_MAP_CLASS) { rc = cil_gen_map_class(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_CLASSMAPPING) { rc = cil_gen_classmapping(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_CLASSPERMISSION) { rc = cil_gen_classpermission(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_CLASSPERMISSIONSET) { rc = cil_gen_classpermissionset(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_COMMON) { rc = cil_gen_common(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_CLASSCOMMON) { rc = cil_gen_classcommon(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_SID) { rc = cil_gen_sid(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_SIDCONTEXT) { rc = cil_gen_sidcontext(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_SIDORDER) { rc = cil_gen_ordered(db, parse_current, new_ast_node, CIL_SIDORDER); } else if (parse_current->data == CIL_KEY_USER) { rc = cil_gen_user(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_USERATTRIBUTE) { rc = cil_gen_userattribute(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_USERATTRIBUTESET) { rc = cil_gen_userattributeset(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_USERLEVEL) { rc = cil_gen_userlevel(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_USERRANGE) { rc = cil_gen_userrange(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_USERBOUNDS) { rc = cil_gen_bounds(db, parse_current, new_ast_node, CIL_USER); } else if (parse_current->data == CIL_KEY_USERPREFIX) { rc = cil_gen_userprefix(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_SELINUXUSER) { rc = cil_gen_selinuxuser(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_SELINUXUSERDEFAULT) { rc = cil_gen_selinuxuserdefault(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_TYPE) { rc = cil_gen_type(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_TYPEATTRIBUTE) { rc = cil_gen_typeattribute(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_TYPEATTRIBUTESET) { rc = cil_gen_typeattributeset(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_EXPANDTYPEATTRIBUTE) { rc = cil_gen_expandtypeattribute(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_TYPEALIAS) { rc = cil_gen_alias(db, parse_current, new_ast_node, CIL_TYPEALIAS); } else if (parse_current->data == CIL_KEY_TYPEALIASACTUAL) { rc = cil_gen_aliasactual(db, parse_current, new_ast_node, CIL_TYPEALIASACTUAL); } else if (parse_current->data == CIL_KEY_TYPEBOUNDS) { rc = cil_gen_bounds(db, parse_current, new_ast_node, CIL_TYPE); } else if (parse_current->data == CIL_KEY_TYPEPERMISSIVE) { rc = cil_gen_typepermissive(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_RANGETRANSITION) { rc = cil_gen_rangetransition(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_ROLE) { rc = cil_gen_role(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_USERROLE) { rc = cil_gen_userrole(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_ROLETYPE) { rc = cil_gen_roletype(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_ROLETRANSITION) { rc = cil_gen_roletransition(parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_ROLEALLOW) { rc = cil_gen_roleallow(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_ROLEATTRIBUTE) { rc = cil_gen_roleattribute(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_ROLEATTRIBUTESET) { rc = cil_gen_roleattributeset(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_ROLEBOUNDS) { rc = cil_gen_bounds(db, parse_current, new_ast_node, CIL_ROLE); } else if (parse_current->data == CIL_KEY_BOOL) { rc = cil_gen_bool(db, parse_current, new_ast_node, CIL_FALSE); } else if (parse_current->data == CIL_KEY_BOOLEANIF) { rc = cil_gen_boolif(db, parse_current, new_ast_node, CIL_FALSE); } else if(parse_current->data == CIL_KEY_TUNABLE) { if (db->preserve_tunables) { rc = cil_gen_bool(db, parse_current, new_ast_node, CIL_TRUE); } else { rc = cil_gen_tunable(db, parse_current, new_ast_node); } } else if (parse_current->data == CIL_KEY_TUNABLEIF) { if (db->preserve_tunables) { rc = cil_gen_boolif(db, parse_current, new_ast_node, CIL_TRUE); } else { rc = cil_gen_tunif(db, parse_current, new_ast_node); } } else if (parse_current->data == CIL_KEY_CONDTRUE) { rc = cil_gen_condblock(db, parse_current, new_ast_node, CIL_CONDTRUE); } else if (parse_current->data == CIL_KEY_CONDFALSE) { rc = cil_gen_condblock(db, parse_current, new_ast_node, CIL_CONDFALSE); } else if (parse_current->data == CIL_KEY_ALLOW) { rc = cil_gen_avrule(parse_current, new_ast_node, CIL_AVRULE_ALLOWED); } else if (parse_current->data == CIL_KEY_AUDITALLOW) { rc = cil_gen_avrule(parse_current, new_ast_node, CIL_AVRULE_AUDITALLOW); } else if (parse_current->data == CIL_KEY_DONTAUDIT) { rc = cil_gen_avrule(parse_current, new_ast_node, CIL_AVRULE_DONTAUDIT); } else if (parse_current->data == CIL_KEY_NEVERALLOW) { rc = cil_gen_avrule(parse_current, new_ast_node, CIL_AVRULE_NEVERALLOW); } else if (parse_current->data == CIL_KEY_ALLOWX) { rc = cil_gen_avrulex(parse_current, new_ast_node, CIL_AVRULE_ALLOWED); } else if (parse_current->data == CIL_KEY_AUDITALLOWX) { rc = cil_gen_avrulex(parse_current, new_ast_node, CIL_AVRULE_AUDITALLOW); } else if (parse_current->data == CIL_KEY_DONTAUDITX) { rc = cil_gen_avrulex(parse_current, new_ast_node, CIL_AVRULE_DONTAUDIT); } else if (parse_current->data == CIL_KEY_NEVERALLOWX) { rc = cil_gen_avrulex(parse_current, new_ast_node, CIL_AVRULE_NEVERALLOW); } else if (parse_current->data == CIL_KEY_PERMISSIONX) { rc = cil_gen_permissionx(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_DENY_RULE) { rc = cil_gen_deny_rule(parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_TYPETRANSITION) { rc = cil_gen_typetransition(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_TYPECHANGE) { rc = cil_gen_type_rule(parse_current, new_ast_node, CIL_TYPE_CHANGE); } else if (parse_current->data == CIL_KEY_TYPEMEMBER) { rc = cil_gen_type_rule(parse_current, new_ast_node, CIL_TYPE_MEMBER); } else if (parse_current->data == CIL_KEY_SENSITIVITY) { rc = cil_gen_sensitivity(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_SENSALIAS) { rc = cil_gen_alias(db, parse_current, new_ast_node, CIL_SENSALIAS); } else if (parse_current->data == CIL_KEY_SENSALIASACTUAL) { rc = cil_gen_aliasactual(db, parse_current, new_ast_node, CIL_SENSALIASACTUAL); } else if (parse_current->data == CIL_KEY_CATEGORY) { rc = cil_gen_category(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_CATALIAS) { rc = cil_gen_alias(db, parse_current, new_ast_node, CIL_CATALIAS); } else if (parse_current->data == CIL_KEY_CATALIASACTUAL) { rc = cil_gen_aliasactual(db, parse_current, new_ast_node, CIL_CATALIASACTUAL); } else if (parse_current->data == CIL_KEY_CATSET) { rc = cil_gen_catset(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_CATORDER) { rc = cil_gen_ordered(db, parse_current, new_ast_node, CIL_CATORDER); } else if (parse_current->data == CIL_KEY_SENSITIVITYORDER) { rc = cil_gen_ordered(db, parse_current, new_ast_node, CIL_SENSITIVITYORDER); } else if (parse_current->data == CIL_KEY_SENSCAT) { rc = cil_gen_senscat(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_LEVEL) { rc = cil_gen_level(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_LEVELRANGE) { rc = cil_gen_levelrange(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_CONSTRAIN) { rc = cil_gen_constrain(db, parse_current, new_ast_node, CIL_CONSTRAIN); } else if (parse_current->data == CIL_KEY_MLSCONSTRAIN) { rc = cil_gen_constrain(db, parse_current, new_ast_node, CIL_MLSCONSTRAIN); } else if (parse_current->data == CIL_KEY_VALIDATETRANS) { rc = cil_gen_validatetrans(db, parse_current, new_ast_node, CIL_VALIDATETRANS); } else if (parse_current->data == CIL_KEY_MLSVALIDATETRANS) { rc = cil_gen_validatetrans(db, parse_current, new_ast_node, CIL_MLSVALIDATETRANS); } else if (parse_current->data == CIL_KEY_CONTEXT) { rc = cil_gen_context(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_FILECON) { rc = cil_gen_filecon(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_IBPKEYCON) { rc = cil_gen_ibpkeycon(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_IBENDPORTCON) { rc = cil_gen_ibendportcon(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_PORTCON) { rc = cil_gen_portcon(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_NODECON) { rc = cil_gen_nodecon(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_GENFSCON) { rc = cil_gen_genfscon(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_NETIFCON) { rc = cil_gen_netifcon(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_PIRQCON) { rc = cil_gen_pirqcon(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_IOMEMCON) { rc = cil_gen_iomemcon(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_IOPORTCON) { rc = cil_gen_ioportcon(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_PCIDEVICECON) { rc = cil_gen_pcidevicecon(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_DEVICETREECON) { rc = cil_gen_devicetreecon(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_FSUSE) { rc = cil_gen_fsuse(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_MACRO) { rc = cil_gen_macro(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_CALL) { rc = cil_gen_call(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_POLICYCAP) { rc = cil_gen_policycap(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_OPTIONAL) { rc = cil_gen_optional(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_IPADDR) { rc = cil_gen_ipaddr(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_DEFAULTUSER) { rc = cil_gen_default(parse_current, new_ast_node, CIL_DEFAULTUSER); } else if (parse_current->data == CIL_KEY_DEFAULTROLE) { rc = cil_gen_default(parse_current, new_ast_node, CIL_DEFAULTROLE); } else if (parse_current->data == CIL_KEY_DEFAULTTYPE) { rc = cil_gen_default(parse_current, new_ast_node, CIL_DEFAULTTYPE); } else if (parse_current->data == CIL_KEY_DEFAULTRANGE) { rc = cil_gen_defaultrange(parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_HANDLEUNKNOWN) { rc = cil_gen_handleunknown(parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_MLS) { rc = cil_gen_mls(parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_SRC_INFO) { rc = cil_gen_src_info(parse_current, new_ast_node); } else { cil_log(CIL_ERR, "Error: Unknown keyword %s\n", (char *)parse_current->data); rc = SEPOL_ERR; } if (rc == SEPOL_OK) { if (ast_parent->cl_head == NULL) { ast_parent->cl_head = new_ast_node; } else { ast_parent->cl_tail->next = new_ast_node; } ast_parent->cl_tail = new_ast_node; } else { cil_tree_node_destroy(&new_ast_node); new_ast_node = NULL; } return new_ast_node; } static int __cil_build_ast_node_helper(struct cil_tree_node *parse_current, uint32_t *finished, void *extra_args) { struct cil_args_build *args = extra_args; struct cil_tree_node *new_ast_node = NULL; int rc = SEPOL_ERR; if (parse_current->parent->cl_head != parse_current) { /* ignore anything that isn't following a parenthesis */ return SEPOL_OK; } else if (parse_current->data == NULL) { /* the only time parenthesis can immediately following parenthesis is if * the parent is the root node */ if (parse_current->parent->parent == NULL) { return SEPOL_OK; } else { cil_tree_log(parse_current, CIL_ERR, "Keyword expected after open parenthesis"); return SEPOL_ERR; } } rc = check_for_illegal_statement(parse_current, args); if (rc != SEPOL_OK) { return SEPOL_ERR; } new_ast_node = parse_statement(args->db, parse_current, args->ast); if (!new_ast_node) { return SEPOL_ERR; } args->ast = new_ast_node; if (parse_current->data != CIL_KEY_BLOCK && parse_current->data != CIL_KEY_IN && parse_current->data != CIL_KEY_TUNABLEIF && parse_current->data != CIL_KEY_BOOLEANIF && parse_current->data != CIL_KEY_CONDTRUE && parse_current->data != CIL_KEY_CONDFALSE && parse_current->data != CIL_KEY_MACRO && parse_current->data != CIL_KEY_OPTIONAL && parse_current->data != CIL_KEY_SRC_INFO) { /* Skip anything that does not contain a list of policy statements */ *finished = CIL_TREE_SKIP_NEXT; } return SEPOL_OK; } static int __cil_build_ast_first_child_helper(__attribute__((unused)) struct cil_tree_node *parse_current, void *extra_args) { struct cil_args_build *args = extra_args; struct cil_tree_node *ast = args->ast; if (ast->flavor == CIL_TUNABLEIF) { args->tunif = ast; } else if (ast->flavor == CIL_IN) { args->in = ast; } else if (ast->flavor == CIL_MACRO) { args->macro = ast; } else if (ast->flavor == CIL_OPTIONAL) { args->optional = ast; } else if (ast->flavor == CIL_BOOLEANIF) { args->boolif = ast; } return SEPOL_OK; } static int __cil_build_ast_last_child_helper(struct cil_tree_node *parse_current, void *extra_args) { struct cil_args_build *args = extra_args; struct cil_tree_node *ast = args->ast; if (ast->flavor == CIL_ROOT) { return SEPOL_OK; } args->ast = ast->parent; if (ast->flavor == CIL_TUNABLEIF) { args->tunif = NULL; } if (ast->flavor == CIL_IN) { args->in = NULL; } if (ast->flavor == CIL_MACRO) { args->macro = NULL; } if (ast->flavor == CIL_OPTIONAL) { struct cil_tree_node *n = ast->parent; args->optional = NULL; /* Optionals can be nested */ while (n && n->flavor != CIL_ROOT) { if (n->flavor == CIL_OPTIONAL) { args->optional = n; break; } n = n->parent; } } if (ast->flavor == CIL_BOOLEANIF) { args->boolif = 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 usage (of which the parse tree uses a lot), start // deleting the parts we don't need now. cil_tree_children_destroy(parse_current->parent); return SEPOL_OK; } int cil_build_ast(struct cil_db *db, struct cil_tree_node *parse_tree, struct cil_tree_node *ast) { int rc = SEPOL_ERR; struct cil_args_build extra_args; if (db == NULL || parse_tree == NULL || ast == NULL) { goto exit; } extra_args.ast = ast; extra_args.db = db; extra_args.tunif = NULL; extra_args.in = NULL; extra_args.macro = NULL; extra_args.optional = NULL; extra_args.boolif = NULL; rc = cil_tree_walk(parse_tree, __cil_build_ast_node_helper, __cil_build_ast_first_child_helper, __cil_build_ast_last_child_helper, &extra_args); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: return rc; } libsepol-3.8.1/cil/src/cil_build_ast.h000066400000000000000000000437441476211737200176660ustar00rootroot00000000000000/* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #ifndef CIL_BUILD_AST_H_ #define CIL_BUILD_AST_H_ #include #include "cil_internal.h" #include "cil_flavor.h" #include "cil_symtab.h" #include "cil_tree.h" #include "cil_list.h" int cil_add_decl_to_symtab(struct cil_db *db, symtab_t *symtab, hashtab_key_t key, struct cil_symtab_datum *datum, struct cil_tree_node *node); struct cil_symtab_datum *cil_gen_declared_string(struct cil_db *db, hashtab_key_t key, struct cil_tree_node *ast_node); 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_ordered(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor); void cil_destroy_ordered(struct cil_ordered *ordered); 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_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_user(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_user(struct cil_user *user); int cil_gen_userattribute(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_userattribute(struct cil_userattribute *attr); int cil_gen_userattributeset(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_userattributeset(struct cil_userattributeset *attrset); int cil_gen_userlevel(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_userlevel(struct cil_userlevel *usrlvl); int cil_gen_userrange(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_userrange(struct cil_userrange *userrange); int cil_gen_userbounds(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); int cil_gen_userprefix(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_userprefix(struct cil_userprefix *userprefix); int cil_gen_selinuxuser(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); int cil_gen_selinuxuserdefault(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_selinuxuser(struct cil_selinuxuser *selinuxuser); int cil_gen_role(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_role(struct cil_role *role); int cil_gen_roletype(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_roletype(struct cil_roletype *roletype); int cil_gen_userrole(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_userrole(struct cil_userrole *userrole); int cil_gen_roletransition(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_roletransition(struct cil_roletransition *roletrans); int cil_gen_roleallow(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_roleallow(struct cil_roleallow *roleallow); int cil_gen_roleattribute(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_roleattribute(struct cil_roleattribute *role); int cil_gen_roleattributeset(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_roleattributeset(struct cil_roleattributeset *attrset); int cil_gen_rolebounds(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); int cil_gen_avrule(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, uint32_t rule_kind); void cil_destroy_avrule(struct cil_avrule *rule); int cil_gen_avrulex(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, uint32_t rule_kind); int cil_gen_permissionx(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_permissionx(struct cil_permissionx *permx); int cil_gen_deny_rule(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_deny_rule(struct cil_deny_rule *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_expandtypeattribute(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_expandtypeattribute(struct cil_expandtypeattribute *expandattr); int cil_gen_typebounds(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); int cil_gen_typepermissive(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_typepermissive(struct cil_typepermissive *typeperm); int cil_gen_typetransition(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_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_senscat(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_senscat(struct cil_senscat *senscat); int cil_gen_level(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_level(struct cil_level *level); int cil_fill_levelrange(struct cil_tree_node *low, struct cil_levelrange *lvlrange); int cil_gen_levelrange(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_levelrange(struct cil_levelrange *lvlrange); void cil_destroy_constrain_node(struct cil_tree_node *cons_node); int cil_gen_constrain(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor); void cil_destroy_constrain(struct cil_constrain *cons); int cil_gen_validatetrans(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor); void cil_destroy_validatetrans(struct cil_validatetrans *validtrans); int cil_fill_context(struct cil_tree_node *user_node, struct cil_context *context); int cil_gen_context(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_context(struct cil_context *context); int cil_gen_filecon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_filecon(struct cil_filecon *filecon); int cil_gen_ibpkeycon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_ibpkeycon(struct cil_ibpkeycon *ibpkeycon); int cil_gen_ibendportcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_ibendportcon(struct cil_ibendportcon *ibendportcon); int cil_gen_portcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_portcon(struct cil_portcon *portcon); int cil_gen_nodecon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_nodecon(struct cil_nodecon *nodecon); int cil_gen_genfscon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_genfscon(struct cil_genfscon *genfscon); int cil_gen_netifcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_netifcon(struct cil_netifcon *netifcon); int cil_gen_pirqcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_pirqcon(struct cil_pirqcon *pirqcon); int cil_gen_iomemcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_iomemcon(struct cil_iomemcon *iomemcon); int cil_gen_ioportcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_ioportcon(struct cil_ioportcon *ioportcon); int cil_gen_pcidevicecon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_pcidevicecon(struct cil_pcidevicecon *pcidevicecon); int cil_gen_devicetreecon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_devicetreecon(struct cil_devicetreecon *devicetreecon); int cil_gen_fsuse(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_fsuse(struct cil_fsuse *fsuse); void cil_destroy_param(struct cil_param *param); int cil_gen_macro(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_macro(struct cil_macro *macro); int cil_gen_call(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_call(struct cil_call *call); void cil_destroy_args(struct cil_args *args); int cil_gen_optional(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_optional(struct cil_optional *optional); int cil_gen_policycap(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_policycap(struct cil_policycap *polcap); int cil_gen_ipaddr(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_ipaddr(struct cil_ipaddr *ipaddr); int cil_gen_bounds(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor); void cil_destroy_bounds(struct cil_bounds *bounds); int cil_gen_default(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor); void cil_destroy_default(struct cil_default *def); int cil_gen_handleunknown(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_handleunknown(struct cil_handleunknown *unk); int cil_gen_mls(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_mls(struct cil_mls *mls); int cil_gen_defaultrange(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_defaultrange(struct cil_defaultrange *def); int cil_gen_src_info(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_src_info(struct cil_src_info *info); int cil_fill_cats(struct cil_tree_node *curr, struct cil_cats **cats); void cil_destroy_cats(struct cil_cats *cats); int cil_fill_context(struct cil_tree_node *user_node, struct cil_context *context); int cil_fill_integer(struct cil_tree_node *int_node, uint32_t *integer, int base); int cil_fill_integer64(struct cil_tree_node *int_node, uint64_t *integer, int base); int cil_fill_ipaddr(struct cil_tree_node *addr_node, struct cil_ipaddr *addr); int cil_fill_level(struct cil_tree_node *sens, struct cil_level *level); int cil_build_ast(struct cil_db *db, struct cil_tree_node *parse_tree, struct cil_tree_node *ast); #endif /* CIL_BUILD_AST_H_ */ libsepol-3.8.1/cil/src/cil_copy_ast.c000066400000000000000000001441521476211737200175270ustar00rootroot00000000000000/* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #include #include #include #include "cil_internal.h" #include "cil_log.h" #include "cil_mem.h" #include "cil_tree.h" #include "cil_list.h" #include "cil_symtab.h" #include "cil_copy_ast.h" #include "cil_build_ast.h" #include "cil_strpool.h" #include "cil_verify.h" struct cil_args_copy { struct cil_tree_node *orig_dest; 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; } static 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_ordered(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_ordered *orig = data; struct cil_ordered *new = NULL; cil_ordered_init(&new); if (orig->strs != NULL) { cil_copy_list(orig->strs, &new->strs); } if (orig->datums != NULL) { cil_copy_list(orig->datums, &new->datums); } *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) { if (FLAVOR(datum) != CIL_BLOCK) { cil_tree_log(NODE(orig), CIL_ERR, "Block %s being copied", key); cil_tree_log(NODE(datum), CIL_ERR, " Conflicts with %s already declared", cil_node_to_string(NODE(datum))); return SEPOL_ERR; } cil_tree_log(NODE(orig), CIL_WARN, "Block %s being copied", key); cil_tree_log(NODE(datum), CIL_WARN, " Previously declared"); *copy = datum; } else { struct cil_block *new; cil_block_init(&new); *copy = new; } 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; new->block = orig->block; *copy = new; return SEPOL_OK; } int cil_copy_blockinherit(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_blockinherit *orig = data; struct cil_blockinherit *new = NULL; cil_blockinherit_init(&new); new->block_str = orig->block_str; new->block = orig->block; *copy = new; return SEPOL_OK; } static 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_class = orig->map_class; new->map_perm_str = orig->map_perm_str; new->map_perm = orig->map_perm; 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_classpermission(__attribute__((unused)) struct cil_db *db, void *data, void **copy, symtab_t *symtab) { struct cil_classpermission *orig = data; struct cil_classpermission *new = NULL; char *key = orig->datum.name; struct cil_symtab_datum *datum = NULL; if (key != NULL) { cil_symtab_get_datum(symtab, key, &datum); if (datum != NULL) { cil_log(CIL_INFO, "classpermission cannot be redefined\n"); return SEPOL_ERR; } } cil_classpermission_init(&new); cil_copy_classperms_list(orig->classperms, &new->classperms); *copy = new; return SEPOL_OK; } int cil_copy_classpermissionset(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_classpermissionset *orig = data; struct cil_classpermissionset *new = NULL; cil_classpermissionset_init(&new); new->set_str = orig->set_str; new->set = orig->set; 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->class = orig->class; new->common_str = orig->common_str; new->common = orig->common; *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_user(__attribute__((unused)) struct cil_db *db, void *data, void **copy, symtab_t *symtab) { struct cil_user *orig = data; char *key = orig->datum.name; struct cil_symtab_datum *datum = NULL; cil_symtab_get_datum(symtab, key, &datum); if (datum == NULL) { struct cil_user *new; cil_user_init(&new); *copy = new; } else { *copy = datum; } return SEPOL_OK; } int cil_copy_userattribute(__attribute__((unused)) struct cil_db *db, void *data, void **copy, symtab_t *symtab) { struct cil_userattribute *orig = data; struct cil_userattribute *new = NULL; char *key = orig->datum.name; struct cil_symtab_datum *datum = NULL; cil_symtab_get_datum(symtab, key, &datum); if (datum == NULL) { cil_userattribute_init(&new); *copy = new; } else { *copy = datum; } return SEPOL_OK; } int cil_copy_userattributeset(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_userattributeset *orig = data; struct cil_userattributeset *new = NULL; cil_userattributeset_init(&new); new->attr_str = orig->attr_str; cil_copy_expr(db, orig->str_expr, &new->str_expr); cil_copy_expr(db, orig->datum_expr, &new->datum_expr); *copy = new; return SEPOL_OK; } int cil_copy_userrole(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_userrole *orig = data; struct cil_userrole *new = NULL; cil_userrole_init(&new); new->user_str = orig->user_str; new->role_str = orig->role_str; *copy = new; return SEPOL_OK; } int cil_copy_userlevel(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_userlevel *orig = data; struct cil_userlevel *new = NULL; cil_userlevel_init(&new); new->user_str = orig->user_str; if (orig->level_str != NULL) { new->level_str = orig->level_str; } else { cil_copy_fill_level(db, orig->level, &new->level); } *copy = new; return SEPOL_OK; } int cil_copy_userrange(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_userrange *orig = data; struct cil_userrange *new = NULL; cil_userrange_init(&new); new->user_str = orig->user_str; if (orig->range_str != NULL) { new->range_str = orig->range_str; } else { cil_levelrange_init(&new->range); cil_copy_fill_levelrange(db, orig->range, new->range); } *copy = new; return SEPOL_OK; } int cil_copy_userprefix(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_userprefix *orig = data; struct cil_userprefix *new = NULL; cil_userprefix_init(&new); new->user_str = orig->user_str; new->prefix_str = orig->prefix_str; *copy = new; return SEPOL_OK; } int cil_copy_role(__attribute__((unused)) struct cil_db *db, void *data, void **copy, symtab_t *symtab) { struct cil_role *orig = data; char *key = orig->datum.name; struct cil_symtab_datum *datum = NULL; cil_symtab_get_datum(symtab, key, &datum); if (datum == NULL) { struct cil_role *new; cil_role_init(&new); *copy = new; } else { *copy = datum; } return SEPOL_OK; } int cil_copy_roletype(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_roletype *orig = data; struct cil_roletype *new = NULL; cil_roletype_init(&new); new->role_str = orig->role_str; new->type_str = orig->type_str; *copy = new; return SEPOL_OK; } int cil_copy_roleattribute(__attribute__((unused)) struct cil_db *db, void *data, void **copy, symtab_t *symtab) { struct cil_roleattribute *orig = data; char *key = orig->datum.name; struct cil_symtab_datum *datum = NULL; cil_symtab_get_datum(symtab, key, &datum); if (datum == NULL) { struct cil_roleattribute *new; cil_roleattribute_init(&new); *copy = new; } else { *copy = datum; } return SEPOL_OK; } int cil_copy_roleattributeset(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_roleattributeset *orig = data; struct cil_roleattributeset *new = NULL; cil_roleattributeset_init(&new); new->attr_str = orig->attr_str; cil_copy_expr(db, orig->str_expr, &new->str_expr); cil_copy_expr(db, orig->datum_expr, &new->datum_expr); *copy = new; return SEPOL_OK; } int cil_copy_roleallow(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_roleallow *orig = data; struct cil_roleallow *new = NULL; cil_roleallow_init(&new); new->src_str = orig->src_str; new->tgt_str = orig->tgt_str; *copy = new; return SEPOL_OK; } int cil_copy_type(__attribute__((unused)) struct cil_db *db, __attribute__((unused)) void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_type *new; cil_type_init(&new); *copy = new; 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, __attribute__((unused)) void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_typeattribute *new; cil_typeattribute_init(&new); *copy = new; 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; } static int cil_copy_expandtypeattribute(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_expandtypeattribute *orig = data; struct cil_expandtypeattribute *new = NULL; cil_expandtypeattribute_init(&new); if (orig->attr_strs != NULL) { cil_copy_list(orig->attr_strs, &new->attr_strs); } if (orig->attr_datums != NULL) { cil_copy_list(orig->attr_datums, &new->attr_datums); } new->expand = orig->expand; *copy = new; return SEPOL_OK; } static 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; } static 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->alias = orig->alias; new->actual_str = orig->actual_str; new->actual = orig->actual; *copy = new; return SEPOL_OK; } static 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->name = orig->name; 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; } static 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; } static void cil_copy_fill_permissionx(struct cil_db *db, struct cil_permissionx *orig, struct cil_permissionx *new) { new->kind = orig->kind; new->obj_str = orig->obj_str; cil_copy_expr(db, orig->expr_str, &new->expr_str); } int cil_copy_avrule(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_avrule *orig = data; struct cil_avrule *new = NULL; cil_avrule_init(&new); new->is_extended = orig->is_extended; new->rule_kind = orig->rule_kind; new->src_str = orig->src_str; new->tgt_str = orig->tgt_str; if (!new->is_extended) { cil_copy_classperms_list(orig->perms.classperms, &new->perms.classperms); } else { if (orig->perms.x.permx_str != NULL) { new->perms.x.permx_str = orig->perms.x.permx_str; } else { cil_permissionx_init(&new->perms.x.permx); cil_copy_fill_permissionx(db, orig->perms.x.permx, new->perms.x.permx); } } *copy = new; return SEPOL_OK; } static int cil_copy_permissionx(struct cil_db *db, void *data, void **copy, symtab_t *symtab) { struct cil_permissionx *orig = data; struct cil_permissionx *new = NULL; char *key = orig->datum.name; struct cil_symtab_datum *datum = NULL; cil_symtab_get_datum(symtab, key, &datum); if (datum != NULL) { cil_log(CIL_INFO, "cil_copy_permissionx: permissionx cannot be redefined\n"); return SEPOL_ERR; } cil_permissionx_init(&new); cil_copy_fill_permissionx(db, orig, new); *copy = new; return SEPOL_OK; } int cil_copy_deny_rule(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_deny_rule *orig = data; struct cil_deny_rule *new = NULL; cil_deny_rule_init(&new); 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; } static 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; } 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->path = orig->path; new->type = orig->type; if (orig->context_str != NULL) { new->context_str = orig->context_str; } else if (orig->context != NULL) { cil_context_init(&new->context); cil_copy_fill_context(db, orig->context, new->context); } *copy = new; return SEPOL_OK; } int cil_copy_nodecon(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_nodecon *orig = data; struct cil_nodecon *new = NULL; cil_nodecon_init(&new); if (orig->addr_str != NULL) { new->addr_str = orig->addr_str; } else { cil_ipaddr_init(&new->addr); cil_copy_fill_ipaddr(orig->addr, new->addr); } if (orig->mask_str != NULL) { new->mask_str = orig->mask_str; } else { cil_ipaddr_init(&new->mask); cil_copy_fill_ipaddr(orig->mask, new->mask); } if (orig->context_str != NULL) { new->context_str = orig->context_str; } else { cil_context_init(&new->context); cil_copy_fill_context(db, orig->context, new->context); } *copy = new; return SEPOL_OK; } int cil_copy_ibpkeycon(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_ibpkeycon *orig = data; struct cil_ibpkeycon *new = NULL; cil_ibpkeycon_init(&new); new->subnet_prefix_str = orig->subnet_prefix_str; new->pkey_low = orig->pkey_low; new->pkey_high = orig->pkey_high; if (orig->context_str) { new->context_str = orig->context_str; } else { cil_context_init(&new->context); cil_copy_fill_context(db, orig->context, new->context); } *copy = new; return SEPOL_OK; } static int cil_copy_ibendportcon(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_ibendportcon *orig = data; struct cil_ibendportcon *new = NULL; cil_ibendportcon_init(&new); new->dev_name_str = orig->dev_name_str; new->port = orig->port; if (orig->context_str) { new->context_str = orig->context_str; } else { cil_context_init(&new->context); cil_copy_fill_context(db, orig->context, new->context); } *copy = new; return SEPOL_OK; } int cil_copy_portcon(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_portcon *orig = data; struct cil_portcon *new = NULL; cil_portcon_init(&new); new->proto = orig->proto; new->port_low = orig->port_low; new->port_high = orig->port_high; if (orig->context_str != NULL) { new->context_str = orig->context_str; } else { cil_context_init(&new->context); cil_copy_fill_context(db, orig->context, new->context); } *copy = new; return SEPOL_OK; } int cil_copy_pirqcon(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_pirqcon *orig = data; struct cil_pirqcon *new = NULL; cil_pirqcon_init(&new); new->pirq = orig->pirq; if (orig->context_str != NULL) { new->context_str = orig->context_str; } else { cil_context_init(&new->context); cil_copy_fill_context(db, orig->context, new->context); } *copy = new; return SEPOL_OK; } int cil_copy_iomemcon(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_iomemcon *orig = data; struct cil_iomemcon *new = NULL; cil_iomemcon_init(&new); new->iomem_low = orig->iomem_low; new->iomem_high = orig->iomem_high; if (orig->context_str != NULL) { new->context_str = orig->context_str; } else { cil_context_init(&new->context); cil_copy_fill_context(db, orig->context, new->context); } *copy = new; return SEPOL_OK; } int cil_copy_ioportcon(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_ioportcon *orig = data; struct cil_ioportcon *new = NULL; cil_ioportcon_init(&new); new->ioport_low = orig->ioport_low; new->ioport_high = orig->ioport_high; if (orig->context_str != NULL) { new->context_str = orig->context_str; } else { cil_context_init(&new->context); cil_copy_fill_context(db, orig->context, new->context); } *copy = new; return SEPOL_OK; } int cil_copy_pcidevicecon(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_pcidevicecon *orig = data; struct cil_pcidevicecon *new = NULL; cil_pcidevicecon_init(&new); new->dev = orig->dev; if (orig->context_str != NULL) { new->context_str = orig->context_str; } else { cil_context_init(&new->context); cil_copy_fill_context(db, orig->context, new->context); } *copy = new; return SEPOL_OK; } static int cil_copy_devicetreecon(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_devicetreecon *orig = data; struct cil_devicetreecon *new = NULL; cil_devicetreecon_init(&new); new->path = orig->path; if (orig->context_str != NULL) { new->context_str = orig->context_str; } else { cil_context_init(&new->context); cil_copy_fill_context(db, orig->context, new->context); } *copy = new; return SEPOL_OK; } int cil_copy_fsuse(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_fsuse *orig = data; struct cil_fsuse *new = NULL; cil_fsuse_init(&new); new->type = orig->type; new->fs_str = orig->fs_str; if (orig->context_str != NULL) { new->context_str = orig->context_str; } else { cil_context_init(&new->context); cil_copy_fill_context(db, orig->context, new->context); } *copy = new; return SEPOL_OK; } int cil_copy_expr(struct cil_db *db, struct cil_list *orig, struct cil_list **new) { struct cil_list_item *curr; if (orig == NULL) { *new = NULL; return SEPOL_OK; } cil_list_init(new, orig->flavor); cil_list_for_each(curr, orig) { switch (curr->flavor) { case CIL_LIST: { struct cil_list *sub_list; cil_copy_expr(db, curr->data, &sub_list); cil_list_append(*new, CIL_LIST, sub_list); break; } case CIL_STRING: cil_list_append(*new, CIL_STRING, curr->data); break; case CIL_DATUM: cil_list_append(*new, curr->flavor, curr->data); break; case CIL_OP: cil_list_append(*new, curr->flavor, curr->data); break; case CIL_CONS_OPERAND: cil_list_append(*new, curr->flavor, curr->data); break; default: cil_log(CIL_INFO, "Unknown flavor %d in expression being copied\n",curr->flavor); cil_list_append(*new, curr->flavor, curr->data); break; } } return SEPOL_OK; } int cil_copy_constrain(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_constrain *orig = data; struct cil_constrain *new = NULL; cil_constrain_init(&new); cil_copy_classperms_list(orig->classperms, &new->classperms); cil_copy_expr(db, orig->str_expr, &new->str_expr); cil_copy_expr(db, orig->datum_expr, &new->datum_expr); *copy = new; return SEPOL_OK; } int cil_copy_validatetrans(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_validatetrans *orig = data; struct cil_validatetrans *new = NULL; cil_validatetrans_init(&new); new->class_str = orig->class_str; cil_copy_expr(db, orig->str_expr, &new->str_expr); cil_copy_expr(db, orig->datum_expr, &new->datum_expr); *copy = new; return SEPOL_OK; } int cil_copy_call(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_call *orig = data; struct cil_call *new = NULL; int rc = SEPOL_ERR; cil_call_init(&new); new->macro_str = orig->macro_str; new->macro = orig->macro; if (orig->args_tree != NULL) { cil_tree_init(&new->args_tree); rc = cil_copy_ast(db, orig->args_tree->root, new->args_tree->root); if (rc != SEPOL_OK) { goto exit; } } new->copied = orig->copied; *copy = new; return SEPOL_OK; exit: cil_destroy_call(new); return rc; } static 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) { if (FLAVOR(datum) != CIL_MACRO) { cil_tree_log(NODE(orig), CIL_ERR, "Macro %s being copied", key); cil_tree_log(NODE(datum), CIL_ERR, " Conflicts with %s already declared", cil_node_to_string(NODE(datum))); return SEPOL_ERR; } cil_tree_log(NODE(orig), CIL_WARN, "Skipping macro %s", key); cil_tree_log(NODE(datum), CIL_WARN, " Previously declared"); *copy = NULL; } else { struct cil_macro *new; cil_macro_init(&new); if (orig->params != NULL) { cil_copy_list(orig->params, &new->params); } *copy = new; } return SEPOL_OK; } int cil_copy_optional(__attribute__((unused)) struct cil_db *db, __attribute__((unused)) void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_optional *new; cil_optional_init(&new); *copy = new; 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; } static 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; } static 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; } static 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; } static 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; } static 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; } static 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; } static 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; } static int cil_copy_src_info(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_src_info *orig = data; struct cil_src_info *new = NULL; cil_src_info_init(&new); new->kind = orig->kind; new->hll_line = orig->hll_line; new->path = orig->path; *copy = new; return SEPOL_OK; } static int __cil_copy_node_helper(struct cil_tree_node *orig, 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; enum cil_sym_index sym_index = CIL_SYM_UNKNOWN; symtab_t *symtab = NULL; void *data = NULL; int (*copy_func)(struct cil_db *db, void *data, void **copy, symtab_t *symtab) = NULL; struct cil_blockinherit *blockinherit = NULL; if (orig == NULL || extra_args == NULL) { goto exit; } args = extra_args; parent = args->dest; db = args->db; switch (orig->flavor) { case CIL_BLOCK: copy_func = &cil_copy_block; break; case CIL_BLOCKABSTRACT: if (args->orig_dest->flavor == CIL_BLOCKINHERIT) { /* When inheriting a block, don't copy any blockabstract * statements. Inheriting a block from a block that was * just inherited never worked. */ return SEPOL_OK; } 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_ordered; 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_ordered; break; case CIL_USER: copy_func = &cil_copy_user; break; case CIL_USERATTRIBUTE: copy_func = &cil_copy_userattribute; break; case CIL_USERATTRIBUTESET: copy_func = &cil_copy_userattributeset; break; case CIL_USERROLE: copy_func = &cil_copy_userrole; break; case CIL_USERLEVEL: copy_func = &cil_copy_userlevel; break; case CIL_USERRANGE: copy_func = &cil_copy_userrange; break; case CIL_USERBOUNDS: copy_func = &cil_copy_bounds; break; case CIL_USERPREFIX: copy_func = &cil_copy_userprefix; break; case CIL_ROLE: copy_func = &cil_copy_role; break; case CIL_ROLETYPE: copy_func = &cil_copy_roletype; break; case CIL_ROLEBOUNDS: copy_func = &cil_copy_bounds; break; case CIL_ROLEATTRIBUTE: copy_func = &cil_copy_roleattribute; break; case CIL_ROLEATTRIBUTESET: copy_func = &cil_copy_roleattributeset; break; case CIL_ROLEALLOW: copy_func = &cil_copy_roleallow; break; case CIL_TYPE: copy_func = &cil_copy_type; break; case CIL_TYPEBOUNDS: copy_func = &cil_copy_bounds; break; case CIL_TYPEPERMISSIVE: copy_func = cil_copy_typepermissive; break; case CIL_TYPEATTRIBUTE: copy_func = &cil_copy_typeattribute; break; case CIL_TYPEATTRIBUTESET: copy_func = &cil_copy_typeattributeset; break; case CIL_EXPANDTYPEATTRIBUTE: copy_func = &cil_copy_expandtypeattribute; break; case CIL_TYPEALIAS: copy_func = &cil_copy_alias; break; case CIL_TYPEALIASACTUAL: copy_func = &cil_copy_aliasactual; break; case CIL_ROLETRANSITION: copy_func = &cil_copy_roletransition; break; case CIL_NAMETYPETRANSITION: copy_func = &cil_copy_nametypetransition; break; case CIL_RANGETRANSITION: copy_func = &cil_copy_rangetransition; break; case CIL_TUNABLE: copy_func = &cil_copy_tunable; break; case CIL_BOOL: copy_func = &cil_copy_bool; break; case CIL_AVRULE: case CIL_AVRULEX: copy_func = &cil_copy_avrule; break; case CIL_PERMISSIONX: copy_func = &cil_copy_permissionx; break; case CIL_DENY_RULE: copy_func = &cil_copy_deny_rule; 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_ordered; break; case CIL_SENSITIVITYORDER: copy_func = &cil_copy_ordered; break; case CIL_LEVEL: copy_func = &cil_copy_level; break; case CIL_LEVELRANGE: copy_func = &cil_copy_levelrange; break; case CIL_CONTEXT: copy_func = &cil_copy_context; break; case CIL_NETIFCON: copy_func = &cil_copy_netifcon; break; case CIL_GENFSCON: copy_func = &cil_copy_genfscon; break; case CIL_FILECON: copy_func = &cil_copy_filecon; break; case CIL_NODECON: copy_func = &cil_copy_nodecon; break; case CIL_IBPKEYCON: copy_func = &cil_copy_ibpkeycon; break; case CIL_IBENDPORTCON: copy_func = &cil_copy_ibendportcon; break; case CIL_PORTCON: copy_func = &cil_copy_portcon; break; case CIL_PIRQCON: copy_func = &cil_copy_pirqcon; break; case CIL_IOMEMCON: copy_func = &cil_copy_iomemcon; break; case CIL_IOPORTCON: copy_func = &cil_copy_ioportcon; break; case CIL_PCIDEVICECON: copy_func = &cil_copy_pcidevicecon; break; case CIL_DEVICETREECON: copy_func = &cil_copy_devicetreecon; break; case CIL_FSUSE: copy_func = &cil_copy_fsuse; break; case CIL_CONSTRAIN: case CIL_MLSCONSTRAIN: copy_func = &cil_copy_constrain; break; case CIL_VALIDATETRANS: case CIL_MLSVALIDATETRANS: copy_func = &cil_copy_validatetrans; break; case CIL_CALL: copy_func = &cil_copy_call; break; case CIL_MACRO: copy_func = &cil_copy_macro; break; case CIL_NODE: copy_func = &cil_copy_node; break; case CIL_OPTIONAL: copy_func = &cil_copy_optional; break; case CIL_IPADDR: copy_func = &cil_copy_ipaddr; break; case CIL_CONDBLOCK: copy_func = &cil_copy_condblock; break; case CIL_BOOLEANIF: copy_func = &cil_copy_boolif; break; case CIL_TUNABLEIF: copy_func = &cil_copy_tunif; break; case CIL_DEFAULTUSER: case CIL_DEFAULTROLE: case CIL_DEFAULTTYPE: copy_func = &cil_copy_default; break; case CIL_DEFAULTRANGE: copy_func = &cil_copy_defaultrange; break; case CIL_HANDLEUNKNOWN: copy_func = &cil_copy_handleunknown; break; case CIL_MLS: copy_func = &cil_copy_mls; break; case CIL_SRC_INFO: copy_func = &cil_copy_src_info; break; default: goto exit; } if (orig->flavor >= CIL_MIN_DECLARATIVE) { rc = cil_flavor_to_symtab_index(orig->flavor, &sym_index); if (rc != SEPOL_OK) { goto exit; } rc = cil_get_symtab(parent, &symtab, sym_index); if (rc != SEPOL_OK) { goto exit; } } rc = (*copy_func)(db, orig->data, &data, symtab); if (rc == SEPOL_OK) { if (orig->flavor == CIL_MACRO && data == NULL) { /* Skipping macro re-declaration */ if (args->orig_dest->flavor != CIL_BLOCKINHERIT) { cil_log(CIL_ERR, " Re-declaration of macro is only allowed when inheriting a block\n"); return SEPOL_ERR; } *finished = CIL_TREE_SKIP_HEAD; return SEPOL_OK; } cil_tree_node_init(&new); new->parent = parent; new->line = orig->line; new->hll_offset = orig->hll_offset; new->flavor = orig->flavor; new->data = data; if (orig->flavor == CIL_BLOCK && DATUM(data)->nodes->head != NULL) { /* Duplicate block */ if (args->orig_dest->flavor != CIL_BLOCKINHERIT) { cil_log(CIL_ERR, " Re-declaration of block is only allowed when inheriting a block\n"); rc = SEPOL_ERR; goto exit; } cil_list_append(DATUM(new->data)->nodes, CIL_NODE, new); } else if (orig->flavor >= CIL_MIN_DECLARATIVE) { /* Check the flavor of data if was found in the destination symtab */ if (DATUM(data)->nodes->head && FLAVOR(data) != orig->flavor) { cil_tree_log(orig, CIL_ERR, "Incompatible flavor when trying to copy %s", DATUM(data)->name); cil_tree_log(NODE(data), CIL_ERR, "Note: conflicting declaration"); new->flavor = FLAVOR(data); rc = SEPOL_ERR; goto exit; } rc = cil_add_decl_to_symtab(db, symtab, DATUM(orig->data)->name, DATUM(data), new); if (rc != SEPOL_OK) { if (rc == SEPOL_EEXIST) { cil_symtab_datum_destroy(data); free(data); data = NULL; rc = SEPOL_OK; } else { goto exit; } } namespace = new; while (namespace->flavor != CIL_MACRO && namespace->flavor != CIL_BLOCK && namespace->flavor != CIL_ROOT) { namespace = namespace->parent; } if (namespace->flavor == CIL_MACRO) { rc = cil_verify_decl_does_not_shadow_macro_parameter(namespace->data, orig, DATUM(orig->data)->name); if (rc != SEPOL_OK) { goto exit; } } } if (new->flavor == CIL_BLOCKINHERIT) { blockinherit = new->data; // if a blockinherit statement is copied before blockinherit are // resolved (like in an in-statement), the block will not have been // resolved yet, so there's nothing to append yet. This is fine, // the copied blockinherit statement will be handled later, as if // it wasn't in an in-statement if (blockinherit->block != NULL) { cil_list_append(blockinherit->block->bi_nodes, CIL_NODE, new); } } if (parent->cl_head == NULL) { parent->cl_head = new; parent->cl_tail = new; } else { parent->cl_tail->next = new; parent->cl_tail = new; } if (orig->cl_head != NULL) { args->dest = new; } } else { cil_tree_log(orig, CIL_ERR, "Problem copying %s node", cil_node_to_string(orig)); goto exit; } return SEPOL_OK; exit: cil_tree_node_destroy(&new); return rc; } static 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.orig_dest = dest; 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_tree_log(dest, CIL_ERR, "Failed to copy %s to %s", cil_node_to_string(orig), cil_node_to_string(dest)); goto exit; } return SEPOL_OK; exit: return rc; } libsepol-3.8.1/cil/src/cil_copy_ast.h000066400000000000000000000205261476211737200175320ustar00rootroot00000000000000/* * 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_ordered(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab); 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_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_user(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_userattribute(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_userattributeset(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_userrole(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_userlevel(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_userrange(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_userbounds(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_userprefix(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_role(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_roletype(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_rolebounds(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_roleattribute(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_roleattributeset(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_roleallow(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_type(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_typebounds(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_typepermissive(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_typeattribute(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_typeattributeset(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_typealias(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_nametypetransition(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_rangetransition(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_bool(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_avrule(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_deny_rule(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) 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); void cil_copy_fill_level(struct cil_db *db, struct cil_level *orig, struct cil_level **new); int cil_copy_level(struct cil_db *db, void *data, void **copy, symtab_t *symtab); void cil_copy_fill_levelrange(struct cil_db *db, struct cil_levelrange *orig, struct cil_levelrange *new); int cil_copy_levelrange(struct cil_db *db, void *data, void **copy, symtab_t *symtab); void cil_copy_fill_context(struct cil_db *db, struct cil_context *orig, struct cil_context *new); int cil_copy_context(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_netifcon(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_genfscon(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_filecon(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_nodecon(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_ibpkeycon(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_portcon(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_pirqcon(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_iomemcon(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_ioportcon(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_pcidevicecon(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_fsuse(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_exrp(struct cil_db *db, struct cil_list *orig, struct cil_list **new); int cil_copy_constrain(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_validatetrans(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_call(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_optional(struct cil_db *db, void *data, void **copy, symtab_t *symtab); void cil_copy_fill_ipaddr(struct cil_ipaddr *orig, struct cil_ipaddr *new); int cil_copy_ipaddr(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_boolif(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_ast(struct cil_db *db, struct cil_tree_node *orig, struct cil_tree_node *dest); #endif libsepol-3.8.1/cil/src/cil_deny.c000066400000000000000000001125201476211737200166370ustar00rootroot00000000000000/* * This file is public domain software, i.e. not copyrighted. * * Warranty Exclusion * ------------------ * You agree that this software is a non-commercially developed program * that may contain "bugs" (as that term is used in the industry) and * that it may not function as intended. The software is licensed * "as is". NSA makes no, and hereby expressly disclaims all, warranties, * express, implied, statutory, or otherwise with respect to the software, * including noninfringement and the implied warranties of merchantability * and fitness for a particular purpose. * * Limitation of Liability *----------------------- * In no event will NSA be liable for any damages, including loss of data, * lost profits, cost of cover, or other special, incidental, consequential, * direct or indirect damages arising from the software or the use thereof, * however caused and on any theory of liability. This limitation will apply * even if NSA has been advised of the possibility of such damage. You * acknowledge that this is a reasonable allocation of risk. * * Original author: James Carter */ #include #include "cil_internal.h" #include "cil_find.h" #include "cil_flavor.h" #include "cil_list.h" #include "cil_strpool.h" #include "cil_log.h" #include "cil_symtab.h" #include "cil_build_ast.h" #include "cil_copy_ast.h" #include "cil_deny.h" #define CIL_DENY_ATTR_PREFIX "deny_rule_attr" /* * A deny rule is like a neverallow rule, except that permissions are * removed rather than an error reported. * * (allow S1 T1 P1) * (deny S2 T2 P2) * * First, write the allow rule with all of the permissions not in the deny rule * P3 = P1 and not P2 * (allow S1 T1 P3) * * Obviously, the rule is only written if P3 is not an empty list. This goes * for the rest of the rules as well--they are only written if the source and * target exist. * * The remaining rules will only involve the common permissions * P4 = P1 and P2 * * Next, write the allow rule for any types in S1 that are not in S2 * S3 = S1 and not S2 * (allow S3 T1 P4) * * Finally, write any allow rules needed to cover the types in T1 that are * not in T2. Since, T1 and T2 might be "self", "notself", or "other", this * requires more complicated handling. Any rule with "self" will not match * a rule with either "notself" or "other". * * if (T1 is self and T2 is self) or (T1 is notself and T2 is notself) then * Nothing more needs to be done. * * The rest of the rules will depend on the intersection of S1 and S2 * which cannot be the empty set since the allow and deny rules match. * S4 = S1 and S2 * * if T1 is notself or T1 is other or T2 is notself or T2 is other then * if T1 is notself then * if T2 is other then * T = ALL and not S2 * (allow S4 T P4) * else [T2 is not self, notself, or other] * S5 = S4 and not T2 * S6 = S4 and T2 * TA = ALL and not T2 * TB = TA and not S4 * (allow S6 TA P4) * (allow S5 TB P4) * if cardinality(S5) > 1 then * (allow S5 other P4) * else if T1 is other then * (allow S3 S4 P4) * if T2 is notself then * [Nothing else is needed] * else if T2 is other then * (allow S4 S3 P4) * else [T2 is not self, notself, or other] * S5 = S4 and not T2 * S6 = S4 and T2 * TC = S1 and not T2 * TD = S3 and not T2 * (allow S6 TC P4) * (allow S5 TD P4) * if cardinality(S5) > 1 then * (allow S5 other P4) * else [T1 is not self, notself, or other] * S8 = S4 and T1 * (allow S8 self P4) * if T2 is notself then * [Nothing else is needed] * else [T2 is other] * T = T1 and not S2 * (allow S4 T P4) * else [Neither T1 nor T2 are notself or other] * if T1 is self and T2 is not self then * S5 = S4 and not T2 * (allow S5 self P4) * else if T1 is not self and T2 is self then * S7 = S4 and not T1 * S8 = S4 and T1 * T8 = T1 and not S4 * (allow S7 T1 P4) * (allow S8 T8 P4) * if cardinality(S8) > 1 then * (allow S8 other P4) * else [Neither T1 nor T2 is self] * T3 = T1 and not T2 * (allow S4 T3 P4) */ static int cil_perm_match(const struct cil_perm *p1, const struct cil_list *pl2) { struct cil_list_item *curr; cil_list_for_each(curr, pl2) { struct cil_perm *p = curr->data; if (p == p1) { return CIL_TRUE; } } return CIL_FALSE; } static int cil_class_perm_match(const struct cil_class *c1, const struct cil_perm *p1, const struct cil_list *cpl2) { struct cil_list_item *curr; cil_list_for_each(curr, cpl2) { if (curr->flavor == CIL_CLASSPERMS) { struct cil_classperms *cp = curr->data; if (FLAVOR(cp->class) == CIL_CLASS) { if (cp->class == c1) { if (cil_perm_match(p1, cp->perms)) { return CIL_TRUE; } } } else { /* MAP */ struct cil_list_item *p; cil_list_for_each(p, cp->perms) { struct cil_perm *cmp = p->data; if (cil_class_perm_match(c1, p1, cmp->classperms)) { return CIL_TRUE; } } } } else { /* SET */ struct cil_classperms_set *cp_set = curr->data; struct cil_classpermission *cp = cp_set->set; if (cil_class_perm_match(c1, p1, cp->classperms)) { return CIL_TRUE; } } } return CIL_FALSE; } static int cil_classperms_match_any(const struct cil_classperms *cp1, const struct cil_list *cpl2) { struct cil_list_item *curr; cil_list_for_each(curr, cp1->perms) { struct cil_perm *perm = curr->data; if (cil_class_perm_match(cp1->class, perm, cpl2)) { return CIL_TRUE; } } return CIL_FALSE; } int cil_classperms_list_match_any(const struct cil_list *cpl1, const struct cil_list *cpl2) { struct cil_list_item *curr; if (!cpl1 || !cpl2) { return (!cpl1 && !cpl2) ? CIL_TRUE : CIL_FALSE; } cil_list_for_each(curr, cpl1) { if (curr->flavor == CIL_CLASSPERMS) { struct cil_classperms *cp = curr->data; if (FLAVOR(cp->class) == CIL_CLASS) { if (cil_classperms_match_any(cp, cpl2)) { return CIL_TRUE; } } else { /* MAP */ struct cil_list_item *p; cil_list_for_each(p, cp->perms) { struct cil_perm *cmp = p->data; if (cil_classperms_list_match_any(cmp->classperms, cpl2)) { return CIL_TRUE; } } } } else { /* SET */ struct cil_classperms_set *cp_set = curr->data; struct cil_classpermission *cp = cp_set->set; if (cil_classperms_list_match_any(cp->classperms, cpl2)) { return CIL_TRUE; } } } return CIL_FALSE; } static int cil_classperms_match_all(const struct cil_classperms *cp1, const struct cil_list *cpl2) { struct cil_list_item *curr; cil_list_for_each(curr, cp1->perms) { struct cil_perm *perm = curr->data; if (!cil_class_perm_match(cp1->class, perm, cpl2)) { return CIL_FALSE; } } return CIL_TRUE; } int cil_classperms_list_match_all(const struct cil_list *cpl1, const struct cil_list *cpl2) { struct cil_list_item *curr; if (!cpl1 || !cpl2) { return (!cpl1 && !cpl2) ? CIL_TRUE : CIL_FALSE; } cil_list_for_each(curr, cpl1) { if (curr->flavor == CIL_CLASSPERMS) { struct cil_classperms *cp = curr->data; if (FLAVOR(cp->class) == CIL_CLASS) { if (!cil_classperms_match_all(cp, cpl2)) { return CIL_FALSE; } } else { /* MAP */ struct cil_list_item *p; cil_list_for_each(p, cp->perms) { struct cil_perm *cmp = p->data; if (!cil_classperms_list_match_all(cmp->classperms, cpl2)) { return CIL_FALSE; } } } } else { /* SET */ struct cil_classperms_set *cp_set = curr->data; struct cil_classpermission *cp = cp_set->set; if (!cil_classperms_list_match_all(cp->classperms, cpl2)) { return CIL_FALSE; } } } return CIL_TRUE; } static void cil_classperms_copy(struct cil_classperms **new, const struct cil_classperms *old) { cil_classperms_init(new); (*new)->class_str = old->class_str; (*new)->class = old->class; cil_copy_list(old->perm_strs, &(*new)->perm_strs); cil_copy_list(old->perms, &(*new)->perms); } static void cil_classperms_set_copy(struct cil_classperms_set **new, const struct cil_classperms_set *old) { cil_classperms_set_init(new); (*new)->set_str = old->set_str; (*new)->set = old->set; } void cil_classperms_list_copy(struct cil_list **new, const struct cil_list *old) { struct cil_list_item *curr; if (!new) { return; } if (!old) { *new = NULL; return; } cil_list_init(new, CIL_LIST); cil_list_for_each(curr, old) { if (curr->flavor == CIL_CLASSPERMS) { struct cil_classperms *new_cp; cil_classperms_copy(&new_cp, curr->data); cil_list_append(*new, CIL_CLASSPERMS, new_cp); } else { /* SET */ struct cil_classperms_set *new_cps; cil_classperms_set_copy(&new_cps, curr->data); cil_list_append(*new, CIL_CLASSPERMS_SET, new_cps); } } if (cil_list_is_empty(*new)) { cil_list_destroy(new, CIL_FALSE); } } /* Append cp1 and cpl2 to result */ static void cil_classperms_and(struct cil_list **result, const struct cil_classperms *cp1, const struct cil_list *cpl2) { struct cil_classperms *new_cp = NULL; struct cil_list_item *curr; if (cil_classperms_match_all(cp1, cpl2)) { cil_classperms_copy(&new_cp, cp1); cil_list_append(*result, CIL_CLASSPERMS, new_cp); return; } cil_list_for_each(curr, cp1->perms) { struct cil_perm *perm = curr->data; if (cil_class_perm_match(cp1->class, perm, cpl2)) { if (new_cp == NULL) { cil_classperms_init(&new_cp); new_cp->class_str = cp1->class_str; new_cp->class = cp1->class; cil_list_init(&new_cp->perm_strs, CIL_PERM); cil_list_init(&new_cp->perms, CIL_PERM); cil_list_append(*result, CIL_CLASSPERMS, new_cp); } cil_list_append(new_cp->perm_strs, CIL_STRING, perm->datum.fqn); cil_list_append(new_cp->perms, CIL_DATUM, perm); } } } /* Append cp1 and cpl2 to result */ static void cil_classperms_map_and(struct cil_list **result, const struct cil_classperms *cp1, const struct cil_list *cpl2) { struct cil_classperms *new_cp = NULL; struct cil_list_item *p; cil_list_for_each(p, cp1->perms) { struct cil_perm *map_perm = p->data; if (cil_classperms_list_match_all(map_perm->classperms, cpl2)) { if (new_cp == NULL) { cil_classperms_init(&new_cp); new_cp->class_str = cp1->class_str; new_cp->class = cp1->class; cil_list_init(&new_cp->perm_strs, CIL_PERM); cil_list_init(&new_cp->perms, CIL_PERM); cil_list_append(*result, CIL_CLASSPERMS, new_cp); } cil_list_append(new_cp->perm_strs, CIL_STRING, map_perm->datum.fqn); cil_list_append(new_cp->perms, CIL_DATUM, map_perm); } else { struct cil_list *new_cpl = NULL; cil_classperms_list_and(&new_cpl, map_perm->classperms, cpl2); if (new_cpl) { struct cil_list_item *i; cil_list_for_each(i, new_cpl) { cil_list_append(*result, i->flavor, i->data); } cil_list_destroy(&new_cpl, CIL_FALSE); } } } } /* Append cps1 and cpl2 to result */ static void cil_classperms_set_and(struct cil_list **result, const struct cil_classperms_set *cps1, const struct cil_list *cpl2) { struct cil_classpermission *cp = cps1->set; if (cil_classperms_list_match_all(cp->classperms, cpl2)) { struct cil_classperms_set *new_cps; cil_classperms_set_copy(&new_cps, cps1); cil_list_append(*result, CIL_CLASSPERMS_SET, new_cps); } else { struct cil_list *new_cpl; cil_classperms_list_and(&new_cpl, cp->classperms, cpl2); if (new_cpl) { struct cil_list_item *i; cil_list_for_each(i, new_cpl) { cil_list_append(*result, i->flavor, i->data); } cil_list_destroy(&new_cpl, CIL_FALSE); } } } /* result = cpl1 and cpl2 */ void cil_classperms_list_and(struct cil_list **result, const struct cil_list *cpl1, const struct cil_list *cpl2) { struct cil_list_item *curr; if (!result) { return; } if (!cpl1 || !cpl2) { *result = NULL; return; } if (cil_classperms_list_match_all(cpl1, cpl2)) { cil_classperms_list_copy(result, cpl1); return; } cil_list_init(result, CIL_LIST); cil_list_for_each(curr, cpl1) { if (curr->flavor == CIL_CLASSPERMS) { struct cil_classperms *cp = curr->data; if (FLAVOR(cp->class) == CIL_CLASS) { cil_classperms_and(result, cp, cpl2); } else { /* MAP */ cil_classperms_map_and(result, cp, cpl2); } } else { /* SET */ struct cil_classperms_set *cps = curr->data; cil_classperms_set_and(result, cps, cpl2); } } if (cil_list_is_empty(*result)) { cil_list_destroy(result, CIL_FALSE); } } /* Append cp1 and not cpl2 to result */ static void cil_classperms_andnot(struct cil_list **result, const struct cil_classperms *cp1, const struct cil_list *cpl2) { struct cil_classperms *new_cp = NULL; struct cil_list_item *curr; if (!cil_classperms_match_any(cp1, cpl2)) { cil_classperms_copy(&new_cp, cp1); cil_list_append(*result, CIL_CLASSPERMS, new_cp); return; } cil_list_for_each(curr, cp1->perms) { struct cil_perm *perm = curr->data; if (!cil_class_perm_match(cp1->class, perm, cpl2)) { if (new_cp == NULL) { cil_classperms_init(&new_cp); new_cp->class_str = cp1->class_str; new_cp->class = cp1->class; cil_list_init(&new_cp->perm_strs, CIL_PERM); cil_list_init(&new_cp->perms, CIL_PERM); cil_list_append(*result, CIL_CLASSPERMS, new_cp); } cil_list_append(new_cp->perm_strs, CIL_STRING, perm->datum.fqn); cil_list_append(new_cp->perms, CIL_DATUM, perm); } } } /* Append cp1 and not cpl2 to result */ static void cil_classperms_map_andnot(struct cil_list **result, const struct cil_classperms *cp1, const struct cil_list *cpl2) { struct cil_classperms *new_cp = NULL; struct cil_list_item *p; cil_list_for_each(p, cp1->perms) { struct cil_perm *map_perm = p->data; if (!cil_classperms_list_match_any(map_perm->classperms, cpl2)) { if (new_cp == NULL) { cil_classperms_init(&new_cp); new_cp->class_str = cp1->class_str; new_cp->class = cp1->class; cil_list_init(&new_cp->perm_strs, CIL_PERM); cil_list_init(&new_cp->perms, CIL_PERM); cil_list_append(*result, CIL_CLASSPERMS, new_cp); } cil_list_append(new_cp->perm_strs, CIL_STRING, map_perm->datum.fqn); cil_list_append(new_cp->perms, CIL_DATUM, map_perm); } else { struct cil_list *new_cpl = NULL; cil_classperms_list_andnot(&new_cpl, map_perm->classperms, cpl2); if (new_cpl) { struct cil_list_item *i; cil_list_for_each(i, new_cpl) { cil_list_append(*result, i->flavor, i->data); } cil_list_destroy(&new_cpl, CIL_FALSE); } } } } /* Append cps1 and not cpl2 to result */ static void cil_classperms_set_andnot(struct cil_list **result, const struct cil_classperms_set *cps1, const struct cil_list *cpl2) { struct cil_classpermission *cp = cps1->set; if (!cil_classperms_list_match_any(cp->classperms, cpl2)) { struct cil_classperms_set *new_cps; cil_classperms_set_copy(&new_cps, cps1); cil_list_append(*result, CIL_CLASSPERMS_SET, new_cps); } else { struct cil_list *new_cpl; cil_classperms_list_andnot(&new_cpl, cp->classperms, cpl2); if (new_cpl) { struct cil_list_item *i; cil_list_for_each(i, new_cpl) { cil_list_append(*result, i->flavor, i->data); } cil_list_destroy(&new_cpl, CIL_FALSE); } } } /* result = cpl1 and not cpl2 */ void cil_classperms_list_andnot(struct cil_list **result, const struct cil_list *cpl1, const struct cil_list *cpl2) { struct cil_list_item *curr; if (!result) { return; } if (!cpl1) { *result = NULL; return; } if (!cpl2 || !cil_classperms_list_match_any(cpl1, cpl2)) { cil_classperms_list_copy(result, cpl1); return; } cil_list_init(result, CIL_LIST); cil_list_for_each(curr, cpl1) { if (curr->flavor == CIL_CLASSPERMS) { struct cil_classperms *cp = curr->data; if (FLAVOR(cp->class) == CIL_CLASS) { cil_classperms_andnot(result, cp, cpl2); } else { /* MAP */ cil_classperms_map_andnot(result, cp, cpl2); } } else { /* SET */ struct cil_classperms_set *cps = curr->data; cil_classperms_set_andnot(result, cps, cpl2); } } if (cil_list_is_empty(*result)) { cil_list_destroy(result, CIL_FALSE); } } static int cil_datum_cardinality(const struct cil_symtab_datum *d) { if (!d) { return 0; } if (FLAVOR(d) != CIL_TYPEATTRIBUTE) { return 1; } else { struct cil_typeattribute *a = (struct cil_typeattribute *)d; return ebitmap_cardinality(a->types); } } /* result = ALL and not d2 */ static int cil_datum_not(ebitmap_t *result, const struct cil_symtab_datum *d, int max) { int rc = SEPOL_OK; if (FLAVOR(d) != CIL_TYPEATTRIBUTE) { struct cil_type *t = (struct cil_type *)d; ebitmap_t e; ebitmap_init(&e); rc = ebitmap_set_bit(&e, t->value, 1); if (rc != SEPOL_OK) { ebitmap_destroy(&e); goto exit; } ebitmap_init(result); rc = ebitmap_not(result, &e, max); if (rc != SEPOL_OK) { ebitmap_destroy(&e); ebitmap_destroy(result); goto exit; } ebitmap_destroy(&e); } else { struct cil_typeattribute *a = (struct cil_typeattribute *)d; ebitmap_init(result); rc = ebitmap_not(result, a->types, max); if (rc != SEPOL_OK) { ebitmap_destroy(result); goto exit; } } exit: return rc; } /* result = d1 and d2 */ static int cil_datums_and(ebitmap_t *result, const struct cil_symtab_datum *d1, const struct cil_symtab_datum *d2) { int rc = SEPOL_OK; enum cil_flavor f1 = FLAVOR(d1); enum cil_flavor f2 = FLAVOR(d2); if (f1 != CIL_TYPEATTRIBUTE && f2 != CIL_TYPEATTRIBUTE) { struct cil_type *t1 = (struct cil_type *)d1; struct cil_type *t2 = (struct cil_type *)d2; ebitmap_init(result); if (t1->value == t2->value) { rc = ebitmap_set_bit(result, t1->value, 1); if (rc != SEPOL_OK) { ebitmap_destroy(result); goto exit; } } } else if (f1 == CIL_TYPEATTRIBUTE && f2 != CIL_TYPEATTRIBUTE) { struct cil_typeattribute *a1 = (struct cil_typeattribute *)d1; struct cil_type *t2 = (struct cil_type *)d2; ebitmap_init(result); if (ebitmap_get_bit(a1->types, t2->value)) { rc = ebitmap_set_bit(result, t2->value, 1); if (rc != SEPOL_OK) { ebitmap_destroy(result); goto exit; } } } else if (f1 != CIL_TYPEATTRIBUTE && f2 == CIL_TYPEATTRIBUTE) { struct cil_type *t1 = (struct cil_type *)d1; struct cil_typeattribute *a2 = (struct cil_typeattribute *)d2; ebitmap_init(result); if (ebitmap_get_bit(a2->types, t1->value)) { rc = ebitmap_set_bit(result, t1->value, 1); if (rc != SEPOL_OK) { ebitmap_destroy(result); goto exit; } } } else { /* Both are attributes */ struct cil_typeattribute *a1 = (struct cil_typeattribute *)d1; struct cil_typeattribute *a2 = (struct cil_typeattribute *)d2; rc = ebitmap_and(result, a1->types, a2->types); if (rc != SEPOL_OK) { ebitmap_destroy(result); goto exit; } } exit: return rc; } /* result = d1 and not d2 */ static int cil_datums_andnot(ebitmap_t *result, const struct cil_symtab_datum *d1, const struct cil_symtab_datum *d2) { int rc = SEPOL_OK; enum cil_flavor f1 = FLAVOR(d1); enum cil_flavor f2 = FLAVOR(d2); if (f1 != CIL_TYPEATTRIBUTE && f2 != CIL_TYPEATTRIBUTE) { struct cil_type *t1 = (struct cil_type *)d1; struct cil_type *t2 = (struct cil_type *)d2; ebitmap_init(result); if (t1->value != t2->value) { rc = ebitmap_set_bit(result, t1->value, 1); if (rc != SEPOL_OK) { ebitmap_destroy(result); goto exit; } } } else if (f1 == CIL_TYPEATTRIBUTE && f2 != CIL_TYPEATTRIBUTE) { struct cil_typeattribute *a1 = (struct cil_typeattribute *)d1; struct cil_type *t2 = (struct cil_type *)d2; rc = ebitmap_cpy(result, a1->types); if (rc != SEPOL_OK) { goto exit; } rc = ebitmap_set_bit(result, t2->value, 0); if (rc != SEPOL_OK) { ebitmap_destroy(result); goto exit; } } else if (f1 != CIL_TYPEATTRIBUTE && f2 == CIL_TYPEATTRIBUTE) { struct cil_type *t1 = (struct cil_type *)d1; struct cil_typeattribute *a2 = (struct cil_typeattribute *)d2; ebitmap_init(result); if (!ebitmap_get_bit(a2->types, t1->value)) { rc = ebitmap_set_bit(result, t1->value, 1); if (rc != SEPOL_OK) { ebitmap_destroy(result); goto exit; } } } else { /* Both are attributes */ struct cil_typeattribute *a1 = (struct cil_typeattribute *)d1; struct cil_typeattribute *a2 = (struct cil_typeattribute *)d2; rc = ebitmap_andnot(result, a1->types, a2->types, a1->types->highbit); if (rc != SEPOL_OK) { ebitmap_destroy(result); goto exit; } } exit: return rc; } static size_t num_digits(unsigned n) { size_t num = 1; while (n >= 10) { n /= 10; num++; } return num; } static char *cil_create_new_attribute_name(unsigned num) { char *s1 = NULL; char *s2 = NULL; size_t len_num = num_digits(num); size_t len = strlen(CIL_DENY_ATTR_PREFIX) + 1 + len_num + 1; int rc; if (len >= CIL_MAX_NAME_LENGTH) { cil_log(CIL_ERR, "Name length greater than max name length of %d", CIL_MAX_NAME_LENGTH); goto exit; } s1 = cil_malloc(len); rc = snprintf(s1, len, "%s_%u", CIL_DENY_ATTR_PREFIX, num); if (rc < 0 || (size_t)rc >= len) { cil_log(CIL_ERR, "Error creating new attribute name"); free(s1); goto exit; } s2 = cil_strpool_add(s1); free(s1); exit: return s2; } static struct cil_list *cil_create_and_expr_list(enum cil_flavor f1, void *v1, enum cil_flavor f2, void *v2) { struct cil_list *expr; cil_list_init(&expr, CIL_TYPE); cil_list_append(expr, CIL_OP, (void *)CIL_AND); cil_list_append(expr, f1, v1); cil_list_append(expr, f2, v2); return expr; } static struct cil_list *cil_create_andnot_expr_list(enum cil_flavor f1, void *v1, enum cil_flavor f2, void *v2) { struct cil_list *expr, *sub_expr; cil_list_init(&expr, CIL_TYPE); cil_list_append(expr, CIL_OP, (void *)CIL_AND); cil_list_append(expr, f1, v1); cil_list_init(&sub_expr, CIL_TYPE); cil_list_append(sub_expr, CIL_OP, (void *)CIL_NOT); cil_list_append(sub_expr, f2, v2); cil_list_append(expr, CIL_LIST, sub_expr); return expr; } static struct cil_tree_node *cil_create_and_insert_node(struct cil_tree_node *prev, enum cil_flavor flavor, void *data) { struct cil_tree_node *new; cil_tree_node_init(&new); new->parent = prev->parent; new->line = prev->line; new->hll_offset = prev->hll_offset; new->flavor = flavor; new->data = data; new->next = prev->next; prev->next = new; return new; } static int cil_create_and_insert_attribute_and_set(struct cil_db *db, struct cil_tree_node *prev, struct cil_list *str_expr, struct cil_list *datum_expr, ebitmap_t *types, struct cil_symtab_datum **d) { struct cil_tree_node *attr_node = NULL; char *name; struct cil_typeattribute *attr = NULL; struct cil_tree_node *attrset_node = NULL; struct cil_typeattributeset *attrset = NULL; symtab_t *symtab = NULL; int rc = SEPOL_ERR; name = cil_create_new_attribute_name(db->num_types_and_attrs); if (!name) { goto exit; } cil_typeattributeset_init(&attrset); attrset->attr_str = name; attrset->str_expr = str_expr; attrset->datum_expr = datum_expr; cil_typeattribute_init(&attr); cil_list_init(&attr->expr_list, CIL_TYPE); cil_list_append(attr->expr_list, CIL_LIST, datum_expr); attr->types = types; attr->used = CIL_ATTR_AVRULE; attr->keep = (ebitmap_cardinality(types) < db->attrs_expand_size) ? CIL_FALSE : CIL_TRUE; attr_node = cil_create_and_insert_node(prev, CIL_TYPEATTRIBUTE, attr); attrset_node = cil_create_and_insert_node(attr_node, CIL_TYPEATTRIBUTESET, attrset); rc = cil_get_symtab(prev->parent, &symtab, CIL_SYM_TYPES); if (rc != SEPOL_OK) { goto exit; } rc = cil_symtab_insert(symtab, name, &attr->datum, attr_node); if (rc != SEPOL_OK) { goto exit; } db->num_types_and_attrs++; *d = &attr->datum; return SEPOL_OK; exit: if (attr_node) { cil_destroy_typeattribute(attr_node->data); // This will not destroy datum_expr free(attr_node); } if (attrset_node) { prev->next = attrset_node->next; free(attrset_node); } return rc; } struct attr_symtab_map_data { struct cil_symtab_datum *d; ebitmap_t *types; }; static int cil_check_attribute_in_symtab(__attribute__((unused))hashtab_key_t k, hashtab_datum_t d, void *args) { struct attr_symtab_map_data *data = args; if (FLAVOR(d) == CIL_TYPEATTRIBUTE) { struct cil_typeattribute *attr = (struct cil_typeattribute *)d; if (ebitmap_cmp(data->types, attr->types)) { data->d = d; } } return SEPOL_OK; } static struct cil_symtab_datum *cil_check_for_previously_defined_attribute(struct cil_db *db, ebitmap_t *types, struct cil_symtab_datum *d) { symtab_t *local_symtab, *root_symtab; struct attr_symtab_map_data data; int rc; data.d = NULL; data.types = types; local_symtab = d->symtab; root_symtab = &((struct cil_root *)db->ast->root->data)->symtab[CIL_SYM_TYPES]; if (local_symtab != root_symtab) { rc = cil_symtab_map(local_symtab, cil_check_attribute_in_symtab, &data); if (rc != SEPOL_OK) { return NULL; } } if (!data.d) { rc = cil_symtab_map(root_symtab, cil_check_attribute_in_symtab, &data); if (rc != SEPOL_OK) { return NULL; } } return data.d; } static int cil_create_attribute_all_and_not_d(struct cil_db *db, struct cil_symtab_datum *d, struct cil_symtab_datum **d3) { struct cil_list *str_expr; struct cil_list *datum_expr; ebitmap_t *types; int rc; *d3 = NULL; if (!d) { return SEPOL_ERR; } str_expr = cil_create_andnot_expr_list(CIL_OP, (void *)CIL_ALL, CIL_STRING, d->fqn); datum_expr = cil_create_andnot_expr_list(CIL_OP, (void *)CIL_ALL, CIL_DATUM, d); types = cil_malloc(sizeof(*types)); rc = cil_datum_not(types, d, db->num_types); if (rc != SEPOL_OK) { goto exit; } if (ebitmap_is_empty(types)) { rc = SEPOL_OK; goto exit; } if (ebitmap_cardinality(types) == 1) { unsigned i = ebitmap_highest_set_bit(types); *d3 = DATUM(db->val_to_type[i]); ebitmap_destroy(types); rc = SEPOL_OK; goto exit; } *d3 = cil_check_for_previously_defined_attribute(db, types, d); if (*d3) { ebitmap_destroy(types); rc = SEPOL_OK; goto exit; } rc = cil_create_and_insert_attribute_and_set(db, NODE(d), str_expr, datum_expr, types, d3); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: cil_list_destroy(&str_expr, CIL_FALSE); cil_list_destroy(&datum_expr, CIL_FALSE); free(types); return rc; } static int cil_create_attribute_d1_and_not_d2(struct cil_db *db, struct cil_symtab_datum *d1, struct cil_symtab_datum *d2, struct cil_symtab_datum **d3) { struct cil_list *str_expr; struct cil_list *datum_expr; ebitmap_t *types; int rc; if (!d2) { *d3 = d1; return SEPOL_OK; } *d3 = NULL; if (!d1 || d1 == d2) { return SEPOL_OK; } str_expr = cil_create_andnot_expr_list(CIL_STRING, d1->fqn, CIL_STRING, d2->fqn); datum_expr = cil_create_andnot_expr_list(CIL_DATUM, d1, CIL_DATUM, d2); types = cil_malloc(sizeof(*types)); rc = cil_datums_andnot(types, d1, d2); if (rc != SEPOL_OK) { goto exit; } if (ebitmap_is_empty(types)) { rc = SEPOL_OK; goto exit; } if (ebitmap_cardinality(types) == 1) { unsigned i = ebitmap_highest_set_bit(types); *d3 = DATUM(db->val_to_type[i]); ebitmap_destroy(types); rc = SEPOL_OK; goto exit; } *d3 = cil_check_for_previously_defined_attribute(db, types, d1); if (*d3) { ebitmap_destroy(types); rc = SEPOL_OK; goto exit; } rc = cil_create_and_insert_attribute_and_set(db, NODE(d1), str_expr, datum_expr, types, d3); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: cil_list_destroy(&str_expr, CIL_FALSE); cil_list_destroy(&datum_expr, CIL_FALSE); free(types); return rc; } static int cil_create_attribute_d1_and_d2(struct cil_db *db, struct cil_symtab_datum *d1, struct cil_symtab_datum *d2, struct cil_symtab_datum **d3) { struct cil_list *str_expr; struct cil_list *datum_expr; ebitmap_t *types; int rc; if (d1 == d2) { *d3 = d1; return SEPOL_OK; } *d3 = NULL; if (!d1 || !d2) { return SEPOL_OK; } str_expr = cil_create_and_expr_list(CIL_STRING, d1->fqn, CIL_STRING, d2->fqn); datum_expr = cil_create_and_expr_list(CIL_DATUM, d1, CIL_DATUM, d2); types = cil_malloc(sizeof(*types)); rc = cil_datums_and(types, d1, d2); if (rc != SEPOL_OK) { goto exit; } if (ebitmap_is_empty(types)) { rc = SEPOL_OK; goto exit; } if (ebitmap_cardinality(types) == 1) { unsigned i = ebitmap_highest_set_bit(types); *d3 = DATUM(db->val_to_type[i]); ebitmap_destroy(types); rc = SEPOL_OK; goto exit; } *d3 = cil_check_for_previously_defined_attribute(db, types, d1); if (*d3) { ebitmap_destroy(types); rc = SEPOL_OK; goto exit; } rc = cil_create_and_insert_attribute_and_set(db, NODE(d1), str_expr, datum_expr, types, d3); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: cil_list_destroy(&str_expr, CIL_FALSE); cil_list_destroy(&datum_expr, CIL_FALSE); free(types); return rc; } static struct cil_avrule *cil_create_avrule(struct cil_symtab_datum *src, struct cil_symtab_datum *tgt, struct cil_list *classperms) { struct cil_avrule *new; cil_avrule_init(&new); new->is_extended = CIL_FALSE; new->rule_kind = CIL_AVRULE_ALLOWED; new->src_str = src->name; new->src = src; new->tgt_str = tgt->name; new->tgt = tgt; new->perms.classperms = classperms; return new; } static struct cil_tree_node *cil_create_and_add_avrule(struct cil_tree_node *curr, struct cil_symtab_datum *src, struct cil_symtab_datum *tgt, struct cil_list *classperms) { struct cil_avrule *new_avrule; struct cil_list *new_cp_list; if (!src || !tgt) { return curr; } cil_classperms_list_copy(&new_cp_list, classperms); new_avrule = cil_create_avrule(src, tgt, new_cp_list); return cil_create_and_insert_node(curr, CIL_AVRULE, new_avrule); } static int cil_remove_permissions_from_special_rule(struct cil_db *db, struct cil_tree_node *curr, struct cil_symtab_datum *s1, struct cil_symtab_datum *t1, struct cil_symtab_datum *s2, struct cil_symtab_datum *t2, struct cil_list *p4, struct cil_symtab_datum *s3, struct cil_symtab_datum *s4) { int rc; if (t1 == DATUM(db->notselftype)) { if (t2 == DATUM(db->othertype)) { struct cil_symtab_datum *t; rc = cil_create_attribute_all_and_not_d(db, s2, &t); if (rc != SEPOL_OK) { goto exit; } curr = cil_create_and_add_avrule(curr, s4, t, p4); } else { struct cil_symtab_datum *s5, *s6, *ta, *tb; rc = cil_create_attribute_d1_and_not_d2(db, s4, t2, &s5); if (rc != SEPOL_OK) { goto exit; } rc = cil_create_attribute_d1_and_d2(db, s4, t2, &s6); if (rc != SEPOL_OK) { goto exit; } rc = cil_create_attribute_all_and_not_d(db, t2, &ta); if (rc != SEPOL_OK) { goto exit; } rc = cil_create_attribute_d1_and_not_d2(db, ta, s4, &tb); if (rc != SEPOL_OK) { goto exit; } curr = cil_create_and_add_avrule(curr, s6, ta, p4); curr = cil_create_and_add_avrule(curr, s5, tb, p4); if (cil_datum_cardinality(s5) > 1) { curr = cil_create_and_add_avrule(curr, s5, DATUM(db->othertype), p4); } } } else if (t1 == DATUM(db->othertype)) { curr = cil_create_and_add_avrule(curr, s3, s4, p4); if (t2 == DATUM(db->notselftype)) { /* Nothing else is needed */ } else if (t2 == DATUM(db->othertype)) { curr = cil_create_and_add_avrule(curr, s4, s3, p4); } else { struct cil_symtab_datum *s5, *s6, *tc, *td; rc = cil_create_attribute_d1_and_not_d2(db, s4, t2, &s5); if (rc != SEPOL_OK) { goto exit; } rc = cil_create_attribute_d1_and_d2(db, s4, t2, &s6); if (rc != SEPOL_OK) { goto exit; } rc = cil_create_attribute_d1_and_not_d2(db, s1, t2, &tc); if (rc != SEPOL_OK) { goto exit; } rc = cil_create_attribute_d1_and_not_d2(db, s3, t2, &td); if (rc != SEPOL_OK) { goto exit; } curr = cil_create_and_add_avrule(curr, s6, tc, p4); curr = cil_create_and_add_avrule(curr, s5, td, p4); if (cil_datum_cardinality(s5) > 1) { curr = cil_create_and_add_avrule(curr, s5, DATUM(db->othertype), p4); } } } else { struct cil_symtab_datum *s8; rc = cil_create_attribute_d1_and_d2(db, s4, t1, &s8); if (rc != SEPOL_OK) { goto exit; } curr = cil_create_and_add_avrule(curr, s8, DATUM(db->selftype), p4); if (t2 == DATUM(db->notselftype)) { /* Nothing else is needed */ } else { /* t2 == DATUM(db->othertype) */ struct cil_symtab_datum *t; rc = cil_create_attribute_d1_and_not_d2(db, t1, s2, &t); if (rc != SEPOL_OK) { goto exit; } curr = cil_create_and_add_avrule(curr, s4, t, p4); } } return SEPOL_OK; exit: return rc; } static int cil_remove_permissions_from_rule(struct cil_db *db, struct cil_tree_node *allow_node, const struct cil_tree_node *deny_node) { struct cil_avrule *allow_rule = allow_node->data; struct cil_deny_rule *deny_rule = deny_node->data; struct cil_symtab_datum *s1 = allow_rule->src; struct cil_symtab_datum *t1 = allow_rule->tgt; struct cil_list *p1 = allow_rule->perms.classperms; struct cil_symtab_datum *s2 = deny_rule->src; struct cil_symtab_datum *t2 = deny_rule->tgt; struct cil_list *p2 = deny_rule->classperms; struct cil_list *p3 = NULL; struct cil_list *p4 = NULL; struct cil_symtab_datum *s3, *s4; struct cil_tree_node *curr = allow_node; int rc; cil_classperms_list_andnot(&p3, p1, p2); if (!cil_list_is_empty(p3)) {; curr = cil_create_and_add_avrule(curr, s1, t1, p3); } cil_destroy_classperms_list(&p3); p3 = NULL; cil_classperms_list_and(&p4, p1, p2); if (cil_list_is_empty(p4)) { cil_tree_log(allow_node, CIL_ERR, "Allow rule did not match deny rule: No matching class and permissions"); cil_tree_log((struct cil_tree_node *)deny_node, CIL_ERR, "Deny rule"); rc = SEPOL_ERR; goto exit; } rc = cil_create_attribute_d1_and_not_d2(db, s1, s2, &s3); if (rc != SEPOL_OK) { goto exit; } curr = cil_create_and_add_avrule(curr, s3, t1, p4); if ((t1 == DATUM(db->selftype) && t2 == DATUM(db->selftype)) || (t1 == DATUM(db->notselftype) && t2 == DATUM(db->notselftype))) { /* Nothing more needs to be done */ rc = SEPOL_OK; goto exit; } rc = cil_create_attribute_d1_and_d2(db, s1, s2, &s4); if (rc != SEPOL_OK) { goto exit; } if (t1 == DATUM(db->notselftype) || t1 == DATUM(db->othertype) || t2 == DATUM(db->notselftype) || t2 == DATUM(db->othertype)) { rc = cil_remove_permissions_from_special_rule(db, curr, s1, t1, s2, t2, p4, s3, s4); goto exit; } if (t1 == DATUM(db->selftype) && t2 != DATUM(db->selftype)) { struct cil_symtab_datum *s5; rc = cil_create_attribute_d1_and_not_d2(db, s4, t2, &s5); if (rc != SEPOL_OK) { goto exit; } curr = cil_create_and_add_avrule(curr, s5, DATUM(db->selftype), p4); } else if (t1 != DATUM(db->selftype) && t2 == DATUM(db->selftype)) { struct cil_symtab_datum *s7, *s8, *t8; rc = cil_create_attribute_d1_and_not_d2(db, s4, t1, &s7); if (rc != SEPOL_OK) { goto exit; } rc = cil_create_attribute_d1_and_d2(db, s4, t1, &s8); if (rc != SEPOL_OK) { goto exit; } rc = cil_create_attribute_d1_and_not_d2(db, t1, s4, &t8); if (rc != SEPOL_OK) { goto exit; } curr = cil_create_and_add_avrule(curr, s7, t1, p4); curr = cil_create_and_add_avrule(curr, s8, t8, p4); if (cil_datum_cardinality(s8) > 1) { curr = cil_create_and_add_avrule(curr, s8, DATUM(db->othertype), p4); } } else { struct cil_symtab_datum *t3; rc = cil_create_attribute_d1_and_not_d2(db, t1, t2, &t3); if (rc != SEPOL_OK) { goto exit; } curr = cil_create_and_add_avrule(curr, s4, t3, p4); } exit: if (p4) { cil_destroy_classperms_list(&p4); } return rc; } static int cil_find_matching_allow_rules(struct cil_list *matching, struct cil_tree_node *start, struct cil_tree_node *deny_node) { struct cil_deny_rule *deny_rule = deny_node->data; struct cil_avrule target; target.rule_kind = CIL_AVRULE_ALLOWED; target.is_extended = CIL_FALSE; target.src = deny_rule->src; target.tgt = deny_rule->tgt; target.perms.classperms = deny_rule->classperms; return cil_find_matching_avrule_in_ast(start, CIL_AVRULE, &target, matching, CIL_FALSE); } static int cil_process_deny_rule(struct cil_db *db, struct cil_tree_node *start, struct cil_tree_node *deny_node) { struct cil_list *matching; struct cil_list_item *item; int rc; cil_list_init(&matching, CIL_NODE); rc = cil_find_matching_allow_rules(matching, start, deny_node); if (rc != SEPOL_OK) { goto exit; } cil_list_for_each(item, matching) { struct cil_tree_node *allow_node = item->data; rc = cil_remove_permissions_from_rule(db, allow_node, deny_node); cil_tree_node_remove(allow_node); if (rc != SEPOL_OK) { goto exit; } } exit: cil_list_destroy(&matching, CIL_FALSE); return rc; } static int cil_process_deny_rules(struct cil_db *db, struct cil_tree_node *start, struct cil_list *deny_rules) { struct cil_list_item *item; int rc = SEPOL_OK; cil_list_for_each(item, deny_rules) { struct cil_tree_node *deny_node = item->data; rc = cil_process_deny_rule(db, start, deny_node); if (rc != SEPOL_OK) { goto exit; } cil_tree_node_remove(deny_node); } exit: return rc; } static int __cil_find_deny_rules(struct cil_tree_node *node, uint32_t *finished, void *extra_args) { struct cil_list *deny_rules = extra_args; if (node->flavor == CIL_BLOCK) { struct cil_block *block = node->data; if (block->is_abstract == CIL_TRUE) { *finished = CIL_TREE_SKIP_HEAD; } } else if (node->flavor == CIL_MACRO) { *finished = CIL_TREE_SKIP_HEAD; } else if (node->flavor == CIL_DENY_RULE) { cil_list_append(deny_rules, CIL_DENY_RULE, node); } return SEPOL_OK; } int cil_process_deny_rules_in_ast(struct cil_db *db) { struct cil_tree_node *start; struct cil_list *deny_rules; int rc = SEPOL_ERR; cil_list_init(&deny_rules, CIL_DENY_RULE); if (!db) { cil_log(CIL_ERR, "No CIL db provided to process deny rules\n"); goto exit; } start = db->ast->root; rc = cil_tree_walk(start, __cil_find_deny_rules, NULL, NULL, deny_rules); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "An error occurred while getting deny rules\n"); goto exit; } rc = cil_process_deny_rules(db, start, deny_rules); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "An error occurred while processing deny rules\n"); goto exit; } exit: cil_list_destroy(&deny_rules, CIL_FALSE); return rc; } libsepol-3.8.1/cil/src/cil_deny.h000066400000000000000000000033131476211737200166430ustar00rootroot00000000000000/* * This file is public domain software, i.e. not copyrighted. * * Warranty Exclusion * ------------------ * You agree that this software is a non-commercially developed program * that may contain "bugs" (as that term is used in the industry) and * that it may not function as intended. The software is licensed * "as is". NSA makes no, and hereby expressly disclaims all, warranties, * express, implied, statutory, or otherwise with respect to the software, * including noninfringement and the implied warranties of merchantability * and fitness for a particular purpose. * * Limitation of Liability *----------------------- * In no event will NSA be liable for any damages, including loss of data, * lost profits, cost of cover, or other special, incidental, consequential, * direct or indirect damages arising from the software or the use thereof, * however caused and on any theory of liability. This limitation will apply * even if NSA has been advised of the possibility of such damage. You * acknowledge that this is a reasonable allocation of risk. * * Original author: James Carter */ #ifndef CIL_DENY_H_ #define CIL_DENY_H_ int cil_classperms_list_match_any(const struct cil_list *cpl1, const struct cil_list *cpl2); int cil_classperms_list_match_all(const struct cil_list *cpl1, const struct cil_list *cpl2); void cil_classperms_list_copy(struct cil_list **new, const struct cil_list *old); void cil_classperms_list_and(struct cil_list **result, const struct cil_list *cpl1, const struct cil_list *cpl2); void cil_classperms_list_andnot(struct cil_list **result, const struct cil_list *cpl1, const struct cil_list *cpl2); int cil_process_deny_rules_in_ast(struct cil_db *db); #endif /* CIL_DENY_H_ */ libsepol-3.8.1/cil/src/cil_find.c000066400000000000000000000365141476211737200166300ustar00rootroot00000000000000/* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #include #include "cil_internal.h" #include "cil_find.h" #include "cil_flavor.h" #include "cil_list.h" #include "cil_log.h" #include "cil_symtab.h" struct cil_args_find { enum cil_flavor flavor; void *target; struct cil_list *matching; int match_self; }; static int cil_type_match_any(struct cil_symtab_datum *d1, struct cil_symtab_datum *d2) { enum cil_flavor f1 = FLAVOR(d1); enum cil_flavor f2 = FLAVOR(d2); if (f1 != CIL_TYPEATTRIBUTE && f2 != CIL_TYPEATTRIBUTE) { struct cil_type *t1 = (struct cil_type *)d1; struct cil_type *t2 = (struct cil_type *)d2; if (t1->value == t2->value) { return CIL_TRUE; } } else if (f1 == CIL_TYPEATTRIBUTE && f2 != CIL_TYPEATTRIBUTE) { struct cil_typeattribute *a = (struct cil_typeattribute *)d1; struct cil_type *t = (struct cil_type *)d2; if (ebitmap_get_bit(a->types, t->value)) { return CIL_TRUE; } } else if (f1 != CIL_TYPEATTRIBUTE && f2 == CIL_TYPEATTRIBUTE) { struct cil_type *t = (struct cil_type *)d1; struct cil_typeattribute *a = (struct cil_typeattribute *)d2; if (ebitmap_get_bit(a->types, t->value)) { return CIL_TRUE; } } else { /* Both are attributes */ struct cil_typeattribute *a1 = (struct cil_typeattribute *)d1; struct cil_typeattribute *a2 = (struct cil_typeattribute *)d2; if (d1 == d2) { return CIL_TRUE; } else if (ebitmap_match_any(a1->types, a2->types)) { return CIL_TRUE; } } return CIL_FALSE; } static int cil_type_matches(ebitmap_t *matches, struct cil_symtab_datum *d1, struct cil_symtab_datum *d2) { int rc = SEPOL_OK; enum cil_flavor f1 = FLAVOR(d1); enum cil_flavor f2 = FLAVOR(d2); if (f1 == CIL_TYPEATTRIBUTE && f2 == CIL_TYPEATTRIBUTE) { struct cil_typeattribute *a1 = (struct cil_typeattribute *)d1; struct cil_typeattribute *a2 = (struct cil_typeattribute *)d2; rc = ebitmap_and(matches, a1->types, a2->types); } else { ebitmap_init(matches); if (f1 != CIL_TYPEATTRIBUTE && f2 != CIL_TYPEATTRIBUTE) { struct cil_type *t1 = (struct cil_type *)d1; struct cil_type *t2 = (struct cil_type *)d2; if (t1->value == t2->value) { rc = ebitmap_set_bit(matches, t1->value, 1); } } else if (f1 == CIL_TYPEATTRIBUTE && f2 != CIL_TYPEATTRIBUTE) { struct cil_typeattribute *a = (struct cil_typeattribute *)d1; struct cil_type *t = (struct cil_type *)d2; if (ebitmap_get_bit(a->types, t->value)) { rc = ebitmap_set_bit(matches, t->value, 1); } } else { // f1 != CIL_TYPEATTRIBUTE && f2 == CIL_TYPEATTRIBUTE struct cil_type *t = (struct cil_type *)d1; struct cil_typeattribute *a = (struct cil_typeattribute *)d2; if (ebitmap_get_bit(a->types, t->value)) { rc = ebitmap_set_bit(matches, t->value, 1); } } if (rc != SEPOL_OK) { ebitmap_destroy(matches); } } return rc; } /* s1 is the src type that is matched with a self * s2, and t2 are the source and type of the other rule * Assumes there is a match between s1 and s2 */ static int cil_self_match_any(struct cil_symtab_datum *s1, struct cil_symtab_datum *s2, struct cil_symtab_datum *t2) { int rc; if (FLAVOR(s1) != CIL_TYPEATTRIBUTE) { rc = cil_type_match_any(s1, t2); } else { struct cil_typeattribute *a = (struct cil_typeattribute *)s1; ebitmap_t map; rc = cil_type_matches(&map, s2, t2); if (rc < 0) { return rc; } if (ebitmap_is_empty(&map)) { return CIL_FALSE; } rc = ebitmap_match_any(&map, a->types); ebitmap_destroy(&map); } return rc; } /* s1 is the src type that is matched with a notself * s2 and t2 are the source and type of the other rule * Assumes there is a match between s1 and s2 */ static int cil_notself_match_any(struct cil_symtab_datum *s1, struct cil_symtab_datum *s2, struct cil_symtab_datum *t2) { int rc; ebitmap_node_t *snode, *tnode; unsigned int s,t; if (FLAVOR(s1) != CIL_TYPEATTRIBUTE) { struct cil_type *ts1 = (struct cil_type *)s1; if (FLAVOR(t2) != CIL_TYPEATTRIBUTE) { struct cil_type *tt2 = (struct cil_type *)t2; if (ts1->value != tt2->value) { return CIL_TRUE; } } else { struct cil_typeattribute *at2 = (struct cil_typeattribute *)t2; ebitmap_for_each_positive_bit(at2->types, tnode, t) { if (t != (unsigned int)ts1->value) { return CIL_TRUE; } } } } else { ebitmap_t smap; rc = cil_type_matches(&smap, s1, s2); if (rc < 0) { return rc; } if (ebitmap_is_empty(&smap)) { return CIL_FALSE; } if (FLAVOR(t2) != CIL_TYPEATTRIBUTE) { struct cil_type *tt2 = (struct cil_type *)t2; ebitmap_for_each_positive_bit(&smap, snode, s) { if (s != (unsigned int)tt2->value) { ebitmap_destroy(&smap); return CIL_TRUE; } } } else { struct cil_typeattribute *at2 = (struct cil_typeattribute *)t2; ebitmap_for_each_positive_bit(&smap, snode, s) { ebitmap_for_each_positive_bit(at2->types, tnode, t) { if (s != t) { ebitmap_destroy(&smap); return CIL_TRUE; } } } } ebitmap_destroy(&smap); } return CIL_FALSE; } /* s1 is the src type that is matched with an other * s2, and t2 are the source and type of the other rule * Assumes there is a match between s1 and s2 */ static int cil_other_match_any(struct cil_symtab_datum *s1, struct cil_symtab_datum *s2, struct cil_symtab_datum *t2) { int rc; ebitmap_t smap, tmap; ebitmap_node_t *snode, *tnode; unsigned int s,t; if (FLAVOR(s1) != CIL_TYPEATTRIBUTE) { return CIL_FALSE; } rc = cil_type_matches(&smap, s1, s2); if (rc < 0) { return rc; } if (ebitmap_is_empty(&smap)) { return CIL_FALSE; } rc = cil_type_matches(&tmap, s1, t2); if (rc < 0) { ebitmap_destroy(&smap); return rc; } if (ebitmap_is_empty(&tmap)) { ebitmap_destroy(&smap); return CIL_FALSE; } ebitmap_for_each_positive_bit(&smap, snode, s) { ebitmap_for_each_positive_bit(&tmap, tnode, t) { if (s != t) { rc = CIL_TRUE; goto exit; } } } rc = CIL_FALSE; exit: ebitmap_destroy(&smap); ebitmap_destroy(&tmap); return rc; } /* s2 is the src type that is matched with an other * Assumes there is a match between s1 and s2 * s1 is not needed, since it is known that there is a match */ static int cil_notself_other_match_any(struct cil_symtab_datum *s2) { if (FLAVOR(s2) == CIL_TYPEATTRIBUTE) { struct cil_typeattribute *as2 = (struct cil_typeattribute *)s2; if (ebitmap_cardinality(as2->types) > 1) { return CIL_TRUE; } } return CIL_FALSE; } static int cil_classperms_match_any(struct cil_classperms *cp1, struct cil_classperms *cp2) { struct cil_class *c1 = cp1->class; struct cil_class *c2 = cp2->class; struct cil_list_item *i1, *i2; if (&c1->datum != &c2->datum) return CIL_FALSE; cil_list_for_each(i1, cp1->perms) { struct cil_perm *p1 = i1->data; cil_list_for_each(i2, cp2->perms) { struct cil_perm *p2 = i2->data; if (&p1->datum == &p2->datum) return CIL_TRUE; } } return CIL_FALSE; } static int __cil_classperms_list_match_any(struct cil_classperms *cp1, struct cil_list *cpl2) { int rc; struct cil_list_item *curr; cil_list_for_each(curr, cpl2) { if (curr->flavor == CIL_CLASSPERMS) { struct cil_classperms *cp = curr->data; if (FLAVOR(cp->class) == CIL_CLASS) { rc = cil_classperms_match_any(cp1, cp); if (rc == CIL_TRUE) return CIL_TRUE; } else { /* MAP */ struct cil_list_item *i = NULL; cil_list_for_each(i, cp->perms) { struct cil_perm *cmp = i->data; rc = __cil_classperms_list_match_any(cp1, cmp->classperms); if (rc == CIL_TRUE) return CIL_TRUE; } } } else { /* SET */ struct cil_classperms_set *cp_set = curr->data; struct cil_classpermission *cp = cp_set->set; rc = __cil_classperms_list_match_any(cp1, cp->classperms); if (rc == CIL_TRUE) return CIL_TRUE; } } return CIL_FALSE; } static int cil_classperms_list_match_any(struct cil_list *cpl1, struct cil_list *cpl2) { int rc; struct cil_list_item *curr; cil_list_for_each(curr, cpl1) { if (curr->flavor == CIL_CLASSPERMS) { struct cil_classperms *cp = curr->data; if (FLAVOR(cp->class) == CIL_CLASS) { rc = __cil_classperms_list_match_any(cp, cpl2); if (rc == CIL_TRUE) return CIL_TRUE; } else { /* MAP */ struct cil_list_item *i = NULL; cil_list_for_each(i, cp->perms) { struct cil_perm *cmp = i->data; rc = cil_classperms_list_match_any(cmp->classperms, cpl2); if (rc == CIL_TRUE) return CIL_TRUE; } } } else { /* SET */ struct cil_classperms_set *cp_set = curr->data; struct cil_classpermission *cp = cp_set->set; rc = cil_classperms_list_match_any(cp->classperms, cpl2); if (rc == CIL_TRUE) return CIL_TRUE; } } return CIL_FALSE; } static void __add_classes_from_classperms_list(struct cil_list *classperms, struct cil_list *class_list) { struct cil_list_item *curr; cil_list_for_each(curr, classperms) { if (curr->flavor == CIL_CLASSPERMS) { struct cil_classperms *cp = curr->data; if (FLAVOR(cp->class) == CIL_CLASS) { cil_list_append(class_list, CIL_CLASS, cp->class); } else { /* MAP */ struct cil_list_item *i = NULL; cil_list_for_each(i, cp->perms) { struct cil_perm *cmp = i->data; __add_classes_from_classperms_list(cmp->classperms, class_list); } } } else { /* SET */ struct cil_classperms_set *cp_set = curr->data; struct cil_classpermission *cp = cp_set->set; __add_classes_from_classperms_list(cp->classperms, class_list); } } } static int __add_classes_from_map_perms(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, void *args) { struct cil_list *class_list = args; struct cil_perm *cmp = (struct cil_perm *)d; __add_classes_from_classperms_list(cmp->classperms, class_list); return SEPOL_OK; } struct cil_list *cil_expand_class(struct cil_class *class) { struct cil_list *class_list; cil_list_init(&class_list, CIL_CLASS); if (FLAVOR(class) == CIL_CLASS) { cil_list_append(class_list, CIL_CLASS, class); } else { /* MAP */ cil_symtab_map(&class->perms, __add_classes_from_map_perms, class_list); } return class_list; } static int cil_permissionx_match_any(struct cil_permissionx *px1, struct cil_permissionx *px2) { int rc = CIL_FALSE; struct cil_list *cl1 = NULL; struct cil_list *cl2 = NULL; if (px1->kind != px2->kind) goto exit; if (!ebitmap_match_any(px1->perms, px2->perms)) goto exit; cl1 = cil_expand_class(px1->obj); cl2 = cil_expand_class(px2->obj); if (!cil_list_match_any(cl1, cl2)) goto exit; rc = CIL_TRUE; exit: cil_list_destroy(&cl1, CIL_FALSE); cil_list_destroy(&cl2, CIL_FALSE); return rc; } static int cil_find_matching_avrule(struct cil_tree_node *node, struct cil_avrule *avrule, struct cil_avrule *target, struct cil_list *matching, int match_self) { int rc = SEPOL_OK; struct cil_symtab_datum *s1 = avrule->src; struct cil_symtab_datum *t1 = avrule->tgt; struct cil_symtab_datum *s2 = target->src; struct cil_symtab_datum *t2 = target->tgt; if (match_self != CIL_TRUE && avrule == target) goto exit; if (avrule->rule_kind != target->rule_kind) goto exit; if (avrule->is_extended != target->is_extended) goto exit; if (!cil_type_match_any(s1, s2)) goto exit; if (t1->fqn == CIL_KEY_SELF) { if (t2->fqn == CIL_KEY_SELF) { /* The earlier check whether s1 and s2 matches is all that is needed */ rc = CIL_TRUE; } else if (t2->fqn == CIL_KEY_NOTSELF || t2->fqn == CIL_KEY_OTHER) { rc = CIL_FALSE; } else { rc = cil_self_match_any(s1, s2, t2); } } else if (t1->fqn == CIL_KEY_NOTSELF) { if (t2->fqn == CIL_KEY_SELF) { rc = CIL_FALSE; } else if (t2->fqn == CIL_KEY_NOTSELF) { /* The earlier check whether s1 and s2 matches is all that is needed */ rc = CIL_TRUE; } else if (t2->fqn == CIL_KEY_OTHER) { rc = cil_notself_other_match_any(s2); } else { rc = cil_notself_match_any(s1, s2, t2); } } else if (t1->fqn == CIL_KEY_OTHER) { if (t2->fqn == CIL_KEY_SELF) { rc = CIL_FALSE; } else if (t2->fqn == CIL_KEY_NOTSELF) { rc = cil_notself_other_match_any(s1); } else if (t2->fqn == CIL_KEY_OTHER) { /* The earlier check whether s1 and s2 matches is all that is needed */ rc = CIL_TRUE; } else { rc = cil_other_match_any(s1, s2, t2); } } else { if (t2->fqn == CIL_KEY_SELF) { rc = cil_self_match_any(s2, s1, t1); } else if (t2->fqn == CIL_KEY_NOTSELF) { rc = cil_notself_match_any(s2, s1, t1); } else if (t2->fqn == CIL_KEY_OTHER) { rc = cil_other_match_any(s2, s1, t1); } else { rc = cil_type_match_any(t1, t2); } } if (rc < 0) { goto exit; } else if (rc == CIL_FALSE) { rc = SEPOL_OK; goto exit; } if (!target->is_extended) { if (cil_classperms_list_match_any(avrule->perms.classperms, target->perms.classperms)) { cil_list_append(matching, CIL_NODE, node); } } else { if (cil_permissionx_match_any(avrule->perms.x.permx, target->perms.x.permx)) { cil_list_append(matching, CIL_NODE, node); } } rc = SEPOL_OK; exit: return rc; } static int __cil_find_matching_avrule_in_ast(struct cil_tree_node *node, uint32_t *finished, void *extra_args) { int rc = SEPOL_OK; struct cil_args_find *args = extra_args; if (node->flavor == CIL_BLOCK) { struct cil_block *blk = node->data; if (blk->is_abstract == CIL_TRUE) { *finished = CIL_TREE_SKIP_HEAD; goto exit; } } else if (node->flavor == CIL_MACRO) { *finished = CIL_TREE_SKIP_HEAD; goto exit; } else if (node->flavor == CIL_AVRULE || node->flavor == CIL_AVRULEX) { if (node->flavor == args->flavor) { rc = cil_find_matching_avrule(node, node->data, args->target, args->matching, args->match_self); } } exit: return rc; } int cil_find_matching_avrule_in_ast(struct cil_tree_node *current, enum cil_flavor flavor, void *target, struct cil_list *matching, int match_self) { int rc; struct cil_args_find args; args.flavor = flavor; args.target = target; args.matching = matching; args.match_self = match_self; rc = cil_tree_walk(current, __cil_find_matching_avrule_in_ast, NULL, NULL, &args); if (rc) { cil_log(CIL_ERR, "An error occurred while searching for avrule in AST\n"); } return rc; } libsepol-3.8.1/cil/src/cil_find.h000066400000000000000000000036161476211737200166320ustar00rootroot00000000000000/* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #include "cil_flavor.h" #include "cil_tree.h" #include "cil_list.h" #ifndef CIL_FIND_H_ #define CIL_FIND_H_ int cil_find_matching_avrule_in_ast(struct cil_tree_node *current, enum cil_flavor flavor, void *target, struct cil_list *matching, int match_self); struct cil_list *cil_expand_class(struct cil_class *class); #endif libsepol-3.8.1/cil/src/cil_flavor.h000066400000000000000000000104771476211737200172060ustar00rootroot00000000000000/* * Copyright 2013 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #ifndef CIL_FLAVOR_H_ #define CIL_FLAVOR_H_ /* Tree/list node types */ #define CIL_MIN_OP_OPERANDS 1000 #define CIL_MIN_DECLARATIVE 2000 enum cil_flavor { CIL_NONE = 0, CIL_ROOT, CIL_NODE, CIL_STRING, CIL_DATUM, CIL_LIST, CIL_LIST_ITEM, CIL_PARAM, CIL_ARGS, CIL_BLOCKINHERIT, CIL_BLOCKABSTRACT, CIL_IN, CIL_CALL, CIL_BOOLEANIF, CIL_TUNABLEIF, CIL_CONDBLOCK, CIL_CONDTRUE, CIL_CONDFALSE, CIL_CLASSORDER, CIL_CLASSCOMMON, CIL_CLASSMAPPING, CIL_CLASSPERMS, CIL_CLASSPERMS_SET, CIL_CLASSPERMISSIONSET, CIL_USERPREFIX, CIL_USERROLE, CIL_USERATTRIBUTESET, CIL_USERLEVEL, CIL_USERRANGE, CIL_USERBOUNDS, CIL_SELINUXUSER, CIL_SELINUXUSERDEFAULT, CIL_ROLEATTRIBUTESET, CIL_ROLETYPE, CIL_ROLEBOUNDS, CIL_TYPEATTRIBUTESET, CIL_EXPANDTYPEATTRIBUTE, CIL_TYPEALIASACTUAL, CIL_TYPEBOUNDS, CIL_TYPEPERMISSIVE, CIL_SENSALIASACTUAL, CIL_SENSITIVITYORDER, CIL_SENSCAT, CIL_CATALIASACTUAL, CIL_CATORDER, CIL_SIDORDER, CIL_ROLEALLOW, CIL_AVRULE, CIL_AVRULEX, CIL_DENY_RULE, CIL_ROLETRANSITION, CIL_TYPE_RULE, CIL_NAMETYPETRANSITION, CIL_RANGETRANSITION, CIL_CONSTRAIN, CIL_MLSCONSTRAIN, CIL_VALIDATETRANS, CIL_MLSVALIDATETRANS, CIL_SIDCONTEXT, CIL_FSUSE, CIL_FILECON, CIL_PORTCON, CIL_NODECON, CIL_GENFSCON, CIL_NETIFCON, CIL_PIRQCON, CIL_IOMEMCON, CIL_IOPORTCON, CIL_PCIDEVICECON, CIL_DEVICETREECON, CIL_DEFAULTUSER, CIL_DEFAULTROLE, CIL_DEFAULTTYPE, CIL_DEFAULTRANGE, CIL_HANDLEUNKNOWN, CIL_MLS, CIL_SRC_INFO, CIL_IBPKEYCON, CIL_IBENDPORTCON, /* * boolean constraint set catset * dom X * domby X * incomp X * eq X X * ne X X * and X X X X * not X X X X * or X X X X * xor X X X * all X X * range X */ CIL_OP = CIL_MIN_OP_OPERANDS, CIL_ALL, CIL_AND, CIL_OR, CIL_XOR, CIL_NOT, CIL_EQ, CIL_NEQ, CIL_RANGE, CIL_CONS_DOM, CIL_CONS_DOMBY, CIL_CONS_INCOMP, CIL_CONS_OPERAND, CIL_CONS_U1, CIL_CONS_U2, CIL_CONS_U3, CIL_CONS_T1, CIL_CONS_T2, CIL_CONS_T3, CIL_CONS_R1, CIL_CONS_R2, CIL_CONS_R3, CIL_CONS_L1, CIL_CONS_L2, CIL_CONS_H1, CIL_CONS_H2, CIL_BLOCK = CIL_MIN_DECLARATIVE, CIL_MACRO, CIL_OPTIONAL, CIL_BOOL, CIL_TUNABLE, CIL_PERM, CIL_MAP_PERM, CIL_COMMON, CIL_CLASS, CIL_MAP_CLASS, CIL_CLASSPERMISSION, CIL_USER, CIL_USERATTRIBUTE, CIL_ROLE, CIL_ROLEATTRIBUTE, CIL_TYPE, CIL_TYPEATTRIBUTE, CIL_TYPEALIAS, CIL_SENS, CIL_SENSALIAS, CIL_CAT, CIL_CATSET, CIL_CATALIAS, CIL_LEVEL, CIL_LEVELRANGE, CIL_SID, CIL_DECLARED_STRING, CIL_CONTEXT, CIL_IPADDR, CIL_POLICYCAP, CIL_PERMISSIONX }; #endif /* CIL_FLAVOR_H_ */ libsepol-3.8.1/cil/src/cil_fqn.c000066400000000000000000000104441476211737200164660ustar00rootroot00000000000000/* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #include #include #include #include "cil_fqn.h" #include "cil_internal.h" #include "cil_log.h" #include "cil_strpool.h" #include "cil_symtab.h" struct cil_fqn_args { char prefix[CIL_MAX_NAME_LENGTH]; int len; struct cil_tree_node *node; }; static int __cil_fqn_qualify_decls(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, void *args) { struct cil_fqn_args *fqn_args = args; struct cil_symtab_datum *datum = (struct cil_symtab_datum *)d; int newlen; char prefix[CIL_MAX_NAME_LENGTH]; int rc = SEPOL_OK; if (fqn_args->len == 0) { goto exit; } newlen = fqn_args->len + strlen(datum->name); if (newlen >= CIL_MAX_NAME_LENGTH) { cil_log(CIL_INFO, "Fully qualified name for %s is too long\n", datum->name); rc = SEPOL_ERR; goto exit; } strcpy(prefix, fqn_args->prefix); strcat(prefix, datum->name); datum->fqn = cil_strpool_add(prefix); exit: return rc; } static int __cil_fqn_qualify_blocks(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, void *args) { struct cil_fqn_args *fqn_args = args; struct cil_fqn_args child_args; struct cil_block *block = (struct cil_block *)d; struct cil_symtab_datum *datum = (struct cil_symtab_datum *)block; struct cil_tree_node *node = NODE(datum); int i; int rc = SEPOL_OK; int newlen; if (node->flavor != CIL_BLOCK) { goto exit; } newlen = fqn_args->len + strlen(datum->name) + 1; if (newlen >= CIL_MAX_NAME_LENGTH) { cil_log(CIL_INFO, "Fully qualified name for block %s is too long\n", datum->name); rc = SEPOL_ERR; goto exit; } child_args.node = node; child_args.len = newlen; strcpy(child_args.prefix, fqn_args->prefix); strcat(child_args.prefix, datum->name); strcat(child_args.prefix, "."); for (i=1; isymtab[i]), __cil_fqn_qualify_decls, &child_args); if (rc != SEPOL_OK) { goto exit; } break; } } rc = cil_symtab_map(&(block->symtab[CIL_SYM_BLOCKS]), __cil_fqn_qualify_blocks, &child_args); exit: if (rc != SEPOL_OK) { cil_tree_log(node, CIL_ERR,"Problem qualifying names in block"); } return rc; } int cil_fqn_qualify(struct cil_tree_node *root_node) { struct cil_root *root = root_node->data; struct cil_fqn_args fqn_args; fqn_args.prefix[0] = '\0'; fqn_args.len = 0; fqn_args.node = root_node; return cil_symtab_map(&(root->symtab[CIL_SYM_BLOCKS]), __cil_fqn_qualify_blocks, &fqn_args); } libsepol-3.8.1/cil/src/cil_fqn.h000066400000000000000000000033631476211737200164750ustar00rootroot00000000000000/* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #ifndef CIL_FQN_H_ #define CIL_FQN_H_ #include "cil_internal.h" #include "cil_tree.h" int cil_fqn_qualify(struct cil_tree_node *root_node); #endif /* CIL_FQN_H_ */ libsepol-3.8.1/cil/src/cil_internal.h000066400000000000000000000671721476211737200175350ustar00rootroot00000000000000/* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #ifndef CIL_INTERNAL_H_ #define CIL_INTERNAL_H_ #include #include #include #include #include #include #include #include #include "cil_flavor.h" #include "cil_tree.h" #include "cil_symtab.h" #include "cil_mem.h" #define CIL_MAX_NAME_LENGTH 2048 #define CIL_DEGENERATE_INHERITANCE_DEPTH 10UL #define CIL_DEGENERATE_INHERITANCE_MINIMUM (0x01 << CIL_DEGENERATE_INHERITANCE_DEPTH) #define CIL_DEGENERATE_INHERITANCE_GROWTH 10UL enum cil_pass { CIL_PASS_INIT = 0, CIL_PASS_TIF, CIL_PASS_IN_BEFORE, CIL_PASS_BLKIN_LINK, CIL_PASS_BLKIN_COPY, CIL_PASS_BLKABS, CIL_PASS_IN_AFTER, 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 */ extern char *CIL_KEY_CONS_T1; extern char *CIL_KEY_CONS_T2; extern char *CIL_KEY_CONS_T3; extern char *CIL_KEY_CONS_R1; extern char *CIL_KEY_CONS_R2; extern char *CIL_KEY_CONS_R3; extern char *CIL_KEY_CONS_U1; extern char *CIL_KEY_CONS_U2; extern char *CIL_KEY_CONS_U3; extern char *CIL_KEY_CONS_L1; extern char *CIL_KEY_CONS_L2; extern char *CIL_KEY_CONS_H1; extern char *CIL_KEY_CONS_H2; extern char *CIL_KEY_AND; extern char *CIL_KEY_OR; extern char *CIL_KEY_NOT; extern char *CIL_KEY_EQ; extern char *CIL_KEY_NEQ; extern char *CIL_KEY_CONS_DOM; extern char *CIL_KEY_CONS_DOMBY; extern char *CIL_KEY_CONS_INCOMP; extern char *CIL_KEY_CONDTRUE; extern char *CIL_KEY_CONDFALSE; extern char *CIL_KEY_SELF; extern char *CIL_KEY_NOTSELF; extern char *CIL_KEY_OTHER; extern char *CIL_KEY_OBJECT_R; extern char *CIL_KEY_STAR; extern char *CIL_KEY_TCP; extern char *CIL_KEY_UDP; extern char *CIL_KEY_DCCP; extern char *CIL_KEY_SCTP; extern char *CIL_KEY_AUDITALLOW; extern char *CIL_KEY_TUNABLEIF; extern char *CIL_KEY_ALLOW; extern char *CIL_KEY_DONTAUDIT; extern char *CIL_KEY_TYPETRANSITION; extern char *CIL_KEY_TYPECHANGE; extern char *CIL_KEY_CALL; extern char *CIL_KEY_TUNABLE; extern char *CIL_KEY_XOR; extern char *CIL_KEY_ALL; extern char *CIL_KEY_RANGE; extern char *CIL_KEY_GLOB; extern char *CIL_KEY_FILE; extern char *CIL_KEY_DIR; extern char *CIL_KEY_CHAR; extern char *CIL_KEY_BLOCK; extern char *CIL_KEY_SOCKET; extern char *CIL_KEY_PIPE; extern char *CIL_KEY_SYMLINK; extern char *CIL_KEY_ANY; extern char *CIL_KEY_XATTR; extern char *CIL_KEY_TASK; extern char *CIL_KEY_TRANS; extern char *CIL_KEY_TYPE; extern char *CIL_KEY_ROLE; extern char *CIL_KEY_USER; extern char *CIL_KEY_USERATTRIBUTE; extern char *CIL_KEY_USERATTRIBUTESET; extern char *CIL_KEY_SENSITIVITY; extern char *CIL_KEY_CATEGORY; extern char *CIL_KEY_CATSET; extern char *CIL_KEY_LEVEL; extern char *CIL_KEY_LEVELRANGE; extern char *CIL_KEY_CLASS; extern char *CIL_KEY_IPADDR; extern char *CIL_KEY_MAP_CLASS; extern char *CIL_KEY_CLASSPERMISSION; extern char *CIL_KEY_BOOL; extern char *CIL_KEY_STRING; extern char *CIL_KEY_NAME; extern char *CIL_KEY_SOURCE; extern char *CIL_KEY_TARGET; extern char *CIL_KEY_LOW; extern char *CIL_KEY_HIGH; extern char *CIL_KEY_LOW_HIGH; extern char *CIL_KEY_GLBLUB; extern char *CIL_KEY_HANDLEUNKNOWN; extern char *CIL_KEY_HANDLEUNKNOWN_ALLOW; extern char *CIL_KEY_HANDLEUNKNOWN_DENY; extern char *CIL_KEY_HANDLEUNKNOWN_REJECT; extern char *CIL_KEY_MACRO; extern char *CIL_KEY_IN; extern char *CIL_KEY_IN_BEFORE; extern char *CIL_KEY_IN_AFTER; extern char *CIL_KEY_MLS; extern char *CIL_KEY_DEFAULTRANGE; extern char *CIL_KEY_BLOCKINHERIT; extern char *CIL_KEY_BLOCKABSTRACT; extern char *CIL_KEY_CLASSORDER; extern char *CIL_KEY_CLASSMAPPING; extern char *CIL_KEY_CLASSPERMISSIONSET; extern char *CIL_KEY_COMMON; extern char *CIL_KEY_CLASSCOMMON; extern char *CIL_KEY_SID; extern char *CIL_KEY_SIDCONTEXT; extern char *CIL_KEY_SIDORDER; extern char *CIL_KEY_USERLEVEL; extern char *CIL_KEY_USERRANGE; extern char *CIL_KEY_USERBOUNDS; extern char *CIL_KEY_USERPREFIX; extern char *CIL_KEY_SELINUXUSER; extern char *CIL_KEY_SELINUXUSERDEFAULT; extern char *CIL_KEY_TYPEATTRIBUTE; extern char *CIL_KEY_TYPEATTRIBUTESET; extern char *CIL_KEY_EXPANDTYPEATTRIBUTE; extern char *CIL_KEY_TYPEALIAS; extern char *CIL_KEY_TYPEALIASACTUAL; extern char *CIL_KEY_TYPEBOUNDS; extern char *CIL_KEY_TYPEPERMISSIVE; extern char *CIL_KEY_RANGETRANSITION; extern char *CIL_KEY_USERROLE; extern char *CIL_KEY_ROLETYPE; extern char *CIL_KEY_ROLETRANSITION; extern char *CIL_KEY_ROLEALLOW; extern char *CIL_KEY_ROLEATTRIBUTE; extern char *CIL_KEY_ROLEATTRIBUTESET; extern char *CIL_KEY_ROLEBOUNDS; extern char *CIL_KEY_BOOLEANIF; extern char *CIL_KEY_NEVERALLOW; extern char *CIL_KEY_TYPEMEMBER; extern char *CIL_KEY_SENSALIAS; extern char *CIL_KEY_SENSALIASACTUAL; extern char *CIL_KEY_CATALIAS; extern char *CIL_KEY_CATALIASACTUAL; extern char *CIL_KEY_CATORDER; extern char *CIL_KEY_SENSITIVITYORDER; extern char *CIL_KEY_SENSCAT; extern char *CIL_KEY_CONSTRAIN; extern char *CIL_KEY_MLSCONSTRAIN; extern char *CIL_KEY_VALIDATETRANS; extern char *CIL_KEY_MLSVALIDATETRANS; extern char *CIL_KEY_CONTEXT; extern char *CIL_KEY_FILECON; extern char *CIL_KEY_IBPKEYCON; extern char *CIL_KEY_IBENDPORTCON; extern char *CIL_KEY_PORTCON; extern char *CIL_KEY_NODECON; extern char *CIL_KEY_GENFSCON; extern char *CIL_KEY_NETIFCON; extern char *CIL_KEY_PIRQCON; extern char *CIL_KEY_IOMEMCON; extern char *CIL_KEY_IOPORTCON; extern char *CIL_KEY_PCIDEVICECON; extern char *CIL_KEY_DEVICETREECON; extern char *CIL_KEY_FSUSE; extern char *CIL_KEY_POLICYCAP; extern char *CIL_KEY_OPTIONAL; extern char *CIL_KEY_DEFAULTUSER; extern char *CIL_KEY_DEFAULTROLE; extern char *CIL_KEY_DEFAULTTYPE; extern char *CIL_KEY_ROOT; extern char *CIL_KEY_NODE; extern char *CIL_KEY_PERM; extern char *CIL_KEY_ALLOWX; extern char *CIL_KEY_AUDITALLOWX; extern char *CIL_KEY_DONTAUDITX; extern char *CIL_KEY_NEVERALLOWX; extern char *CIL_KEY_PERMISSIONX; extern char *CIL_KEY_IOCTL; extern char *CIL_KEY_NLMSG; extern char *CIL_KEY_UNORDERED; extern char *CIL_KEY_SRC_INFO; extern char *CIL_KEY_SRC_CIL; extern char *CIL_KEY_SRC_HLL_LMS; extern char *CIL_KEY_SRC_HLL_LMX; extern char *CIL_KEY_SRC_HLL_LME; extern char *CIL_KEY_DENY_RULE; /* 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_STRINGS, CIL_SYM_PERMX, CIL_SYM_NUM, CIL_SYM_UNKNOWN, CIL_SYM_PERMS // Special case for permissions. This symtab is not included in arrays }; enum cil_sym_array { CIL_SYM_ARRAY_ROOT = 0, CIL_SYM_ARRAY_BLOCK, CIL_SYM_ARRAY_IN, CIL_SYM_ARRAY_MACRO, CIL_SYM_ARRAY_CONDBLOCK, CIL_SYM_ARRAY_NUM }; extern const int cil_sym_sizes[CIL_SYM_ARRAY_NUM][CIL_SYM_NUM]; #define CIL_CLASS_SYM_SIZE 256 #define CIL_PERMS_PER_CLASS (sizeof(sepol_access_vector_t) * 8) struct cil_db { struct cil_tree *parse; struct cil_tree *ast; struct cil_type *selftype; struct cil_type *notselftype; struct cil_type *othertype; struct cil_list *sidorder; struct cil_list *classorder; struct cil_list *catorder; struct cil_list *sensitivityorder; struct cil_sort *netifcon; struct cil_sort *genfscon; struct cil_sort *filecon; struct cil_sort *nodecon; struct cil_sort *ibpkeycon; struct cil_sort *ibendportcon; struct cil_sort *portcon; struct cil_sort *pirqcon; struct cil_sort *iomemcon; struct cil_sort *ioportcon; struct cil_sort *pcidevicecon; struct cil_sort *devicetreecon; struct cil_sort *fsuse; struct cil_list *userprefixes; struct cil_list *selinuxusers; struct cil_list *declared_strings; int num_types_and_attrs; int num_classes; int num_cats; int num_types; int num_roles; int num_users; struct cil_type **val_to_type; struct cil_role **val_to_role; struct cil_user **val_to_user; int disable_dontaudit; int disable_neverallow; int attrs_expand_generated; unsigned attrs_expand_size; int preserve_tunables; int handle_unknown; int mls; int multiple_decls; int qualified_names; int target_platform; int policy_version; }; struct cil_root { symtab_t symtab[CIL_SYM_NUM]; }; struct cil_sort { enum cil_flavor flavor; uint32_t count; uint32_t index; void **array; }; struct cil_ordered { int merged; struct cil_list *strs; struct cil_list *datums; }; struct cil_block { struct cil_symtab_datum datum; symtab_t symtab[CIL_SYM_NUM]; uint16_t is_abstract; struct cil_list *bi_nodes; }; struct cil_blockinherit { char *block_str; struct cil_block *block; }; struct cil_blockabstract { char *block_str; struct cil_block *block; }; struct cil_in { symtab_t symtab[CIL_SYM_NUM]; int is_after; char *block_str; struct cil_block *block; }; 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_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_classpermission *set; struct cil_list *classperms; }; struct cil_classmapping { char *map_class_str; struct cil_class *map_class; char *map_perm_str; struct cil_perm *map_perm; struct cil_list *classperms; }; struct cil_classcommon { char *class_str; struct cil_class *class; char *common_str; struct cil_class *common; }; struct cil_alias { struct cil_symtab_datum datum; void *actual; }; struct cil_aliasactual { char *alias_str; void *alias; char *actual_str; void *actual; }; struct cil_sid { struct cil_symtab_datum datum; struct cil_context *context; uint32_t ordered; }; struct cil_sidcontext { char *sid_str; struct cil_sid *sid; char *context_str; struct cil_context *context; }; struct cil_user { struct cil_symtab_datum datum; struct cil_user *bounds; ebitmap_t *roles; struct cil_level *dftlevel; struct cil_levelrange *range; int value; }; struct cil_userattribute { struct cil_symtab_datum datum; struct cil_list *expr_list; ebitmap_t *users; }; struct cil_userattributeset { char *attr_str; struct cil_userattribute *attr; struct cil_list *str_expr; struct cil_list *datum_expr; }; struct cil_userrole { char *user_str; void *user; char *role_str; void *role; }; struct cil_userlevel { char *user_str; void *user; char *level_str; struct cil_level *level; }; struct cil_userrange { char *user_str; void *user; 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_roleattribute *attr; struct cil_list *str_expr; struct cil_list *datum_expr; }; struct cil_roletype { char *role_str; void *role; /* role or attribute */ char *type_str; void *type; /* type, alias, or attribute */ }; struct cil_type { struct cil_symtab_datum datum; struct cil_type *bounds; int value; }; #define CIL_ATTR_AVRULE (1 << 0) #define CIL_ATTR_NEVERALLOW (1 << 1) #define CIL_ATTR_CONSTRAINT (1 << 2) #define CIL_ATTR_EXPAND_TRUE (1 << 3) #define CIL_ATTR_EXPAND_FALSE (1 << 4) struct cil_typeattribute { struct cil_symtab_datum datum; struct cil_list *expr_list; ebitmap_t *types; int used; // whether or not this attribute was used in a binary policy rule int keep; }; struct cil_typeattributeset { char *attr_str; struct cil_typeattribute *attr; struct cil_list *str_expr; struct cil_list *datum_expr; }; struct cil_expandtypeattribute { struct cil_list *attr_strs; struct cil_list *attr_datums; int expand; }; struct cil_typepermissive { char *type_str; void *type; /* type or alias */ }; struct cil_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_symtab_datum *name; char *result_str; void *result; /* type or alias */ }; struct cil_rangetransition { char *src_str; void *src; /* type, alias, or attribute */ char *exec_str; void *exec; /* type, alias, or attribute */ char *obj_str; struct cil_class *obj; char *range_str; struct cil_levelrange *range; }; struct cil_bool { struct cil_symtab_datum datum; uint16_t value; }; struct cil_tunable { struct cil_symtab_datum datum; uint16_t value; }; #define CIL_AVRULE_ALLOWED 1 #define CIL_AVRULE_AUDITALLOW 2 #define CIL_AVRULE_DONTAUDIT 8 #define CIL_AVRULE_NEVERALLOW 128 #define CIL_AVRULE_AV (AVRULE_ALLOWED | AVRULE_AUDITALLOW | AVRULE_DONTAUDIT | AVRULE_NEVERALLOW) struct cil_avrule { int is_extended; uint32_t rule_kind; char *src_str; void *src; /* type, alias, or attribute */ char *tgt_str; void *tgt; /* type, alias, or attribute */ union { struct cil_list *classperms; struct { char *permx_str; struct cil_permissionx *permx; } x; } perms; }; #define CIL_PERMX_KIND_IOCTL 1 #define CIL_PERMX_KIND_NLMSG 2 struct cil_permissionx { struct cil_symtab_datum datum; uint32_t kind; char *obj_str; struct cil_class *obj; struct cil_list *expr_str; ebitmap_t *perms; }; struct cil_deny_rule { 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_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_senscat { char *sens_str; struct cil_sens *sens; 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_ANY = 0, CIL_FILECON_FILE, CIL_FILECON_DIR, CIL_FILECON_CHAR, CIL_FILECON_BLOCK, CIL_FILECON_SOCKET, CIL_FILECON_PIPE, CIL_FILECON_SYMLINK, }; struct cil_filecon { char *path_str; struct cil_symtab_datum *path; enum cil_filecon_types type; char *context_str; struct cil_context *context; }; enum cil_protocol { CIL_PROTOCOL_UDP = 1, CIL_PROTOCOL_TCP, CIL_PROTOCOL_DCCP, CIL_PROTOCOL_SCTP }; struct cil_ibpkeycon { char *subnet_prefix_str; uint32_t pkey_low; uint32_t pkey_high; char *context_str; struct cil_context *context; }; struct cil_portcon { enum cil_protocol proto; uint32_t port_low; uint32_t port_high; char *context_str; struct cil_context *context; }; struct cil_nodecon { char *addr_str; struct cil_ipaddr *addr; char *mask_str; struct cil_ipaddr *mask; char *context_str; struct cil_context *context; }; struct cil_ipaddr { struct cil_symtab_datum datum; int family; union { struct in_addr v4; struct in6_addr v6; } ip; }; struct cil_genfscon { char *fs_str; char *path_str; enum cil_filecon_types file_type; char *context_str; struct cil_context *context; }; struct cil_netifcon { char *interface_str; char *if_context_str; struct cil_context *if_context; char *packet_context_str; struct cil_context *packet_context; char *context_str; }; struct cil_ibendportcon { char *dev_name_str; uint32_t port; char *context_str; struct cil_context *context; }; struct cil_pirqcon { uint32_t pirq; char *context_str; struct cil_context *context; }; struct cil_iomemcon { uint64_t iomem_low; uint64_t iomem_high; char *context_str; struct cil_context *context; }; struct cil_ioportcon { uint32_t ioport_low; uint32_t ioport_high; char *context_str; struct cil_context *context; }; struct cil_pcidevicecon { uint32_t dev; char *context_str; struct cil_context *context; }; struct cil_devicetreecon { char *path; char *context_str; struct cil_context *context; }; /* Ensure that CIL uses the same values as sepol services.h */ enum cil_fsuse_types { CIL_FSUSE_XATTR = SECURITY_FS_USE_XATTR, CIL_FSUSE_TASK = SECURITY_FS_USE_TASK, CIL_FSUSE_TRANS = SECURITY_FS_USE_TRANS }; struct cil_fsuse { enum cil_fsuse_types type; char *fs_str; char *context_str; struct cil_context *context; }; #define CIL_MLS_LEVELS "l1 l2 h1 h2" #define CIL_CONSTRAIN_KEYS "t1 t2 r1 r2 u1 u2" #define CIL_MLSCONSTRAIN_KEYS CIL_MLS_LEVELS CIL_CONSTRAIN_KEYS #define CIL_CONSTRAIN_OPER "== != eq dom domby incomp not and or" struct cil_constrain { struct cil_list *classperms; struct cil_list *str_expr; struct cil_list *datum_expr; }; struct cil_validatetrans { char *class_str; struct cil_class *class; struct cil_list *str_expr; struct cil_list *datum_expr; }; struct cil_param { char *str; enum cil_flavor flavor; }; struct cil_macro { struct cil_symtab_datum datum; symtab_t symtab[CIL_SYM_NUM]; struct cil_list *params; }; struct cil_args { char *arg_str; struct cil_symtab_datum *arg; char *param_str; enum cil_flavor flavor; }; struct cil_call { char *macro_str; struct cil_macro *macro; struct cil_tree *args_tree; struct cil_list *args; int copied; }; #define CIL_TRUE 1 #define CIL_FALSE 0 struct cil_condblock { enum cil_flavor flavor; symtab_t symtab[CIL_SYM_NUM]; }; struct cil_booleanif { struct cil_list *str_expr; struct cil_list *datum_expr; int preserved_tunable; }; struct cil_tunableif { struct cil_list *str_expr; struct cil_list *datum_expr; }; struct cil_policycap { struct cil_symtab_datum datum; }; struct cil_bounds { char *parent_str; void *parent; char *child_str; void *child; }; /* 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, CIL_DEFAULT_GLBLUB = DEFAULT_GLBLUB, }; /* Default labeling behavior for range */ struct cil_defaultrange { struct cil_list *class_strs; struct cil_list *class_datums; enum cil_default_object_range object_range; }; struct cil_handleunknown { int handle_unknown; }; struct cil_mls { int value; }; struct cil_src_info { char *kind; uint32_t hll_line; char *path; }; void cil_db_init(struct cil_db **db); void cil_db_destroy(struct cil_db **db); void cil_root_init(struct cil_root **root); void cil_root_destroy(struct cil_root *root); void cil_destroy_data(void **data, enum cil_flavor flavor); int cil_flavor_to_symtab_index(enum cil_flavor flavor, enum cil_sym_index *index); const char * cil_node_to_string(struct cil_tree_node *node); int cil_userprefixes_to_string(struct cil_db *db, char **out, size_t *size); int cil_selinuxusers_to_string(struct cil_db *db, char **out, size_t *size); int cil_filecons_to_string(struct cil_db *db, char **out, size_t *size); void cil_symtab_array_init(symtab_t symtab[], const 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); int cil_string_to_uint32(const char *string, uint32_t *value, int base); int cil_string_to_uint64(const char *string, uint64_t *value, int base); void cil_sort_init(struct cil_sort **sort); void cil_sort_destroy(struct cil_sort **sort); void cil_ordered_init(struct cil_ordered **ordered); void cil_netifcon_init(struct cil_netifcon **netifcon); void cil_ibendportcon_init(struct cil_ibendportcon **ibendportcon); void cil_context_init(struct cil_context **context); void cil_level_init(struct cil_level **level); void cil_levelrange_init(struct cil_levelrange **lvlrange); void cil_sens_init(struct cil_sens **sens); void cil_block_init(struct cil_block **block); void cil_blockinherit_init(struct cil_blockinherit **inherit); void cil_blockabstract_init(struct cil_blockabstract **abstract); void cil_in_init(struct cil_in **in); void cil_class_init(struct cil_class **class); void cil_classcommon_init(struct cil_classcommon **classcommon); void cil_sid_init(struct cil_sid **sid); void cil_sidcontext_init(struct cil_sidcontext **sidcontext); void cil_userrole_init(struct cil_userrole **userrole); void cil_userprefix_init(struct cil_userprefix **userprefix); void cil_selinuxuser_init(struct cil_selinuxuser **selinuxuser); void cil_roleattribute_init(struct cil_roleattribute **attribute); void cil_roleattributeset_init(struct cil_roleattributeset **attrset); void cil_roletype_init(struct cil_roletype **roletype); void cil_typeattribute_init(struct cil_typeattribute **attribute); void cil_typeattributeset_init(struct cil_typeattributeset **attrset); void cil_expandtypeattribute_init(struct cil_expandtypeattribute **expandattr); void cil_alias_init(struct cil_alias **alias); void cil_aliasactual_init(struct cil_aliasactual **aliasactual); void cil_typepermissive_init(struct cil_typepermissive **typeperm); void cil_nametypetransition_init(struct cil_nametypetransition **nametypetrans); void cil_rangetransition_init(struct cil_rangetransition **rangetrans); void cil_bool_init(struct cil_bool **cilbool); void cil_boolif_init(struct cil_booleanif **bif); void cil_condblock_init(struct cil_condblock **cb); void cil_tunable_init(struct cil_tunable **ciltun); void cil_tunif_init(struct cil_tunableif **tif); void cil_avrule_init(struct cil_avrule **avrule); void cil_permissionx_init(struct cil_permissionx **permx); void cil_deny_rule_init(struct cil_deny_rule **rule); void cil_type_rule_init(struct cil_type_rule **type_rule); void cil_roletransition_init(struct cil_roletransition **roletrans); void cil_roleallow_init(struct cil_roleallow **role_allow); void cil_catset_init(struct cil_catset **catset); void cil_cats_init(struct cil_cats **cats); void cil_senscat_init(struct cil_senscat **senscat); void cil_filecon_init(struct cil_filecon **filecon); void cil_ibpkeycon_init(struct cil_ibpkeycon **ibpkeycon); void cil_portcon_init(struct cil_portcon **portcon); void cil_nodecon_init(struct cil_nodecon **nodecon); void cil_genfscon_init(struct cil_genfscon **genfscon); void cil_pirqcon_init(struct cil_pirqcon **pirqcon); void cil_iomemcon_init(struct cil_iomemcon **iomemcon); void cil_ioportcon_init(struct cil_ioportcon **ioportcon); void cil_pcidevicecon_init(struct cil_pcidevicecon **pcidevicecon); void cil_devicetreecon_init(struct cil_devicetreecon **devicetreecon); void cil_fsuse_init(struct cil_fsuse **fsuse); void cil_constrain_init(struct cil_constrain **constrain); void cil_validatetrans_init(struct cil_validatetrans **validtrans); void cil_ipaddr_init(struct cil_ipaddr **ipaddr); void cil_perm_init(struct cil_perm **perm); void cil_classpermission_init(struct cil_classpermission **cp); void cil_classpermissionset_init(struct cil_classpermissionset **cps); void cil_classperms_set_init(struct cil_classperms_set **cp_set); void cil_classperms_init(struct cil_classperms **cp); void cil_classmapping_init(struct cil_classmapping **mapping); void cil_user_init(struct cil_user **user); void cil_userlevel_init(struct cil_userlevel **usrlvl); void cil_userrange_init(struct cil_userrange **userrange); void cil_role_init(struct cil_role **role); void cil_type_init(struct cil_type **type); void cil_cat_init(struct cil_cat **cat); void cil_args_init(struct cil_args **args); void cil_call_init(struct cil_call **call); void cil_optional_init(struct cil_optional **optional); void cil_param_init(struct cil_param **param); void cil_macro_init(struct cil_macro **macro); void cil_policycap_init(struct cil_policycap **policycap); void cil_bounds_init(struct cil_bounds **bounds); void cil_default_init(struct cil_default **def); void cil_defaultrange_init(struct cil_defaultrange **def); void cil_handleunknown_init(struct cil_handleunknown **unk); void cil_mls_init(struct cil_mls **mls); void cil_src_info_init(struct cil_src_info **info); void cil_userattribute_init(struct cil_userattribute **attribute); void cil_userattributeset_init(struct cil_userattributeset **attrset); #endif libsepol-3.8.1/cil/src/cil_lexer.h000066400000000000000000000040111476211737200170170ustar00rootroot00000000000000/* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #ifndef CIL_LEXER_H_ #define CIL_LEXER_H_ #include #define OPAREN 1 #define CPAREN 2 #define SYMBOL 3 #define QSTRING 4 #define COMMENT 5 #define HLL_LINEMARK 6 #define NEWLINE 7 #define END_OF_FILE 8 #define UNKNOWN 9 struct token { uint32_t type; char * value; uint32_t line; }; int cil_lexer_setup(char *buffer, uint32_t size); void cil_lexer_destroy(void); int cil_lexer_next(struct token *tok); #endif /* CIL_LEXER_H_ */ libsepol-3.8.1/cil/src/cil_lexer.l000066400000000000000000000054421476211737200170340ustar00rootroot00000000000000/* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ %{ #include #include #include "cil_internal.h" #include "cil_lexer.h" #include "cil_log.h" #include "cil_mem.h" char *value = NULL; int line = 1; %} %option nounput %option noinput %option noyywrap %option prefix="cil_yy" digit [0-9] alpha [a-zA-Z] spec_char [\[\]\.\@\=\/\*\-\_\$\%\+\-\!\|\&\^\:\~\`\#\{\}\'\<\>\?\,] symbol ({digit}|{alpha}|{spec_char})+ white [ \t] newline [\n\r] qstring \"[^"\n\0]*\" hll_lm ^;;\* comment ; %% {newline} line++; return NEWLINE; {hll_lm} value=yytext; return HLL_LINEMARK; {comment} value=yytext; return COMMENT; "(" value=yytext; return OPAREN; ")" value=yytext; return CPAREN; {symbol} value=yytext; return SYMBOL; {white} ; {qstring} value=yytext; return QSTRING; <> return END_OF_FILE; . value=yytext; return UNKNOWN; %% int cil_lexer_setup(char *buffer, uint32_t size) { size = (yy_size_t)size; if (yy_scan_buffer(buffer, size) == NULL) { cil_log(CIL_INFO, "Lexer failed to setup buffer\n"); return SEPOL_ERR; } line = 1; return SEPOL_OK; } void cil_lexer_destroy(void) { yylex_destroy(); } int cil_lexer_next(struct token *tok) { tok->type = yylex(); tok->value = value; tok->line = line; return SEPOL_OK; } libsepol-3.8.1/cil/src/cil_list.c000066400000000000000000000145501476211737200166570ustar00rootroot00000000000000/* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #include #include #include "cil_internal.h" #include "cil_flavor.h" #include "cil_log.h" #include "cil_mem.h" __attribute__((noreturn)) __attribute__((format (printf, 1, 2))) static void cil_list_error(const char* msg, ...) { va_list ap; va_start(ap, msg); cil_vlog(CIL_ERR, msg, ap); va_end(ap); exit(1); } void cil_list_init(struct cil_list **list, enum cil_flavor flavor) { struct cil_list *new_list = cil_malloc(sizeof(*new_list)); new_list->head = NULL; new_list->tail = NULL; new_list->flavor = flavor; *list = new_list; } void cil_list_destroy(struct cil_list **list, unsigned destroy_data) { struct cil_list_item *item; if (*list == NULL) { return; } item = (*list)->head; while (item != NULL) { struct cil_list_item *next = item->next; if (item->flavor == CIL_LIST) { cil_list_destroy((struct cil_list**)&(item->data), destroy_data); free(item); } else { cil_list_item_destroy(&item, destroy_data); } item = next; } free(*list); *list = NULL; } void cil_list_item_init(struct cil_list_item **item) { struct cil_list_item *new_item = cil_malloc(sizeof(*new_item)); new_item->next = NULL; new_item->flavor = CIL_NONE; new_item->data = NULL; *item = new_item; } void cil_list_item_destroy(struct cil_list_item **item, unsigned destroy_data) { if (destroy_data) { cil_destroy_data(&(*item)->data, (*item)->flavor); } free(*item); *item = NULL; } void cil_list_append(struct cil_list *list, enum cil_flavor flavor, void *data) { struct cil_list_item *item; if (list == NULL) { cil_list_error("Attempt to append data to a NULL list"); } cil_list_item_init(&item); item->flavor = flavor; item->data = data; if (list->tail == NULL) { list->head = item; list->tail = item; return; } list->tail->next = item; list->tail = item; } void cil_list_prepend(struct cil_list *list, enum cil_flavor flavor, void *data) { struct cil_list_item *item; if (list == NULL) { cil_list_error("Attempt to prepend data to a NULL list"); } cil_list_item_init(&item); item->flavor = flavor; item->data = data; if (list->tail == NULL) { list->head = item; list->tail = item; return; } item->next = list->head; list->head = item; } struct cil_list_item *cil_list_insert(struct cil_list *list, struct cil_list_item *curr, enum cil_flavor flavor, void *data) { struct cil_list_item *item; if (list == NULL) { cil_list_error("Attempt to append data to a NULL list"); } if (curr == NULL) { /* Insert at the front of the list */ cil_list_prepend(list, flavor, data); return list->head; } if (curr == list->tail) { cil_list_append(list, flavor, data); return list->tail; } cil_list_item_init(&item); item->flavor = flavor; item->data = data; item->next = curr->next; curr->next = item; return item; } void cil_list_append_item(struct cil_list *list, struct cil_list_item *item) { struct cil_list_item *last = item; if (list == NULL) { cil_list_error("Attempt to append an item to a NULL list"); } if (item == NULL) { cil_list_error("Attempt to append a NULL item to a list"); } while (last->next != NULL) { last = last->next; } if (list->tail == NULL) { list->head = item; list->tail = last; return; } list->tail->next = item; list->tail = last; } void cil_list_prepend_item(struct cil_list *list, struct cil_list_item *item) { struct cil_list_item *last = item; if (list == NULL) { cil_list_error("Attempt to prepend an item to a NULL list"); } if (item == NULL) { cil_list_error("Attempt to prepend a NULL item to a list"); } while (last->next != NULL) { last = last->next; } if (list->tail == NULL) { list->head = item; list->tail = last; return; } last->next = list->head; list->head = item; } void cil_list_remove(struct cil_list *list, enum cil_flavor flavor, void *data, unsigned destroy_data) { struct cil_list_item *item; struct cil_list_item *previous = NULL; if (list == NULL) { cil_list_error("Attempt to remove data from a NULL list"); } cil_list_for_each(item, list) { if (item->data == data && item->flavor == flavor) { if (previous == NULL) { list->head = item->next; } else { previous->next = item->next; } if (item->next == NULL) { list->tail = previous; } cil_list_item_destroy(&item, destroy_data); break; } previous = item; } } int cil_list_contains(struct cil_list *list, void *data) { struct cil_list_item *curr = NULL; cil_list_for_each(curr, list) { if (curr->data == data) { return CIL_TRUE; } } return CIL_FALSE; } int cil_list_match_any(struct cil_list *l1, struct cil_list *l2) { struct cil_list_item *i1; struct cil_list_item *i2; cil_list_for_each(i1, l1) { cil_list_for_each(i2, l2) { if (i1->data == i2->data && i1->flavor == i2->flavor) { return CIL_TRUE; } } } return CIL_FALSE; } libsepol-3.8.1/cil/src/cil_list.h000066400000000000000000000057031476211737200166640ustar00rootroot00000000000000/* * 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_is_empty(list) \ ((list) == NULL || (list)->head == NULL) #define cil_list_for_each(item, list) \ for (item = (list)->head; item != NULL; item = item->next) void cil_list_init(struct cil_list **list, enum cil_flavor flavor); void cil_list_destroy (struct cil_list **list, unsigned destroy_data); void cil_list_item_init(struct cil_list_item **item); void cil_list_item_destroy(struct cil_list_item **item, unsigned destroy_data); void cil_list_append(struct cil_list *list, enum cil_flavor flavor, void *data); void cil_list_prepend(struct cil_list *list, enum cil_flavor flavor, void *data); void cil_list_remove(struct cil_list *list, enum cil_flavor flavor, void *data, unsigned destroy_data); struct cil_list_item *cil_list_insert(struct cil_list *list, struct cil_list_item *curr, enum cil_flavor flavor, void *data); void cil_list_append_item(struct cil_list *list, struct cil_list_item *item); void cil_list_prepend_item(struct cil_list *list, struct cil_list_item *item); int cil_list_contains(struct cil_list *list, void *data); int cil_list_match_any(struct cil_list *l1, struct cil_list *l2); #endif libsepol-3.8.1/cil/src/cil_log.c000066400000000000000000000054051476211737200164640ustar00rootroot00000000000000/* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #include #include #include #include #include #include "cil_log.h" static enum cil_log_level cil_log_level = CIL_ERR; static void cil_default_log_handler(__attribute__((unused)) int lvl, const char *msg) { fprintf(stderr, "%s", msg); } static void (*cil_log_handler)(int lvl, const char *msg) = &cil_default_log_handler; void cil_set_log_handler(void (*handler)(int lvl, const char *msg)) { cil_log_handler = handler; } __attribute__ ((format (printf, 2, 0))) void cil_vlog(enum cil_log_level lvl, const char *msg, va_list args) { if (cil_log_level >= lvl) { char buff[MAX_LOG_SIZE]; int n = vsnprintf(buff, MAX_LOG_SIZE, msg, args); if (n > 0) { (*cil_log_handler)(cil_log_level, buff); if (n >= MAX_LOG_SIZE) { (*cil_log_handler)(cil_log_level, " "); } } } } __attribute__ ((format (printf, 2, 3))) void cil_log(enum cil_log_level lvl, const char *msg, ...) { va_list args; va_start(args, msg); cil_vlog(lvl, msg, args); va_end(args); } void cil_set_log_level(enum cil_log_level lvl) { cil_log_level = lvl; } enum cil_log_level cil_get_log_level(void) { return cil_log_level; } libsepol-3.8.1/cil/src/cil_log.h000066400000000000000000000037351476211737200164750ustar00rootroot00000000000000/* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #ifndef CIL_LOG_H_ #define CIL_LOG_H_ #include #include #include #define MAX_LOG_SIZE 512 __attribute__ ((format(printf, 2, 0))) void cil_vlog(enum cil_log_level lvl, const char *msg, va_list args); __attribute__ ((format(printf, 2, 3))) void cil_log(enum cil_log_level lvl, const char *msg, ...); enum cil_log_level cil_get_log_level(void); #endif // CIL_LOG_H_ libsepol-3.8.1/cil/src/cil_mem.c000066400000000000000000000054541476211737200164650ustar00rootroot00000000000000/* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #include #include #include #include #include "cil_log.h" #include "cil_mem.h" void *cil_malloc(size_t size) { void *mem = malloc(size); if (mem == NULL){ if (size == 0) { return NULL; } cil_log(CIL_ERR, "Failed to allocate memory\n"); exit(1); } return mem; } void *cil_calloc(size_t num_elements, size_t element_size) { void *mem = calloc(num_elements, element_size); if (mem == NULL){ cil_log(CIL_ERR, "Failed to allocate memory\n"); exit(1); } return mem; } void *cil_realloc(void *ptr, size_t size) { void *mem = realloc(ptr, size); if (mem == NULL){ if (size == 0) { return NULL; } cil_log(CIL_ERR, "Failed to allocate memory\n"); exit(1); } return mem; } char *cil_strdup(const char *str) { char *mem = NULL; if (str == NULL) { return NULL; } mem = strdup(str); if (mem == NULL) { cil_log(CIL_ERR, "Failed to allocate memory\n"); exit(1); } return mem; } __attribute__ ((format (printf, 2, 3))) int cil_asprintf(char **strp, const char *fmt, ...) { int rc; va_list ap; va_start(ap, fmt); rc = vasprintf(strp, fmt, ap); va_end(ap); if (rc == -1) { cil_log(CIL_ERR, "Failed to allocate memory\n"); exit(1); } return rc; } libsepol-3.8.1/cil/src/cil_mem.h000066400000000000000000000036611476211737200164700ustar00rootroot00000000000000/* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #ifndef CIL_MEM_H_ #define CIL_MEM_H_ /* Wrapped malloc that catches errors and calls the error callback */ void *cil_malloc(size_t size); void *cil_calloc(size_t num_elements, size_t element_size); void *cil_realloc(void *ptr, size_t size); char *cil_strdup(const char *str); int cil_asprintf(char **strp, const char *fmt, ...); #endif /* CIL_MEM_H_ */ libsepol-3.8.1/cil/src/cil_parser.c000066400000000000000000000221071476211737200171750ustar00rootroot00000000000000/* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #include #include #include #include #include #include "cil_internal.h" #include "cil_log.h" #include "cil_mem.h" #include "cil_tree.h" #include "cil_lexer.h" #include "cil_parser.h" #include "cil_strpool.h" #include "cil_stack.h" #define CIL_PARSER_MAX_EXPR_DEPTH (0x1 << 12) struct hll_info { uint32_t hll_offset; uint32_t hll_expand; }; static void push_hll_info(struct cil_stack *stack, uint32_t hll_offset, uint32_t hll_expand) { struct hll_info *new = cil_malloc(sizeof(*new)); new->hll_offset = hll_offset; new->hll_expand = hll_expand; cil_stack_push(stack, CIL_NONE, new); } static void pop_hll_info(struct cil_stack *stack, uint32_t *hll_offset, uint32_t *hll_expand) { struct cil_stack_item *curr = cil_stack_pop(stack); struct hll_info *info; if (!curr) { return; } info = curr->data; *hll_expand = info->hll_expand; *hll_offset = info->hll_offset; free(curr->data); } static void create_node(struct cil_tree_node **node, struct cil_tree_node *current, uint32_t line, uint32_t hll_offset, void *value) { cil_tree_node_init(node); (*node)->parent = current; (*node)->flavor = CIL_NODE; (*node)->line = line; (*node)->hll_offset = hll_offset; (*node)->data = value; } static void insert_node(struct cil_tree_node *node, struct cil_tree_node *current) { if (current->cl_head == NULL) { current->cl_head = node; } else { current->cl_tail->next = node; } current->cl_tail = node; } static int add_hll_linemark(struct cil_tree_node **current, uint32_t *hll_offset, uint32_t *hll_expand, struct cil_stack *stack, char *path) { char *hll_type; struct cil_tree_node *node; struct token tok; uint32_t prev_hll_expand, prev_hll_offset; cil_lexer_next(&tok); if (tok.type != SYMBOL) { cil_log(CIL_ERR, "Invalid line mark syntax\n"); goto exit; } hll_type = cil_strpool_add(tok.value); if (hll_type != CIL_KEY_SRC_HLL_LME && hll_type != CIL_KEY_SRC_HLL_LMS && hll_type != CIL_KEY_SRC_HLL_LMX) { cil_log(CIL_ERR, "Invalid line mark syntax\n"); goto exit; } if (hll_type == CIL_KEY_SRC_HLL_LME) { if (cil_stack_is_empty(stack)) { cil_log(CIL_ERR, "Line mark end without start\n"); goto exit; } prev_hll_expand = *hll_expand; prev_hll_offset = *hll_offset; pop_hll_info(stack, hll_offset, hll_expand); if (!*hll_expand) { /* This is needed if not going back to an lmx section. */ *hll_offset = prev_hll_offset; } if (prev_hll_expand && !*hll_expand) { /* This is needed to count the lme at the end of an lmx section * within an lms section (or within no hll section). */ (*hll_offset)++; } *current = (*current)->parent; } else { push_hll_info(stack, *hll_offset, *hll_expand); if (cil_stack_number_of_items(stack) > CIL_PARSER_MAX_EXPR_DEPTH) { cil_log(CIL_ERR, "Number of active line marks exceeds limit of %d\n", CIL_PARSER_MAX_EXPR_DEPTH); goto exit; } create_node(&node, *current, tok.line, *hll_offset, NULL); insert_node(node, *current); *current = node; create_node(&node, *current, tok.line, *hll_offset, CIL_KEY_SRC_INFO); insert_node(node, *current); create_node(&node, *current, tok.line, *hll_offset, hll_type); insert_node(node, *current); cil_lexer_next(&tok); if (tok.type != SYMBOL) { cil_log(CIL_ERR, "Invalid line mark syntax\n"); goto exit; } create_node(&node, *current, tok.line, *hll_offset, cil_strpool_add(tok.value)); insert_node(node, *current); cil_lexer_next(&tok); if (tok.type != SYMBOL && tok.type != QSTRING) { cil_log(CIL_ERR, "Invalid line mark syntax\n"); goto exit; } if (tok.type == QSTRING) { tok.value[strlen(tok.value) - 1] = '\0'; tok.value = tok.value+1; } create_node(&node, *current, tok.line, *hll_offset, cil_strpool_add(tok.value)); insert_node(node, *current); *hll_expand = (hll_type == CIL_KEY_SRC_HLL_LMX) ? 1 : 0; } cil_lexer_next(&tok); if (tok.type != NEWLINE) { cil_log(CIL_ERR, "Invalid line mark syntax\n"); goto exit; } if (!*hll_expand) { /* Need to increment because of the NEWLINE */ (*hll_offset)++; } return SEPOL_OK; exit: cil_log(CIL_ERR, "Problem with high-level line mark at line %u of %s\n", tok.line, path); return SEPOL_ERR; } static void add_cil_path(struct cil_tree_node **current, char *path) { struct cil_tree_node *node; create_node(&node, *current, 0, 0, NULL); insert_node(node, *current); *current = node; create_node(&node, *current, 0, 0, CIL_KEY_SRC_INFO); insert_node(node, *current); create_node(&node, *current, 0, 0, CIL_KEY_SRC_CIL); insert_node(node, *current); create_node(&node, *current, 0, 0, cil_strpool_add("1")); insert_node(node, *current); create_node(&node, *current, 0, 0, path); insert_node(node, *current); } int cil_parser(const char *_path, char *buffer, uint32_t size, struct cil_tree **parse_tree) { int paren_count = 0; struct cil_tree *tree = NULL; struct cil_tree_node *node = NULL; struct cil_tree_node *current = NULL; char *path = cil_strpool_add(_path); struct cil_stack *stack; uint32_t hll_offset = 1; uint32_t hll_expand = 0; struct token tok; int rc = SEPOL_OK; cil_stack_init(&stack); cil_lexer_setup(buffer, size); tree = *parse_tree; current = tree->root; add_cil_path(¤t, path); do { cil_lexer_next(&tok); switch (tok.type) { case HLL_LINEMARK: rc = add_hll_linemark(¤t, &hll_offset, &hll_expand, stack, path); if (rc != SEPOL_OK) { goto exit; } break; case OPAREN: paren_count++; if (paren_count > CIL_PARSER_MAX_EXPR_DEPTH) { cil_log(CIL_ERR, "Number of open parenthesis exceeds limit of %d at line %d of %s\n", CIL_PARSER_MAX_EXPR_DEPTH, tok.line, path); goto exit; } create_node(&node, current, tok.line, hll_offset, NULL); insert_node(node, current); current = node; break; case CPAREN: paren_count--; if (paren_count < 0) { cil_log(CIL_ERR, "Close parenthesis without matching open at line %d of %s\n", tok.line, path); goto exit; } current = current->parent; break; case QSTRING: tok.value[strlen(tok.value) - 1] = '\0'; tok.value = tok.value+1; /* FALLTHRU */ case SYMBOL: if (paren_count == 0) { cil_log(CIL_ERR, "Symbol not inside parenthesis at line %d of %s\n", tok.line, path); goto exit; } create_node(&node, current, tok.line, hll_offset, cil_strpool_add(tok.value)); insert_node(node, current); break; case NEWLINE : if (!hll_expand) { hll_offset++; } break; case COMMENT: while (tok.type != NEWLINE && tok.type != END_OF_FILE) { cil_lexer_next(&tok); } if (!hll_expand) { hll_offset++; } if (tok.type != END_OF_FILE) { break; } /* FALLTHRU */ // Fall through if EOF case END_OF_FILE: if (paren_count > 0) { cil_log(CIL_ERR, "Open parenthesis without matching close at line %d of %s\n", tok.line, path); goto exit; } if (!cil_stack_is_empty(stack)) { cil_log(CIL_ERR, "High-level language line marker start without close at line %d of %s\n", tok.line, path); goto exit; } break; case UNKNOWN: cil_log(CIL_ERR, "Invalid token '%s' at line %d of %s\n", tok.value, tok.line, path); goto exit; default: cil_log(CIL_ERR, "Unknown token type '%d' at line %d of %s\n", tok.type, tok.line, path); goto exit; } } while (tok.type != END_OF_FILE); cil_lexer_destroy(); cil_stack_destroy(&stack); *parse_tree = tree; return SEPOL_OK; exit: while (!cil_stack_is_empty(stack)) { pop_hll_info(stack, &hll_offset, &hll_expand); } cil_lexer_destroy(); cil_stack_destroy(&stack); return SEPOL_ERR; } libsepol-3.8.1/cil/src/cil_parser.h000066400000000000000000000034111476211737200171770ustar00rootroot00000000000000/* * 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(const char *path, char *buffer, uint32_t size, struct cil_tree **parse_tree); #endif /* CIL_PARSER_H_ */ libsepol-3.8.1/cil/src/cil_policy.c000066400000000000000000001441371476211737200172100ustar00rootroot00000000000000/* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #include #include #include #include #include #include #include #include #include "cil_internal.h" #include "cil_flavor.h" #include "cil_find.h" #include "cil_mem.h" #include "cil_policy.h" #include "cil_tree.h" #include "cil_list.h" #include "cil_symtab.h" enum cil_statement_list { CIL_LIST_COMMON = 1, CIL_LIST_DEFAULT_USER, CIL_LIST_DEFAULT_ROLE, CIL_LIST_DEFAULT_TYPE, CIL_LIST_DEFAULT_RANGE, CIL_LIST_SENSALIAS, CIL_LIST_CATALIAS, CIL_LIST_MLSCONSTRAIN, CIL_LIST_MLSVALIDATETRANS, CIL_LIST_POLICYCAP, CIL_LIST_TYPEATTRIBUTE, CIL_LIST_ROLEATTRIBUTE, CIL_LIST_BOOL, CIL_LIST_TYPE, CIL_LIST_TYPEALIAS, CIL_LIST_ROLE, CIL_LIST_ROLEALLOW, CIL_LIST_ROLETRANSITION, CIL_LIST_USER, CIL_LIST_CONSTRAINT, CIL_LIST_VALIDATETRANS, CIL_LIST_NUM_LISTS }; static int __cil_gather_statements_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args) { struct cil_list **lists; int kind = 0; lists = (struct cil_list **)extra_args; switch (node->flavor) { case CIL_BLOCK: { struct cil_block *blk = node->data; if (blk->is_abstract == CIL_TRUE) { *finished = CIL_TREE_SKIP_HEAD; } break; } case CIL_MACRO: *finished = CIL_TREE_SKIP_HEAD; break; case CIL_BOOLEANIF: *finished = CIL_TREE_SKIP_HEAD; break; case CIL_COMMON: kind = CIL_LIST_COMMON; break; case CIL_DEFAULTUSER: kind = CIL_LIST_DEFAULT_USER; break; case CIL_DEFAULTROLE: kind = CIL_LIST_DEFAULT_ROLE; break; case CIL_DEFAULTTYPE: kind = CIL_LIST_DEFAULT_TYPE; break; case CIL_DEFAULTRANGE: kind = CIL_LIST_DEFAULT_RANGE; break; case CIL_SENSALIAS: kind = CIL_LIST_SENSALIAS; break; case CIL_CATALIAS: kind = CIL_LIST_CATALIAS; break; case CIL_MLSCONSTRAIN: kind = CIL_LIST_MLSCONSTRAIN; break; case CIL_MLSVALIDATETRANS: kind = CIL_LIST_MLSVALIDATETRANS; break; case CIL_POLICYCAP: kind = CIL_LIST_POLICYCAP; break; case CIL_TYPEATTRIBUTE: { struct cil_typeattribute *attr = node->data; if (strcmp(attr->datum.fqn, "cil_gen_require") != 0) { kind = CIL_LIST_TYPEATTRIBUTE; } break; } case CIL_ROLEATTRIBUTE: { struct cil_roleattribute *attr = node->data; if (strcmp(attr->datum.fqn, "cil_gen_require") != 0) { kind = CIL_LIST_ROLEATTRIBUTE; } break; } case CIL_BOOL: kind = CIL_LIST_BOOL; break; case CIL_TYPE: kind = CIL_LIST_TYPE; break; case CIL_TYPEALIAS: kind = CIL_LIST_TYPEALIAS; break; case CIL_ROLE: { struct cil_role *role = node->data; if (strcmp(role->datum.fqn, "object_r") != 0) { kind = CIL_LIST_ROLE; } break; } case CIL_ROLEALLOW: kind = CIL_LIST_ROLEALLOW; break; case CIL_ROLETRANSITION: kind = CIL_LIST_ROLETRANSITION; break; case CIL_USER: kind = CIL_LIST_USER; break; case CIL_CONSTRAIN: kind = CIL_LIST_CONSTRAINT; break; case CIL_VALIDATETRANS: kind = CIL_LIST_VALIDATETRANS; break; default: break; } if (kind > 0) { cil_list_append(lists[kind], node->flavor, node->data); } return SEPOL_OK; } static void cil_gather_statements(struct cil_tree_node *start, struct cil_list *lists[]) { cil_tree_walk(start, __cil_gather_statements_helper, NULL, NULL, lists); } static void cil_simple_rules_to_policy(FILE *out, struct cil_list *rules, const char *kind) { struct cil_list_item *i1; cil_list_for_each(i1, rules) { fprintf(out, "%s %s;\n", kind, DATUM(i1->data)->fqn); } } static void cil_cats_to_policy(FILE *out, struct cil_cats *cats) { const char *lead = ""; struct cil_cat *first = NULL, *last = NULL, *cat; struct cil_list_item *i1; cil_list_for_each(i1, cats->datum_expr) { cat = i1->data; if (first == NULL) { first = cat; } else if (last == NULL) { if (cat->value == first->value + 1) { last = cat; } else { fprintf(out, "%s%s", lead, DATUM(first)->fqn); lead = ","; first = cat; } } else if (cat->value == last->value + 1) { last = cat; } else { fprintf(out, "%s%s", lead, DATUM(first)->fqn); lead = ","; if (last->value >= first->value + 1) { fprintf(out, "."); } else { fprintf(out, ","); } fprintf(out, "%s", DATUM(last)->fqn); first = cat; last = NULL; } } if (first) { fprintf(out, "%s%s", lead, DATUM(first)->fqn); if (last != NULL) { if (last->value >= first->value + 1) { fprintf(out, "."); } else { fprintf(out, ","); } fprintf(out, "%s", DATUM(last)->fqn); } } } static void cil_level_to_policy(FILE *out, struct cil_level *level) { fprintf(out, "%s", DATUM(level->sens)->fqn); if (level->cats != NULL) { fprintf(out, ":"); cil_cats_to_policy(out, level->cats); } } static int cil_levels_simple_and_equal(struct cil_level *l1, struct cil_level *l2) { /* Mostly just want to detect s0 - s0 ranges */ if (l1 == l2) return CIL_TRUE; if (l1->sens == l2->sens && (l1->cats == NULL && l2->cats == NULL)) return CIL_TRUE; return CIL_FALSE; } static void cil_levelrange_to_policy(FILE *out, struct cil_levelrange *lvlrange) { cil_level_to_policy(out, lvlrange->low); if (cil_levels_simple_and_equal(lvlrange->low, lvlrange->high) == CIL_FALSE) { fprintf(out, " - "); cil_level_to_policy(out, lvlrange->high); } } static void cil_context_to_policy(FILE *out, struct cil_context *context, int mls) { fprintf(out, "%s:", DATUM(context->user)->fqn); fprintf(out, "%s:", DATUM(context->role)->fqn); fprintf(out, "%s", DATUM(context->type)->fqn); if (mls) { fprintf(out, ":"); cil_levelrange_to_policy(out, context->range); } } static void cil_cond_expr_to_policy(FILE *out, struct cil_list *expr, int first) { struct cil_list_item *i1 = expr->head; if (i1->flavor == CIL_OP) { enum cil_flavor op = (enum cil_flavor)(uintptr_t)i1->data; fprintf(out, "("); switch (op) { case CIL_NOT: fprintf(out, "! "); cil_cond_expr_to_policy(out, i1->next->data, CIL_FALSE); break; case CIL_OR: cil_cond_expr_to_policy(out, i1->next->data, CIL_FALSE); fprintf(out, " || "); cil_cond_expr_to_policy(out, i1->next->next->data, CIL_FALSE); break; case CIL_AND: cil_cond_expr_to_policy(out, i1->next->data, CIL_FALSE); fprintf(out, " && "); cil_cond_expr_to_policy(out, i1->next->next->data, CIL_FALSE); break; case CIL_XOR: cil_cond_expr_to_policy(out, i1->next->data, CIL_FALSE); fprintf(out, " ^ "); cil_cond_expr_to_policy(out, i1->next->next->data, CIL_FALSE); break; case CIL_EQ: cil_cond_expr_to_policy(out, i1->next->data, CIL_FALSE); fprintf(out, " == "); cil_cond_expr_to_policy(out, i1->next->next->data, CIL_FALSE); break; case CIL_NEQ: cil_cond_expr_to_policy(out, i1->next->data, CIL_FALSE); fprintf(out, " != "); cil_cond_expr_to_policy(out, i1->next->next->data, CIL_FALSE); break; default: fprintf(out, "???"); break; } fprintf(out, ")"); } else if (i1->flavor == CIL_DATUM) { if (first == CIL_TRUE) { fprintf(out, "("); } fprintf(out, "%s", DATUM(i1->data)->fqn); if (first == CIL_TRUE) { fprintf(out, ")"); } } else if (i1->flavor == CIL_LIST) { cil_cond_expr_to_policy(out, i1->data, CIL_FALSE); } else { fprintf(out, "???"); } } static size_t __cil_userattribute_len(struct cil_db *db, struct cil_userattribute *attr) { ebitmap_node_t *unode; unsigned int i; size_t len = 0; ebitmap_for_each_positive_bit(attr->users, unode, i) { len += strlen(DATUM(db->val_to_user[i])->fqn); len++; } return len; } static size_t __cil_cons_leaf_operand_len(struct cil_db *db, struct cil_list_item *operand) { struct cil_list_item *i1; enum cil_flavor flavor = operand->flavor; size_t len = 0; if (flavor == CIL_CONS_OPERAND) { len = 2; } else if (flavor == CIL_DATUM) { struct cil_tree_node *node = NODE(operand->data); if (node->flavor == CIL_USERATTRIBUTE) { len = __cil_userattribute_len(db, operand->data); len++; /* "{" */ } else { len = strlen(DATUM(operand->data)->fqn); } } else if (flavor == CIL_LIST) { len = 1; /* "{" */ cil_list_for_each(i1, (struct cil_list *)operand->data) { struct cil_tree_node *node = NODE(operand->data); if (node->flavor == CIL_USERATTRIBUTE) { len = __cil_userattribute_len(db, operand->data); } else { len += strlen(DATUM(operand->data)->fqn); len++; /* " " or "}" */ } } } return len; } static size_t __cil_cons_leaf_op_len(struct cil_list_item *op) { enum cil_flavor flavor = (enum cil_flavor)(uintptr_t)op->data; size_t len; switch (flavor) { case CIL_EQ: len = 4; /* " == " */ break; case CIL_NEQ: len = 4; /* " != " */ break; case CIL_CONS_DOM: len = 5; /* " dom " */ break; case CIL_CONS_DOMBY: len = 7; /* " domby " */ break; case CIL_CONS_INCOMP: len = 8; /* " incomp " */ break; default: /* Should be impossible to be here */ len = 5; /* " ??? " */ } return len; } static size_t cil_cons_expr_len(struct cil_db *db, struct cil_list *cons_expr) { struct cil_list_item *i1; enum cil_flavor op; size_t len; i1 = cons_expr->head; op = (enum cil_flavor)(uintptr_t)i1->data; switch (op) { case CIL_NOT: len = 6; /* "(not )" */ len += cil_cons_expr_len(db, i1->next->data); break; case CIL_AND: len = 7; /* "( and )" */ len += cil_cons_expr_len(db, i1->next->data); len += cil_cons_expr_len(db, i1->next->next->data); break; case CIL_OR: len = 6; /* "( or )" */ len += cil_cons_expr_len(db, i1->next->data); len += cil_cons_expr_len(db, i1->next->next->data); break; default: len = 2; /* "()" */ len += __cil_cons_leaf_operand_len(db, i1->next); len += __cil_cons_leaf_op_len(i1); len += __cil_cons_leaf_operand_len(db, i1->next->next); } return len; } static char *__cil_userattribute_to_string(struct cil_db *db, struct cil_userattribute *attr, char *new) { ebitmap_node_t *unode; unsigned int i; char *str; size_t len; ebitmap_for_each_positive_bit(attr->users, unode, i) { str = DATUM(db->val_to_user[i])->fqn; len = strlen(str); memcpy(new, str, len); new += len; *new++ = ' '; } return new; } static char *__cil_cons_leaf_operand_to_string(struct cil_db *db, struct cil_list_item *operand, char *new) { struct cil_list_item *i1; enum cil_flavor flavor = operand->flavor; const char *o_str; size_t o_len; if (flavor == CIL_CONS_OPERAND) { enum cil_flavor o_flavor = (enum cil_flavor)(uintptr_t)operand->data; switch (o_flavor) { case CIL_CONS_U1: o_str = "u1"; break; case CIL_CONS_U2: o_str = "u2"; break; case CIL_CONS_U3: o_str = "u3"; break; case CIL_CONS_R1: o_str = "r1"; break; case CIL_CONS_R2: o_str = "r2"; break; case CIL_CONS_R3: o_str = "r3"; break; case CIL_CONS_T1: o_str = "t1"; break; case CIL_CONS_T2: o_str = "t2"; break; case CIL_CONS_T3: o_str = "t3"; break; case CIL_CONS_L1: o_str = "l1"; break; case CIL_CONS_L2: o_str = "l2"; break; case CIL_CONS_H1: o_str = "h1"; break; case CIL_CONS_H2: o_str = "h2"; break; default: /* Impossible */ o_str = "??"; } strcpy(new, o_str); new += 2; } else if (flavor == CIL_DATUM) { struct cil_tree_node *node = NODE(operand->data); if (node->flavor == CIL_USERATTRIBUTE) { *new++ = '{'; new = __cil_userattribute_to_string(db, operand->data, new); new--; *new++ = '}'; } else { o_str = DATUM(operand->data)->fqn; o_len = strlen(o_str); memcpy(new, o_str, o_len); new += o_len; } } else if (flavor == CIL_LIST) { *new++ = '{'; cil_list_for_each(i1, (struct cil_list *)operand->data) { struct cil_tree_node *node = NODE(operand->data); if (node->flavor == CIL_USERATTRIBUTE) { new = __cil_userattribute_to_string(db, operand->data, new); } else { o_str = DATUM(operand->data)->fqn; o_len = strlen(o_str); memcpy(new, o_str, o_len); new += o_len; *new++ = ' '; } } new--; *new++ = '}'; } return new; } static char *__cil_cons_leaf_op_to_string(struct cil_list_item *op, char *new) { enum cil_flavor flavor = (enum cil_flavor)(uintptr_t)op->data; const char *op_str; size_t len; switch (flavor) { case CIL_EQ: op_str = " == "; len = 4; break; case CIL_NEQ: op_str = " != "; len = 4; break; case CIL_CONS_DOM: op_str = " dom "; len = 5; break; case CIL_CONS_DOMBY: op_str = " domby "; len = 7; break; case CIL_CONS_INCOMP: op_str = " incomp "; len = 8; break; default: /* Should be impossible to be here */ op_str = " ??? "; len = 5; } strcpy(new, op_str); new += len; return new; } static char *__cil_cons_expr_to_string(struct cil_db *db, struct cil_list *cons_expr, char *new) { struct cil_list_item *i1; enum cil_flavor op; i1 = cons_expr->head; op = (enum cil_flavor)(uintptr_t)i1->data; switch (op) { case CIL_NOT: *new++ = '('; strcpy(new, "not "); new += 4; new = __cil_cons_expr_to_string(db, i1->next->data, new); *new++ = ')'; break; case CIL_AND: *new++ = '('; new = __cil_cons_expr_to_string(db, i1->next->data, new); strcpy(new, " and "); new += 5; new = __cil_cons_expr_to_string(db, i1->next->next->data, new); *new++ = ')'; break; case CIL_OR: *new++ = '('; new = __cil_cons_expr_to_string(db, i1->next->data, new); strcpy(new, " or "); new += 4; new = __cil_cons_expr_to_string(db, i1->next->next->data, new); *new++ = ')'; break; default: *new++ = '('; new = __cil_cons_leaf_operand_to_string(db, i1->next, new); new = __cil_cons_leaf_op_to_string(i1, new); new = __cil_cons_leaf_operand_to_string(db, i1->next->next, new); *new++ = ')'; } return new; } static char *cil_cons_expr_to_string(struct cil_db *db, struct cil_list *cons_expr) { char *new, *tail; size_t len = cil_cons_expr_len(db, cons_expr); new = cil_malloc(len+1); tail = __cil_cons_expr_to_string(db, cons_expr, new); *tail = '\0'; return new; } static void cil_classperms_to_string(struct cil_classperms *classperms, struct cil_list *classperms_strs) { struct cil_list_item *i1; size_t len = 0; char *new, *curr; len += strlen(DATUM(classperms->class)->fqn) + 1; cil_list_for_each(i1, classperms->perms) { len += strlen(DATUM(i1->data)->fqn) + 1; } len += 4; /* for "{ " and " }" */ new = cil_malloc(len); curr = new; curr[len-1] = '\0'; len = strlen(DATUM(classperms->class)->fqn); memcpy(curr, DATUM(classperms->class)->fqn, len); curr += len; *curr++ = ' '; *curr++ = '{'; *curr++ = ' '; cil_list_for_each(i1, classperms->perms) { len = strlen(DATUM(i1->data)->fqn); memcpy(curr, DATUM(i1->data)->fqn, len); curr += len; *curr++ = ' '; } *curr++ = '}'; cil_list_append(classperms_strs, CIL_STRING, new); } static void cil_classperms_to_strings(struct cil_list *classperms, struct cil_list *classperms_strs) { struct cil_list_item *i1; cil_list_for_each(i1, classperms) { if (i1->flavor == CIL_CLASSPERMS) { struct cil_classperms *cp = i1->data; if (FLAVOR(cp->class) == CIL_CLASS) { cil_classperms_to_string(cp, classperms_strs); } else { /* MAP */ struct cil_list_item *i2 = NULL; cil_list_for_each(i2, cp->perms) { struct cil_perm *cmp = i2->data; cil_classperms_to_strings(cmp->classperms, classperms_strs); } } } else { /* SET */ struct cil_classperms_set *cp_set = i1->data; struct cil_classpermission *cp = cp_set->set; cil_classperms_to_strings(cp->classperms, classperms_strs); } } } static void cil_class_decls_to_policy(FILE *out, struct cil_list *classorder) { struct cil_list_item *i1; cil_list_for_each(i1, classorder) { fprintf(out, "class %s\n", DATUM(i1->data)->fqn); } } static void cil_sid_decls_to_policy(FILE *out, struct cil_list *sidorder) { struct cil_list_item *i1; cil_list_for_each(i1, sidorder) { fprintf(out, "sid %s\n", DATUM(i1->data)->fqn); } } static void cil_commons_to_policy(FILE *out, struct cil_list *commons) { struct cil_list_item *i1; struct cil_class* common; struct cil_tree_node *node; struct cil_tree_node *perm; cil_list_for_each(i1, commons) { common = i1->data; node = NODE(&common->datum); perm = node->cl_head; fprintf(out, "common %s {", common->datum.fqn); while (perm != NULL) { fprintf(out, "%s ", DATUM(perm->data)->fqn); perm = perm->next; } fprintf(out, "}\n"); } } static void cil_classes_to_policy(FILE *out, struct cil_list *classorder) { struct cil_list_item *i1; struct cil_class *class; struct cil_tree_node *node; cil_list_for_each(i1, classorder) { class = i1->data; node = NODE(&class->datum); fprintf(out, "class %s", class->datum.fqn); if (class->common != NULL) { fprintf(out, " inherits %s", class->common->datum.fqn); } if (node->cl_head != NULL) { struct cil_tree_node *perm = node->cl_head; fprintf(out, " {"); while (perm != NULL) { fprintf(out, " %s", DATUM(perm->data)->fqn); perm = perm->next; } fprintf(out, " }"); } fprintf(out, "\n"); } } static void cil_defaults_to_policy(FILE *out, struct cil_list *defaults, const char *kind) { struct cil_list_item *i1, *i2, *i3; struct cil_default *def; struct cil_list *class_list; cil_list_for_each(i1, defaults) { def = i1->data; fprintf(out, "%s {",kind); cil_list_for_each(i2, def->class_datums) { class_list = cil_expand_class(i2->data); cil_list_for_each(i3, class_list) { fprintf(out, " %s", DATUM(i3->data)->fqn); } cil_list_destroy(&class_list, CIL_FALSE); } fprintf(out, " }"); if (def->object == CIL_DEFAULT_SOURCE) { fprintf(out," %s",CIL_KEY_SOURCE); } else if (def->object == CIL_DEFAULT_TARGET) { fprintf(out," %s",CIL_KEY_TARGET); } fprintf(out,";\n"); } } static void cil_default_ranges_to_policy(FILE *out, struct cil_list *defaults) { struct cil_list_item *i1, *i2, *i3; struct cil_defaultrange *def; struct cil_list *class_list; cil_list_for_each(i1, defaults) { def = i1->data; fprintf(out, "default_range {"); cil_list_for_each(i2, def->class_datums) { class_list = cil_expand_class(i2->data); cil_list_for_each(i3, class_list) { fprintf(out, " %s", DATUM(i3->data)->fqn); } cil_list_destroy(&class_list, CIL_FALSE); } fprintf(out, " }"); switch (def->object_range) { case CIL_DEFAULT_SOURCE_LOW: fprintf(out," %s %s", CIL_KEY_SOURCE, CIL_KEY_LOW); break; case CIL_DEFAULT_SOURCE_HIGH: fprintf(out," %s %s", CIL_KEY_SOURCE, CIL_KEY_HIGH); break; case CIL_DEFAULT_SOURCE_LOW_HIGH: fprintf(out," %s %s", CIL_KEY_SOURCE, CIL_KEY_LOW_HIGH); break; case CIL_DEFAULT_TARGET_LOW: fprintf(out," %s %s", CIL_KEY_TARGET, CIL_KEY_LOW); break; case CIL_DEFAULT_TARGET_HIGH: fprintf(out," %s %s", CIL_KEY_TARGET, CIL_KEY_HIGH); break; case CIL_DEFAULT_TARGET_LOW_HIGH: fprintf(out," %s %s", CIL_KEY_TARGET, CIL_KEY_LOW_HIGH); break; case CIL_DEFAULT_GLBLUB: fprintf(out," %s", CIL_KEY_GLBLUB); break; default: break; } fprintf(out,";\n"); } } static void cil_sensitivities_to_policy(FILE *out, struct cil_list *sensorder, struct cil_list *all_aliases) { struct cil_list_item *i1, *i2; struct cil_sens *sens; struct cil_list *aliases = NULL; struct cil_alias *alias; struct cil_sens *actual; int num_aliases; cil_list_for_each(i1, sensorder) { sens = i1->data; num_aliases = 0; cil_list_for_each(i2, all_aliases) { alias = i2->data; actual = alias->actual; if (sens == actual) { if (num_aliases == 0) { cil_list_init(&aliases, CIL_LIST); } cil_list_append(aliases, CIL_SENSALIAS, alias); num_aliases++; } } fprintf(out, "sensitivity %s", sens->datum.fqn); if (num_aliases > 0) { fprintf(out, " alias"); if (num_aliases > 1) { fprintf(out, " {"); } cil_list_for_each(i2, aliases) { alias = i2->data; fprintf(out, " %s", alias->datum.fqn); } if (num_aliases > 1) { fprintf(out, " }"); } cil_list_destroy(&aliases, CIL_FALSE); } fprintf(out, ";\n"); } } static void cil_dominance_to_policy(FILE *out, struct cil_list *sensorder) { struct cil_list_item *item; struct cil_sens *sens; fprintf(out, "dominance {"); cil_list_for_each(item, sensorder) { sens = item->data; fprintf(out, " %s", sens->datum.fqn); } fprintf(out, " }\n"); } static void cil_categories_to_policy(FILE *out, struct cil_list *catorder, struct cil_list *all_aliases) { struct cil_list_item *i1, *i2; struct cil_sens *cat; struct cil_list *aliases = NULL; struct cil_alias *alias; struct cil_sens *actual; int num_aliases; cil_list_for_each(i1, catorder) { cat = i1->data; num_aliases = 0; cil_list_for_each(i2, all_aliases) { alias = i2->data; actual = alias->actual; if (cat == actual) { if (num_aliases == 0) { cil_list_init(&aliases, CIL_LIST); } cil_list_append(aliases, CIL_CATALIAS, alias); num_aliases++; } } fprintf(out, "category %s",cat->datum.fqn); if (num_aliases > 0) { fprintf(out, " alias"); if (num_aliases > 1) { fprintf(out, " { "); } cil_list_for_each(i2, aliases) { alias = i2->data; fprintf(out, " %s", alias->datum.fqn); } if (num_aliases > 1) { fprintf(out, " }"); } cil_list_destroy(&aliases, CIL_FALSE); } fprintf(out, ";\n"); } } static void cil_levels_to_policy(FILE *out, struct cil_list *sensorder) { struct cil_list_item *i1, *i2; struct cil_sens *sens; cil_list_for_each(i1, sensorder) { sens = i1->data; if (sens->cats_list) { cil_list_for_each(i2, sens->cats_list) { fprintf(out, "level %s:",sens->datum.fqn); cil_cats_to_policy(out, i2->data); fprintf(out,";\n"); } } else { fprintf(out, "level %s;\n",sens->datum.fqn); } } } static void cil_mlsconstrains_to_policy(FILE *out, struct cil_db *db, struct cil_list *mlsconstrains) { struct cil_list_item *i1, *i2; struct cil_constrain *cons; struct cil_list *classperms_strs; char *cp_str; char *expr_str; cil_list_for_each(i1, mlsconstrains) { cons = i1->data; cil_list_init(&classperms_strs, CIL_LIST); cil_classperms_to_strings(cons->classperms, classperms_strs); expr_str = cil_cons_expr_to_string(db, cons->datum_expr); cil_list_for_each(i2, classperms_strs) { cp_str = i2->data; fprintf(out, "mlsconstrain %s %s;\n", cp_str, expr_str); free(cp_str); } free(expr_str); cil_list_destroy(&classperms_strs, CIL_FALSE); } } static void cil_validatetrans_to_policy(FILE *out, struct cil_db *db, struct cil_list *validatetrans, char *kind) { struct cil_list_item *i1, *i2; struct cil_validatetrans *trans; struct cil_list *class_list; struct cil_class *class; char *expr_str; cil_list_for_each(i1, validatetrans) { trans = i1->data; class_list = cil_expand_class(trans->class); expr_str = cil_cons_expr_to_string(db, trans->datum_expr); cil_list_for_each(i2, class_list) { class = i2->data; fprintf(out, "%s %s %s;\n", kind, class->datum.fqn, expr_str); } free(expr_str); cil_list_destroy(&class_list, CIL_FALSE); } } static void cil_bools_to_policy(FILE *out, struct cil_list *bools) { struct cil_list_item *i1; struct cil_bool *boolean; const char *value; cil_list_for_each(i1, bools) { boolean = i1->data; value = boolean->value ? "true" : "false"; fprintf(out, "bool %s %s;\n", boolean->datum.fqn, value); } } static void cil_typealiases_to_policy(FILE *out, struct cil_list *types, struct cil_list *all_aliases) { struct cil_list_item *i1, *i2; struct cil_type *type; struct cil_list *aliases = NULL; struct cil_alias *alias; struct cil_type *actual; int num_aliases; cil_list_for_each(i1, types) { type = i1->data; num_aliases = 0; cil_list_for_each(i2, all_aliases) { alias = i2->data; actual = alias->actual; if (type == actual) { if (num_aliases == 0) { cil_list_init(&aliases, CIL_LIST); } cil_list_append(aliases, CIL_TYPEALIAS, alias); num_aliases++; } } if (num_aliases > 0) { fprintf(out, "typealias %s alias", type->datum.fqn); if (num_aliases > 1) { fprintf(out, " {"); } cil_list_for_each(i2, aliases) { alias = i2->data; fprintf(out, " %s", alias->datum.fqn); } if (num_aliases > 1) { fprintf(out, " }"); } fprintf(out, ";\n"); cil_list_destroy(&aliases, CIL_FALSE); } } } static void cil_typebounds_to_policy(FILE *out, struct cil_list *types) { struct cil_list_item *i1; struct cil_type *child; struct cil_type *parent; cil_list_for_each(i1, types) { child = i1->data; if (child->bounds != NULL) { parent = child->bounds; fprintf(out, "typebounds %s %s;\n", parent->datum.fqn, child->datum.fqn); } } } static void cil_typeattributes_to_policy(FILE *out, struct cil_list *types, struct cil_list *attributes) { struct cil_list_item *i1, *i2; struct cil_type *type; struct cil_typeattribute *attribute; int first = CIL_TRUE; cil_list_for_each(i1, types) { type = i1->data; cil_list_for_each(i2, attributes) { attribute = i2->data; if (!attribute->keep) continue; if (ebitmap_get_bit(attribute->types, type->value)) { if (first) { fprintf(out, "typeattribute %s %s", type->datum.fqn, attribute->datum.fqn); first = CIL_FALSE; } else { fprintf(out, ", %s", attribute->datum.fqn); } } } if (!first) { fprintf(out, ";\n"); first = CIL_TRUE; } } } static void cil_xperms_to_policy(FILE *out, struct cil_permissionx *permx) { ebitmap_node_t *node; unsigned int i, first = 0, last = 0; int need_first = CIL_TRUE, need_last = CIL_TRUE; const char *kind; if (permx->kind == CIL_PERMX_KIND_IOCTL) { kind = "ioctl"; } else if (permx->kind == CIL_PERMX_KIND_NLMSG) { kind = "nlmsg"; } else { kind = "???"; } fprintf(out, "%s %s {", DATUM(permx->obj)->fqn, kind); ebitmap_for_each_positive_bit(permx->perms, node, i) { if (need_first == CIL_TRUE) { first = i; need_first = CIL_FALSE; } else if (need_last == CIL_TRUE) { if (i == first+1) { last = i; need_last = CIL_FALSE; } else { fprintf(out, " 0x%x", first); first = i; } } else if (i == last+1) { last = i; } else { if (last > first+1) { fprintf(out, " 0x%x-0x%x", first, last); } else { fprintf(out, " 0x%x 0x%x", first, last); } first = i; need_last = CIL_TRUE; } } if (need_first == CIL_FALSE) { if (need_last == CIL_FALSE) { fprintf(out, " 0x%x-0x%x", first, last); } else { fprintf(out, " 0x%x", first); } } fprintf(out," }"); } static void cil_av_rulex_to_policy(FILE *out, struct cil_avrule *rule) { const char *kind; struct cil_symtab_datum *src, *tgt; src = rule->src; tgt = rule->tgt; switch (rule->rule_kind) { case CIL_AVRULE_ALLOWED: kind = "allowxperm"; break; case CIL_AVRULE_AUDITALLOW: kind = "auditallowxperm"; break; case CIL_AVRULE_DONTAUDIT: kind = "dontauditxperm"; break; case CIL_AVRULE_NEVERALLOW: kind = "neverallowxperm"; break; default: kind = "???"; break; } fprintf(out, "%s %s %s : ", kind, src->fqn, tgt->fqn); cil_xperms_to_policy(out, rule->perms.x.permx); fprintf(out, ";\n"); } static void cil_av_rule_to_policy(FILE *out, struct cil_avrule *rule) { const char *kind; struct cil_symtab_datum *src, *tgt; struct cil_list *classperms_strs; struct cil_list_item *i1; src = rule->src; tgt = rule->tgt; switch (rule->rule_kind) { case CIL_AVRULE_ALLOWED: kind = "allow"; break; case CIL_AVRULE_AUDITALLOW: kind = "auditallow"; break; case CIL_AVRULE_DONTAUDIT: kind = "dontaudit"; break; case CIL_AVRULE_NEVERALLOW: kind = "neverallow"; break; default: kind = "???"; break; } cil_list_init(&classperms_strs, CIL_LIST); cil_classperms_to_strings(rule->perms.classperms, classperms_strs); cil_list_for_each(i1, classperms_strs) { char *cp_str = i1->data; fprintf(out, "%s %s %s : %s;\n", kind, src->fqn, tgt->fqn, cp_str); free(cp_str); } cil_list_destroy(&classperms_strs, CIL_FALSE); } static void cil_type_rule_to_policy(FILE *out, struct cil_type_rule *rule) { const char *kind; struct cil_symtab_datum *src, *tgt, *res; struct cil_list *class_list; struct cil_list_item *i1; src = rule->src; tgt = rule->tgt; res = rule->result; switch (rule->rule_kind) { case CIL_TYPE_TRANSITION: kind = "type_transition"; break; case CIL_TYPE_MEMBER: kind = "type_member"; break; case CIL_TYPE_CHANGE: kind = "type_change"; break; default: kind = "???"; break; } class_list = cil_expand_class(rule->obj); cil_list_for_each(i1, class_list) { fprintf(out, "%s %s %s : %s %s;\n", kind, src->fqn, tgt->fqn, DATUM(i1->data)->fqn, res->fqn); } cil_list_destroy(&class_list, CIL_FALSE); } static void cil_nametypetransition_to_policy(FILE *out, struct cil_nametypetransition *trans) { struct cil_symtab_datum *src, *tgt, *name, *res; struct cil_list *class_list; struct cil_list_item *i1; src = trans->src; tgt = trans->tgt; name = trans->name; res = trans->result; class_list = cil_expand_class(trans->obj); cil_list_for_each(i1, class_list) { fprintf(out, "type_transition %s %s : %s %s \"%s\";\n", src->fqn, tgt->fqn, DATUM(i1->data)->fqn, res->fqn, name->fqn); } cil_list_destroy(&class_list, CIL_FALSE); } static void cil_rangetransition_to_policy(FILE *out, struct cil_rangetransition *trans) { struct cil_symtab_datum *src, *exec; struct cil_list *class_list; struct cil_list_item *i1; src = trans->src; exec = trans->exec; class_list = cil_expand_class(trans->obj); cil_list_for_each(i1, class_list) { fprintf(out, "range_transition %s %s : %s ", src->fqn, exec->fqn, DATUM(i1->data)->fqn); cil_levelrange_to_policy(out, trans->range); fprintf(out, ";\n"); } cil_list_destroy(&class_list, CIL_FALSE); } static void cil_typepermissive_to_policy(FILE *out, struct cil_typepermissive *rule) { fprintf(out, "permissive %s;\n", DATUM(rule->type)->fqn); } struct block_te_rules_extra { FILE *out; enum cil_flavor flavor; uint32_t rule_kind; }; static int __cil_block_te_rules_to_policy_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args) { struct block_te_rules_extra *args = extra_args; switch (node->flavor) { case CIL_BLOCK: { struct cil_block *blk = node->data; if (blk->is_abstract == CIL_TRUE) { *finished = CIL_TREE_SKIP_HEAD; } break; } case CIL_MACRO: *finished = CIL_TREE_SKIP_HEAD; break; case CIL_BOOLEANIF: *finished = CIL_TREE_SKIP_HEAD; break; case CIL_AVRULE: case CIL_AVRULEX: if (args->flavor == node->flavor) { struct cil_avrule *rule = node->data; if (args->rule_kind == rule->rule_kind) { if (rule->is_extended) { cil_av_rulex_to_policy(args->out, rule); } else { cil_av_rule_to_policy(args->out, rule); } } } break; case CIL_TYPE_RULE: if (args->flavor == node->flavor) { struct cil_type_rule *rule = node->data; if (args->rule_kind == rule->rule_kind) { cil_type_rule_to_policy(args->out, rule); } } break; case CIL_NAMETYPETRANSITION: if (args->flavor == node->flavor) { cil_nametypetransition_to_policy(args->out, node->data); } break; case CIL_RANGETRANSITION: if (args->flavor == node->flavor) { cil_rangetransition_to_policy(args->out, node->data); } break; case CIL_TYPEPERMISSIVE: if (args->flavor == node->flavor) { cil_typepermissive_to_policy(args->out, node->data); } break; default: break; } return SEPOL_OK; } static void cil_block_te_rules_to_policy(FILE *out, struct cil_tree_node *start, int mls) { struct block_te_rules_extra args; args.out = out; args.flavor = CIL_TYPEPERMISSIVE; args.rule_kind = 0; cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args); args.flavor = CIL_AVRULE; args.rule_kind = CIL_AVRULE_ALLOWED; cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args); args.rule_kind = CIL_AVRULE_AUDITALLOW; cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args); args.rule_kind = CIL_AVRULE_DONTAUDIT; cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args); args.rule_kind = CIL_AVRULE_NEVERALLOW; cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args); args.flavor = CIL_AVRULEX; args.rule_kind = CIL_AVRULE_ALLOWED; cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args); args.rule_kind = CIL_AVRULE_AUDITALLOW; cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args); args.rule_kind = CIL_AVRULE_DONTAUDIT; cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args); args.rule_kind = CIL_AVRULE_NEVERALLOW; cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args); args.flavor = CIL_TYPE_RULE; args.rule_kind = CIL_TYPE_TRANSITION; cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args); args.rule_kind = CIL_TYPE_MEMBER; cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args); args.rule_kind = CIL_TYPE_CHANGE; cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args); args.rule_kind = CIL_AVRULE_TYPE; cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args); args.flavor = CIL_NAMETYPETRANSITION; args.rule_kind = 0; cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args); if (mls == CIL_TRUE) { args.flavor = CIL_RANGETRANSITION; args.rule_kind = 0; cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args); } } struct te_rules_extra { FILE *out; int mls; }; static int __cil_te_rules_to_policy_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args) { struct te_rules_extra *args = extra_args; switch (node->flavor) { case CIL_BLOCK: { struct cil_block *blk = node->data; if (blk->is_abstract == CIL_TRUE) { *finished = CIL_TREE_SKIP_HEAD; } break; } case CIL_MACRO: *finished = CIL_TREE_SKIP_HEAD; break; case CIL_BOOLEANIF: { struct cil_booleanif *boolean = node->data; struct cil_tree_node *n; struct cil_condblock *cb; fprintf(args->out, "if "); cil_cond_expr_to_policy(args->out, boolean->datum_expr, CIL_TRUE); fprintf(args->out," {\n"); n = node->cl_head; cb = n != NULL ? n->data : NULL; if (cb && cb->flavor == CIL_CONDTRUE) { cil_block_te_rules_to_policy(args->out, n, args->mls); n = n->next; cb = n != NULL ? n->data : NULL; } if (cb && cb->flavor == CIL_CONDFALSE) { fprintf(args->out,"} else {\n"); cil_block_te_rules_to_policy(args->out, n, args->mls); } fprintf(args->out,"}\n"); *finished = CIL_TREE_SKIP_HEAD; break; } default: break; } return SEPOL_OK; } static void cil_te_rules_to_policy(FILE *out, struct cil_tree_node *head, int mls) { struct te_rules_extra args; args.out = out; args.mls = mls; cil_block_te_rules_to_policy(out, head, mls); cil_tree_walk(head, __cil_te_rules_to_policy_helper, NULL, NULL, &args); } static void cil_roles_to_policy(FILE *out, struct cil_list *rules) { struct cil_list_item *i1; struct cil_role *role; cil_list_for_each(i1, rules) { role = i1->data; if (strcmp(role->datum.fqn,"object_r") == 0) continue; fprintf(out, "role %s;\n", role->datum.fqn); } } static void cil_role_types_to_policy(FILE *out, struct cil_list *roles, struct cil_list *types) { struct cil_list_item *i1, *i2; struct cil_role *role; struct cil_type *type; int first = CIL_TRUE; cil_list_for_each(i1, roles) { role = i1->data; if (strcmp(role->datum.fqn,"object_r") == 0) continue; if (role->types) { cil_list_for_each(i2, types) { type = i2->data; if (ebitmap_get_bit(role->types, type->value)) { if (first) { fprintf(out, "role %s types { %s", role->datum.fqn, type->datum.fqn); first = CIL_FALSE; } else { fprintf(out, " %s", type->datum.fqn); } } } if (!first) { fprintf(out, " }"); first = CIL_TRUE; } fprintf(out, ";\n"); } } } static void cil_roleattributes_to_policy(FILE *out, struct cil_list *roles, struct cil_list *attributes) { struct cil_list_item *i1, *i2; struct cil_role *role; struct cil_roleattribute *attribute; int first = CIL_TRUE; cil_list_for_each(i1, roles) { role = i1->data; if (strcmp(role->datum.fqn,"object_r") == 0) continue; cil_list_for_each(i2, attributes) { attribute = i2->data; if (ebitmap_get_bit(attribute->roles, role->value)) { if (first) { fprintf(out, "roleattribute %s %s", role->datum.fqn, attribute->datum.fqn); first = CIL_FALSE; } else { fprintf(out, ", %s", attribute->datum.fqn); } } } if (!first) { fprintf(out, ";\n"); first = CIL_TRUE; } } } static void cil_roleallows_to_policy(FILE *out, struct cil_list *roleallows) { struct cil_list_item *i1; struct cil_roleallow *allow; cil_list_for_each(i1, roleallows) { allow = i1->data; fprintf(out, "allow %s %s;\n", DATUM(allow->src)->fqn, DATUM(allow->tgt)->fqn); } } static void cil_roletransitions_to_policy(FILE *out, struct cil_list *roletransitions) { struct cil_list_item *i1, *i2; struct cil_list *class_list; struct cil_roletransition *trans; cil_list_for_each(i1, roletransitions) { trans = i1->data; class_list = cil_expand_class(trans->obj); cil_list_for_each(i2, class_list) { fprintf(out, "role_transition %s %s : %s %s;\n", DATUM(trans->src)->fqn, DATUM(trans->tgt)->fqn, DATUM(i2->data)->fqn, DATUM(trans->result)->fqn); } cil_list_destroy(&class_list, CIL_FALSE); } } static void cil_users_to_policy(FILE *out, int mls, struct cil_list *users, struct cil_list *all_roles) { struct cil_list_item *i1, *i2; struct cil_user *user; struct cil_list *roles = NULL; struct cil_role *role; int num_roles; cil_list_for_each(i1, users) { user = i1->data; num_roles = 0; fprintf(out, "user %s",user->datum.fqn); cil_list_for_each(i2, all_roles) { role = i2->data; if (ebitmap_get_bit(user->roles, role->value)) { if (num_roles == 0) { cil_list_init(&roles, CIL_LIST); } cil_list_append(roles, CIL_ROLE, role); num_roles++; } } if (num_roles > 0) { fprintf(out, " roles"); if (num_roles > 1) { fprintf(out, " {"); } cil_list_for_each(i2, roles) { role = i2->data; fprintf(out, " %s", role->datum.fqn); } if (num_roles > 1) { fprintf(out, " }"); } cil_list_destroy(&roles, CIL_FALSE); } if (mls == CIL_TRUE && user->dftlevel != NULL) { fprintf(out, " level "); cil_level_to_policy(out, user->dftlevel); } if (mls == CIL_TRUE && user->range != NULL) { fprintf(out, " range "); cil_levelrange_to_policy(out, user->range); } fprintf(out,";\n"); } } static void cil_constrains_to_policy(FILE *out, struct cil_db *db, struct cil_list *constrains) { struct cil_list_item *i1, *i2; struct cil_constrain *cons; struct cil_list *classperms_strs; char *cp_str; char *expr_str; cil_list_for_each(i1, constrains) { cons = i1->data; cil_list_init(&classperms_strs, CIL_LIST); cil_classperms_to_strings(cons->classperms, classperms_strs); expr_str = cil_cons_expr_to_string(db, cons->datum_expr); cil_list_for_each(i2, classperms_strs) { cp_str = i2->data; fprintf(out, "constrain %s %s;\n",cp_str, expr_str); free(cp_str); } free(expr_str); cil_list_destroy(&classperms_strs, CIL_FALSE); } } static void cil_sid_contexts_to_policy(FILE *out, struct cil_list *sids, int mls) { struct cil_list_item *i1; struct cil_sid *sid; cil_list_for_each(i1, sids) { sid = i1->data; if (sid->context) { fprintf(out, "sid %s ", sid->datum.fqn); cil_context_to_policy(out, sid->context, mls); fprintf(out,"\n"); } } } static void cil_fsuses_to_policy(FILE *out, struct cil_sort *fsuses, int mls) { unsigned i; struct cil_fsuse *fsuse; for (i=0; icount; i++) { fsuse = fsuses->array[i]; if (fsuse->type == CIL_FSUSE_XATTR) { fprintf(out, "fs_use_xattr %s ", fsuse->fs_str); cil_context_to_policy(out, fsuse->context, mls); fprintf(out,";\n"); } } for (i=0; icount; i++) { fsuse = fsuses->array[i]; if (fsuse->type == CIL_FSUSE_TASK) { fprintf(out, "fs_use_task %s ", fsuse->fs_str); cil_context_to_policy(out, fsuse->context, mls); fprintf(out,";\n"); } } for (i=0; icount; i++) { fsuse = fsuses->array[i]; if (fsuse->type == CIL_FSUSE_TRANS) { fprintf(out, "fs_use_trans %s ", fsuse->fs_str); cil_context_to_policy(out, fsuse->context, mls); fprintf(out,";\n"); } } } static void cil_genfscons_to_policy(FILE *out, struct cil_sort *genfscons, int mls) { unsigned i; struct cil_genfscon *genfscon; for (i=0; icount; i++) { genfscon = genfscons->array[i]; fprintf(out, "genfscon %s %s ", genfscon->fs_str, genfscon->path_str); cil_context_to_policy(out, genfscon->context, mls); fprintf(out, "\n"); } } static void cil_ibpkeycons_to_policy(FILE *out, struct cil_sort *ibpkeycons, int mls) { uint32_t i = 0; for (i = 0; i < ibpkeycons->count; i++) { struct cil_ibpkeycon *ibpkeycon = (struct cil_ibpkeycon *)ibpkeycons->array[i]; fprintf(out, "ibpkeycon %s ", ibpkeycon->subnet_prefix_str); fprintf(out, "%d ", ibpkeycon->pkey_low); fprintf(out, "%d ", ibpkeycon->pkey_high); cil_context_to_policy(out, ibpkeycon->context, mls); fprintf(out, "\n"); } } static void cil_ibendportcons_to_policy(FILE *out, struct cil_sort *ibendportcons, int mls) { uint32_t i; for (i = 0; i < ibendportcons->count; i++) { struct cil_ibendportcon *ibendportcon = (struct cil_ibendportcon *)ibendportcons->array[i]; fprintf(out, "ibendportcon %s ", ibendportcon->dev_name_str); fprintf(out, "%u ", ibendportcon->port); cil_context_to_policy(out, ibendportcon->context, mls); fprintf(out, "\n"); } } static void cil_portcons_to_policy(FILE *out, struct cil_sort *portcons, int mls) { unsigned i; struct cil_portcon *portcon; for (i=0; icount; i++) { portcon = portcons->array[i]; fprintf(out, "portcon "); if (portcon->proto == CIL_PROTOCOL_UDP) { fprintf(out, "udp "); } else if (portcon->proto == CIL_PROTOCOL_TCP) { fprintf(out, "tcp "); } else if (portcon->proto == CIL_PROTOCOL_DCCP) { fprintf(out, "dccp "); } else if (portcon->proto == CIL_PROTOCOL_SCTP) { fprintf(out, "sctp "); } if (portcon->port_low == portcon->port_high) { fprintf(out, "%d ", portcon->port_low); } else { fprintf(out, "%d-%d ", portcon->port_low, portcon->port_high); } cil_context_to_policy(out, portcon->context, mls); fprintf(out, "\n"); } } static void cil_netifcons_to_policy(FILE *out, struct cil_sort *netifcons, int mls) { unsigned i; struct cil_netifcon *netifcon; for (i=0; icount; i++) { netifcon = netifcons->array[i]; fprintf(out, "netifcon %s ", netifcon->interface_str); cil_context_to_policy(out, netifcon->if_context, mls); fprintf(out, " "); cil_context_to_policy(out, netifcon->packet_context, mls); fprintf(out, "\n"); } } static void cil_nodecons_to_policy(FILE *out, struct cil_sort *nodecons, int mls) { unsigned i; struct cil_nodecon *nodecon; char *addr, *mask; for (i=0; icount; i++) { nodecon = nodecons->array[i]; fprintf(out, "nodecon "); if (nodecon->addr->family == AF_INET) { errno = 0; addr = cil_malloc(INET_ADDRSTRLEN); inet_ntop(nodecon->addr->family, &nodecon->addr->ip.v4, addr, INET_ADDRSTRLEN); if (errno == 0) { fprintf(out, "%s ",addr); } else { fprintf(out, "[INVALID] "); } free(addr); errno = 0; mask = cil_malloc(INET_ADDRSTRLEN); inet_ntop(nodecon->mask->family, &nodecon->mask->ip.v4, mask, INET_ADDRSTRLEN); if (errno == 0) { fprintf(out, "%s ",mask); } else { fprintf(out, "[INVALID] "); } free(mask); } else { errno = 0; addr = cil_malloc(INET6_ADDRSTRLEN); inet_ntop(nodecon->addr->family, &nodecon->addr->ip.v6, addr, INET6_ADDRSTRLEN); if (errno == 0) { fprintf(out, "%s ",addr); } else { fprintf(out, "[INVALID] "); } free(addr); errno = 0; mask = cil_malloc(INET6_ADDRSTRLEN); inet_ntop(nodecon->mask->family, &nodecon->mask->ip.v6, mask, INET6_ADDRSTRLEN); if (errno == 0) { fprintf(out, "%s ",mask); } else { fprintf(out, "[INVALID] "); } free(mask); } cil_context_to_policy(out, nodecon->context, mls); fprintf(out, "\n"); } } static void cil_pirqcons_to_policy(FILE *out, struct cil_sort *pirqcons, int mls) { unsigned i; struct cil_pirqcon *pirqcon; for (i = 0; icount; i++) { pirqcon = pirqcons->array[i]; fprintf(out, "pirqcon %d ", pirqcon->pirq); cil_context_to_policy(out, pirqcon->context, mls); fprintf(out, ";\n"); } } static void cil_iomemcons_to_policy(FILE *out, struct cil_sort *iomemcons, int mls) { unsigned i; struct cil_iomemcon *iomemcon; for (i = 0; icount; i++) { iomemcon = iomemcons->array[i]; if (iomemcon->iomem_low == iomemcon->iomem_high) { fprintf(out, "iomemcon %"PRIx64" ", iomemcon->iomem_low); } else { fprintf(out, "iomemcon %"PRIx64"-%"PRIx64" ", iomemcon->iomem_low, iomemcon->iomem_high); } cil_context_to_policy(out, iomemcon->context, mls); fprintf(out, ";\n"); } } static void cil_ioportcons_to_policy(FILE *out, struct cil_sort *ioportcons, int mls) { unsigned i; struct cil_ioportcon *ioportcon; for (i = 0; i < ioportcons->count; i++) { ioportcon = ioportcons->array[i]; fprintf(out, "ioportcon 0x%x-0x%x ", ioportcon->ioport_low, ioportcon->ioport_high); cil_context_to_policy(out, ioportcon->context, mls); fprintf(out, ";\n"); } } static void cil_pcidevicecons_to_policy(FILE *out, struct cil_sort *pcidevicecons, int mls) { unsigned i; struct cil_pcidevicecon *pcidevicecon; for (i = 0; i < pcidevicecons->count; i++) { pcidevicecon = pcidevicecons->array[i]; fprintf(out, "pcidevicecon 0x%x ", pcidevicecon->dev); cil_context_to_policy(out, pcidevicecon->context, mls); fprintf(out, ";\n"); } } static void cil_devicetreecons_to_policy(FILE *out, struct cil_sort *devicetreecons, int mls) { unsigned i; struct cil_devicetreecon *devicetreecon; for (i = 0; i < devicetreecons->count; i++) { devicetreecon = devicetreecons->array[i]; fprintf(out, "devicetreecon %s ", devicetreecon->path); cil_context_to_policy(out, devicetreecon->context, mls); fprintf(out, ";\n"); } } void cil_gen_policy(FILE *out, struct cil_db *db) { unsigned i; struct cil_tree_node *head = db->ast->root; struct cil_list *lists[CIL_LIST_NUM_LISTS]; for (i=0; iclassorder); cil_sid_decls_to_policy(out, db->sidorder); cil_commons_to_policy(out, lists[CIL_LIST_COMMON]); cil_classes_to_policy(out, db->classorder); cil_defaults_to_policy(out, lists[CIL_LIST_DEFAULT_USER], "default_user"); cil_defaults_to_policy(out, lists[CIL_LIST_DEFAULT_ROLE], "default_role"); cil_defaults_to_policy(out, lists[CIL_LIST_DEFAULT_TYPE], "default_type"); if (db->mls == CIL_TRUE) { cil_default_ranges_to_policy(out, lists[CIL_LIST_DEFAULT_RANGE]); cil_sensitivities_to_policy(out, db->sensitivityorder, lists[CIL_LIST_SENSALIAS]); cil_dominance_to_policy(out, db->sensitivityorder); cil_categories_to_policy(out, db->catorder, lists[CIL_LIST_CATALIAS]); cil_levels_to_policy(out, db->sensitivityorder); cil_mlsconstrains_to_policy(out, db, lists[CIL_LIST_MLSCONSTRAIN]); cil_validatetrans_to_policy(out, db, lists[CIL_LIST_MLSVALIDATETRANS], CIL_KEY_MLSVALIDATETRANS); } cil_simple_rules_to_policy(out, lists[CIL_LIST_POLICYCAP], CIL_KEY_POLICYCAP); cil_simple_rules_to_policy(out, lists[CIL_LIST_TYPEATTRIBUTE], "attribute"); cil_simple_rules_to_policy(out, lists[CIL_LIST_ROLEATTRIBUTE], "attribute_role"); cil_bools_to_policy(out, lists[CIL_LIST_BOOL]); cil_simple_rules_to_policy(out, lists[CIL_LIST_TYPE], "type"); cil_typealiases_to_policy(out, lists[CIL_LIST_TYPE], lists[CIL_LIST_TYPEALIAS]); cil_typebounds_to_policy(out, lists[CIL_LIST_TYPE]); cil_typeattributes_to_policy(out, lists[CIL_LIST_TYPE], lists[CIL_LIST_TYPEATTRIBUTE]); cil_te_rules_to_policy(out, head, db->mls); cil_roles_to_policy(out, lists[CIL_LIST_ROLE]); cil_role_types_to_policy(out, lists[CIL_LIST_ROLE], lists[CIL_LIST_TYPE]); cil_roleattributes_to_policy(out, lists[CIL_LIST_ROLE], lists[CIL_LIST_ROLEATTRIBUTE]); cil_roleallows_to_policy(out, lists[CIL_LIST_ROLEALLOW]); cil_roletransitions_to_policy(out, lists[CIL_LIST_ROLETRANSITION]); cil_users_to_policy(out, db->mls, lists[CIL_LIST_USER], lists[CIL_LIST_ROLE]); cil_constrains_to_policy(out, db, lists[CIL_LIST_CONSTRAINT]); cil_validatetrans_to_policy(out, db, lists[CIL_LIST_VALIDATETRANS], CIL_KEY_VALIDATETRANS); cil_sid_contexts_to_policy(out, db->sidorder, db->mls); cil_fsuses_to_policy(out, db->fsuse, db->mls); cil_genfscons_to_policy(out, db->genfscon, db->mls); cil_portcons_to_policy(out, db->portcon, db->mls); cil_netifcons_to_policy(out, db->netifcon, db->mls); cil_ibpkeycons_to_policy(out, db->ibpkeycon, db->mls); cil_ibendportcons_to_policy(out, db->ibendportcon, db->mls); cil_nodecons_to_policy(out, db->nodecon, db->mls); cil_pirqcons_to_policy(out, db->pirqcon, db->mls); cil_iomemcons_to_policy(out, db->iomemcon, db->mls); cil_ioportcons_to_policy(out, db->ioportcon, db->mls); cil_pcidevicecons_to_policy(out, db->pcidevicecon, db->mls); cil_devicetreecons_to_policy(out, db->devicetreecon, db->mls); for (i=0; i #include #include #include #include #include #include #include #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" #include "cil_deny.h" #define GEN_REQUIRE_ATTR "cil_gen_require" /* Also in libsepol/src/module_to_cil.c */ #define TYPEATTR_INFIX "_typeattr_" /* Also in libsepol/src/module_to_cil.c */ #define spaceship_cmp(a, b) (((a) > (b)) - ((a) < (b))) struct fc_data { unsigned int meta; size_t stem_len; size_t str_len; }; static int __cil_expr_to_bitmap(struct cil_list *expr, ebitmap_t *out, int max, struct cil_db *db); static int __cil_expr_list_to_bitmap(struct cil_list *expr_list, ebitmap_t *out, int max, struct cil_db *db); static int cats_compare(struct cil_cats *a, struct cil_cats *b) { struct cil_list_item *i, *j; int rc; if (a == b) return 0; if (!a) return -1; if (!b) return 1; /* Expects cat expression to have been evaluated */ cil_list_for_each(i, a->datum_expr) { cil_list_for_each(j, b->datum_expr) { rc = strcmp(DATUM(i->data)->fqn, DATUM(j->data)->fqn); if (!rc) return rc; } } return 0; } static int level_compare(struct cil_level *a, struct cil_level *b) { int rc; if (a == b) return 0; if (!a) return -1; if (!b) return 1; if (a->sens != b->sens) { rc = strcmp(DATUM(a->sens)->fqn, DATUM(b->sens)->fqn); if (rc != 0) return rc; } if (a->cats != b->cats) { return cats_compare(a->cats, b->cats); } return 0; } static int range_compare(struct cil_levelrange *a, struct cil_levelrange *b) { int rc; if (a == b) return 0; if (!a) return -1; if (!b) return 1; if (a->low != b->low) { rc = level_compare(a->low, b->low); if (rc != 0) return rc; } if (a->high != b->high) { return level_compare(a->high, b->high); } return 0; } static int context_compare(struct cil_context *a, struct cil_context *b) { int rc; if (a->user != b->user) { rc = strcmp(DATUM(a->user)->fqn, DATUM(b->user)->fqn); if (rc != 0) return rc; } if (a->role != b->role) { rc = strcmp(DATUM(a->role)->fqn, DATUM(b->role)->fqn); if (rc != 0) return rc; } if (a->type != b->type) { rc = strcmp(DATUM(a->type)->fqn, DATUM(b->type)->fqn); if (rc != 0) return rc; } if (a->range != b->range) { return range_compare(a->range, b->range); } return 0; } static int cil_verify_is_list(struct cil_list *list, enum cil_flavor flavor) { struct cil_list_item *curr; cil_list_for_each(curr, list) { switch (curr->flavor) { case CIL_LIST: return CIL_FALSE; break; case CIL_OP: return CIL_FALSE; break; default: if (flavor == CIL_CAT) { struct cil_symtab_datum *d = curr->data; struct cil_tree_node *n = d->nodes->head->data; if (n->flavor == CIL_CATSET) { return CIL_FALSE; } } break; } } return CIL_TRUE; } static void cil_post_fc_fill_data(struct fc_data *fc, const char *path) { size_t 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++; if (path[c] == '\0') { if (!fc->meta) { fc->stem_len++; } fc->str_len++; return; } /* FALLTHRU */ default: if (!fc->meta) { fc->stem_len++; } break; } fc->str_len++; c++; } } int cil_post_filecon_compare(const void *a, const void *b) { int rc = 0; struct cil_filecon *a_filecon = *(struct cil_filecon**)a; struct cil_filecon *b_filecon = *(struct cil_filecon**)b; struct fc_data *a_data = cil_malloc(sizeof(*a_data)); struct fc_data *b_data = cil_malloc(sizeof(*b_data)); char *a_path_str, *a_path, *b_path_str, *b_path; a_path_str = a_filecon->path ? DATUM(a_filecon->path)->fqn : a_filecon->path_str; b_path_str = b_filecon->path ? DATUM(b_filecon->path)->fqn : b_filecon->path_str; a_path = cil_malloc(strlen(a_path_str) + 1); b_path = cil_malloc(strlen(b_path_str) + 1); a_path[0] = '\0'; b_path[0] = '\0'; strcat(a_path, a_path_str); strcat(b_path, b_path_str); cil_post_fc_fill_data(a_data, a_path); cil_post_fc_fill_data(b_data, b_path); if (a_data->meta && !b_data->meta) { rc = -1; } else if (b_data->meta && !a_data->meta) { rc = 1; } else if (a_data->stem_len < b_data->stem_len) { rc = -1; } else if (b_data->stem_len < a_data->stem_len) { rc = 1; } else if (a_data->str_len < b_data->str_len) { rc = -1; } else if (b_data->str_len < a_data->str_len) { rc = 1; } else if (a_filecon->type < b_filecon->type) { rc = -1; } else if (b_filecon->type < a_filecon->type) { rc = 1; } else { rc = strcmp(a_path_str, b_path_str); } free(a_path); free(b_path); free(a_data); free(b_data); return rc; } int cil_post_ibpkeycon_compare(const void *a, const void *b) { int rc = SEPOL_ERR; struct cil_ibpkeycon *aibpkeycon = *(struct cil_ibpkeycon **)a; struct cil_ibpkeycon *bibpkeycon = *(struct cil_ibpkeycon **)b; rc = strcmp(aibpkeycon->subnet_prefix_str, bibpkeycon->subnet_prefix_str); if (rc) return rc; rc = spaceship_cmp(aibpkeycon->pkey_high - aibpkeycon->pkey_low, bibpkeycon->pkey_high - bibpkeycon->pkey_low); if (rc == 0) { if (aibpkeycon->pkey_low < bibpkeycon->pkey_low) rc = -1; else if (bibpkeycon->pkey_low < aibpkeycon->pkey_low) rc = 1; } return rc; } int cil_post_portcon_compare(const void *a, const void *b) { int rc = SEPOL_ERR; struct cil_portcon *aportcon = *(struct cil_portcon**)a; struct cil_portcon *bportcon = *(struct cil_portcon**)b; rc = spaceship_cmp(aportcon->port_high - aportcon->port_low, bportcon->port_high - bportcon->port_low); if (rc == 0) { if (aportcon->port_low < bportcon->port_low) { rc = -1; } else if (bportcon->port_low < aportcon->port_low) { rc = 1; } else if (aportcon->proto < bportcon->proto) { rc = -1; } else if (aportcon->proto > bportcon->proto) { rc = 1; } } return rc; } int cil_post_genfscon_compare(const void *a, const void *b) { int rc = SEPOL_ERR; struct cil_genfscon *agenfscon = *(struct cil_genfscon**)a; struct cil_genfscon *bgenfscon = *(struct cil_genfscon**)b; rc = strcmp(agenfscon->fs_str, bgenfscon->fs_str); if (rc == 0) { rc = strcmp(agenfscon->path_str, bgenfscon->path_str); } return rc; } int cil_post_netifcon_compare(const void *a, const void *b) { struct cil_netifcon *anetifcon = *(struct cil_netifcon**)a; struct cil_netifcon *bnetifcon = *(struct cil_netifcon**)b; return strcmp(anetifcon->interface_str, bnetifcon->interface_str); } int cil_post_ibendportcon_compare(const void *a, const void *b) { int rc = SEPOL_ERR; struct cil_ibendportcon *aibendportcon = *(struct cil_ibendportcon **)a; struct cil_ibendportcon *bibendportcon = *(struct cil_ibendportcon **)b; rc = strcmp(aibendportcon->dev_name_str, bibendportcon->dev_name_str); if (rc) return rc; if (aibendportcon->port < bibendportcon->port) return -1; else if (bibendportcon->port < aibendportcon->port) return 1; return rc; } int cil_post_nodecon_compare(const void *a, const void *b) { struct cil_nodecon *anodecon; struct cil_nodecon *bnodecon; anodecon = *(struct cil_nodecon**)a; bnodecon = *(struct cil_nodecon**)b; /* sort ipv4 before ipv6 */ if (anodecon->addr->family != bnodecon->addr->family) { if (anodecon->addr->family == AF_INET) { return -1; } else { return 1; } } /* most specific netmask goes first, then order by ip addr */ if (anodecon->addr->family == AF_INET) { int rc = memcmp(&anodecon->mask->ip.v4, &bnodecon->mask->ip.v4, sizeof(anodecon->mask->ip.v4)); if (rc != 0) { return -1 * rc; } return memcmp(&anodecon->addr->ip.v4, &bnodecon->addr->ip.v4, sizeof(anodecon->addr->ip.v4)); } else { int rc = memcmp(&anodecon->mask->ip.v6, &bnodecon->mask->ip.v6, sizeof(anodecon->mask->ip.v6)); if (rc != 0) { return -1 * rc; } return memcmp(&anodecon->addr->ip.v6, &bnodecon->addr->ip.v6, sizeof(anodecon->addr->ip.v6)); } } static 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; } static 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 = spaceship_cmp(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; } static 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 = spaceship_cmp(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; } static 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; } static int cil_post_devicetreecon_compare(const void *a, const void *b) { int rc = SEPOL_ERR; struct cil_devicetreecon *adevicetreecon = *(struct cil_devicetreecon**)a; struct cil_devicetreecon *bdevicetreecon = *(struct cil_devicetreecon**)b; rc = strcmp(adevicetreecon->path, bdevicetreecon->path); return rc; } int cil_post_fsuse_compare(const void *a, const void *b) { int rc; struct cil_fsuse *afsuse; struct cil_fsuse *bfsuse; afsuse = *(struct cil_fsuse**)a; bfsuse = *(struct cil_fsuse**)b; if (afsuse->type < bfsuse->type) { rc = -1; } else if (bfsuse->type < afsuse->type) { rc = 1; } else { rc = strcmp(afsuse->fs_str, bfsuse->fs_str); } return rc; } static int cil_post_filecon_context_compare(const void *a, const void *b) { struct cil_filecon *a_filecon = *(struct cil_filecon**)a; struct cil_filecon *b_filecon = *(struct cil_filecon**)b; return context_compare(a_filecon->context, b_filecon->context); } static int cil_post_ibpkeycon_context_compare(const void *a, const void *b) { struct cil_ibpkeycon *a_ibpkeycon = *(struct cil_ibpkeycon **)a; struct cil_ibpkeycon *b_ibpkeycon = *(struct cil_ibpkeycon **)b; return context_compare(a_ibpkeycon->context, b_ibpkeycon->context); } static int cil_post_portcon_context_compare(const void *a, const void *b) { struct cil_portcon *a_portcon = *(struct cil_portcon**)a; struct cil_portcon *b_portcon = *(struct cil_portcon**)b; return context_compare(a_portcon->context, b_portcon->context); } static int cil_post_genfscon_context_compare(const void *a, const void *b) { struct cil_genfscon *a_genfscon = *(struct cil_genfscon**)a; struct cil_genfscon *b_genfscon = *(struct cil_genfscon**)b; return context_compare(a_genfscon->context, b_genfscon->context); } static int cil_post_netifcon_context_compare(const void *a, const void *b) { int rc; struct cil_netifcon *a_netifcon = *(struct cil_netifcon**)a; struct cil_netifcon *b_netifcon = *(struct cil_netifcon**)b; rc = context_compare(a_netifcon->if_context, b_netifcon->if_context); if (rc != 0) { return rc; } return context_compare(a_netifcon->packet_context, b_netifcon->packet_context); } static int cil_post_ibendportcon_context_compare(const void *a, const void *b) { struct cil_ibendportcon *a_ibendportcon = *(struct cil_ibendportcon **)a; struct cil_ibendportcon *b_ibendportcon = *(struct cil_ibendportcon **)b; return context_compare(a_ibendportcon->context, b_ibendportcon->context); } static int cil_post_nodecon_context_compare(const void *a, const void *b) { struct cil_nodecon *a_nodecon = *(struct cil_nodecon **)a; struct cil_nodecon *b_nodecon = *(struct cil_nodecon **)b; return context_compare(a_nodecon->context, b_nodecon->context); } static int cil_post_pirqcon_context_compare(const void *a, const void *b) { struct cil_pirqcon *a_pirqcon = *(struct cil_pirqcon**)a; struct cil_pirqcon *b_pirqcon = *(struct cil_pirqcon**)b; return context_compare(a_pirqcon->context, b_pirqcon->context); } static int cil_post_iomemcon_context_compare(const void *a, const void *b) { struct cil_iomemcon *a_iomemcon = *(struct cil_iomemcon**)a; struct cil_iomemcon *b_iomemcon = *(struct cil_iomemcon**)b; return context_compare(a_iomemcon->context, b_iomemcon->context); } static int cil_post_ioportcon_context_compare(const void *a, const void *b) { struct cil_ioportcon *a_ioportcon = *(struct cil_ioportcon**)a; struct cil_ioportcon *b_ioportcon = *(struct cil_ioportcon**)b; return context_compare(a_ioportcon->context, b_ioportcon->context); } static int cil_post_pcidevicecon_context_compare(const void *a, const void *b) { struct cil_pcidevicecon *a_pcidevicecon = *(struct cil_pcidevicecon**)a; struct cil_pcidevicecon *b_pcidevicecon = *(struct cil_pcidevicecon**)b; return context_compare(a_pcidevicecon->context, b_pcidevicecon->context); } static int cil_post_devicetreecon_context_compare(const void *a, const void *b) { struct cil_devicetreecon *a_devicetreecon = *(struct cil_devicetreecon**)a; struct cil_devicetreecon *b_devicetreecon = *(struct cil_devicetreecon**)b; return context_compare(a_devicetreecon->context, b_devicetreecon->context); } static int cil_post_fsuse_context_compare(const void *a, const void *b) { struct cil_fsuse *a_fsuse = *(struct cil_fsuse**)a; struct cil_fsuse *b_fsuse = *(struct cil_fsuse**)b; return context_compare(a_fsuse->context, b_fsuse->context); } static int __cil_post_db_count_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args) { struct cil_db *db = extra_args; switch(node->flavor) { case CIL_BLOCK: { struct cil_block *blk = node->data; if (blk->is_abstract == CIL_TRUE) { *finished = CIL_TREE_SKIP_HEAD; } break; } case CIL_MACRO: *finished = CIL_TREE_SKIP_HEAD; break; case CIL_CLASS: { struct cil_class *class = node->data; if (class->datum.nodes->head->data == node) { // Multiple nodes can point to the same datum. Only count once. db->num_classes++; } break; } case CIL_TYPE: { struct cil_type *type = node->data; if (type->datum.nodes->head->data == node) { // Multiple nodes can point to the same datum. Only count once. type->value = db->num_types; db->num_types++; db->num_types_and_attrs++; } break; } case CIL_TYPEATTRIBUTE: { struct cil_typeattribute *attr = node->data; if (attr->datum.nodes->head->data == node) { // Multiple nodes can point to the same datum. Only count once. db->num_types_and_attrs++; } break; } case CIL_ROLE: { struct cil_role *role = node->data; if (role->datum.nodes->head->data == node) { // Multiple nodes can point to the same datum. Only count once. role->value = db->num_roles; db->num_roles++; } break; } case CIL_USER: { struct cil_user *user = node->data; if (user->datum.nodes->head->data == node) { // multiple AST nodes can point to the same cil_user data (like if // copied from a macro). This check ensures we only count the // duplicates once user->value = db->num_users; db->num_users++; } break; } case CIL_NETIFCON: db->netifcon->count++; break; case CIL_GENFSCON: db->genfscon->count++; break; case CIL_FILECON: db->filecon->count++; break; case CIL_NODECON: db->nodecon->count++; break; case CIL_IBPKEYCON: db->ibpkeycon->count++; break; case CIL_IBENDPORTCON: db->ibendportcon->count++; break; case CIL_PORTCON: db->portcon->count++; break; case CIL_PIRQCON: db->pirqcon->count++; break; case CIL_IOMEMCON: db->iomemcon->count++; break; case CIL_IOPORTCON: db->ioportcon->count++; break; case CIL_PCIDEVICECON: db->pcidevicecon->count++; break; case CIL_DEVICETREECON: db->devicetreecon->count++; break; case CIL_FSUSE: db->fsuse->count++; break; default: break; } return SEPOL_OK; } static int __cil_post_db_array_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args) { struct cil_db *db = extra_args; switch(node->flavor) { case CIL_BLOCK: { struct cil_block *blk = node->data; if (blk->is_abstract == CIL_TRUE) { *finished = CIL_TREE_SKIP_HEAD; } break; } case CIL_MACRO: *finished = CIL_TREE_SKIP_HEAD; break; case CIL_TYPE: { struct cil_type *type = node->data; if (db->val_to_type == NULL) { db->val_to_type = cil_malloc(sizeof(*db->val_to_type) * db->num_types); } db->val_to_type[type->value] = type; break; } case CIL_ROLE: { struct cil_role *role = node->data; if (db->val_to_role == NULL) { db->val_to_role = cil_malloc(sizeof(*db->val_to_role) * db->num_roles); } db->val_to_role[role->value] = role; break; } case CIL_USER: { struct cil_user *user= node->data; if (db->val_to_user == NULL) { db->val_to_user = cil_malloc(sizeof(*db->val_to_user) * db->num_users); } db->val_to_user[user->value] = user; break; } case CIL_USERPREFIX: { cil_list_append(db->userprefixes, CIL_USERPREFIX, node->data); break; } case CIL_SELINUXUSER: { cil_list_prepend(db->selinuxusers, CIL_SELINUXUSER, node->data); break; } case CIL_SELINUXUSERDEFAULT: { cil_list_append(db->selinuxusers, CIL_SELINUXUSERDEFAULT, node->data); break; } case CIL_NETIFCON: { struct cil_sort *sort = db->netifcon; uint32_t count = sort->count; uint32_t i = sort->index; if (sort->array == NULL) { sort->array = cil_malloc(sizeof(*sort->array)*count); } sort->array[i] = node->data; sort->index++; break; } case CIL_IBENDPORTCON: { struct cil_sort *sort = db->ibendportcon; uint32_t count = sort->count; uint32_t i = sort->index; if (!sort->array) sort->array = cil_malloc(sizeof(*sort->array) * count); sort->array[i] = node->data; sort->index++; break; } case CIL_FSUSE: { struct cil_sort *sort = db->fsuse; uint32_t count = sort->count; uint32_t i = sort->index; if (sort->array == NULL) { sort->array = cil_malloc(sizeof(*sort->array)*count); } sort->array[i] = node->data; sort->index++; break; } case CIL_GENFSCON: { struct cil_sort *sort = db->genfscon; uint32_t count = sort->count; uint32_t i = sort->index; if (sort->array == NULL) { sort->array = cil_malloc(sizeof(*sort->array)*count); } sort->array[i] = node->data; sort->index++; break; } case CIL_FILECON: { struct cil_sort *sort = db->filecon; uint32_t count = sort->count; uint32_t i = sort->index; if (sort->array == NULL) { sort->array = cil_malloc(sizeof(*sort->array)*count); } sort->array[i] = node->data; sort->index++; break; } case CIL_NODECON: { struct cil_sort *sort = db->nodecon; uint32_t count = sort->count; uint32_t i = sort->index; if (sort->array == NULL) { sort->array = cil_malloc(sizeof(*sort->array)*count); } sort->array[i] = node->data; sort->index++; break; } case CIL_IBPKEYCON: { struct cil_sort *sort = db->ibpkeycon; uint32_t count = sort->count; uint32_t i = sort->index; if (!sort->array) sort->array = cil_malloc(sizeof(*sort->array) * count); sort->array[i] = node->data; sort->index++; break; } case CIL_PORTCON: { struct cil_sort *sort = db->portcon; uint32_t count = sort->count; uint32_t i = sort->index; if (sort->array == NULL) { sort->array = cil_malloc(sizeof(*sort->array)*count); } sort->array[i] = node->data; sort->index++; break; } case CIL_PIRQCON: { struct cil_sort *sort = db->pirqcon; uint32_t count = sort->count; uint32_t i = sort->index; if (sort->array == NULL) { sort->array = cil_malloc(sizeof(*sort->array)*count); } sort->array[i] = node->data; sort->index++; break; } case CIL_IOMEMCON: { struct cil_sort *sort = db->iomemcon; uint32_t count = sort->count; uint32_t i = sort->index; if (sort->array == NULL) { sort->array = cil_malloc(sizeof(*sort->array)*count); } sort->array[i] = node->data; sort->index++; break; } case CIL_IOPORTCON: { struct cil_sort *sort = db->ioportcon; uint32_t count = sort->count; uint32_t i = sort->index; if (sort->array == NULL) { sort->array = cil_malloc(sizeof(*sort->array)*count); } sort->array[i] = node->data; sort->index++; break; } case CIL_PCIDEVICECON: { struct cil_sort *sort = db->pcidevicecon; uint32_t count = sort->count; uint32_t i = sort->index; if (sort->array == NULL) { sort->array = cil_malloc(sizeof(*sort->array)*count); } sort->array[i] = node->data; sort->index++; break; } case CIL_DEVICETREECON: { struct cil_sort *sort = db->devicetreecon; uint32_t count = sort->count; uint32_t i = sort->index; if (sort->array == NULL) { sort->array = cil_malloc(sizeof(*sort->array)*count); } sort->array[i] = node->data; sort->index++; break; } default: break; } return SEPOL_OK; } static int __evaluate_type_expression(struct cil_typeattribute *attr, struct cil_db *db) { int rc; attr->types = cil_malloc(sizeof(*attr->types)); rc = __cil_expr_list_to_bitmap(attr->expr_list, attr->types, db->num_types, db); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Failed to expand type attribute to bitmap\n"); ebitmap_destroy(attr->types); free(attr->types); attr->types = NULL; } return rc; } static int __cil_type_to_bitmap(struct cil_symtab_datum *datum, ebitmap_t *bitmap, struct cil_db *db) { int rc = SEPOL_ERR; struct cil_tree_node *node = datum->nodes->head->data; ebitmap_init(bitmap); if (node->flavor == CIL_TYPEATTRIBUTE) { struct cil_typeattribute *attr = (struct cil_typeattribute *)datum; if (attr->types == NULL) { rc = __evaluate_type_expression(attr, db); if (rc != SEPOL_OK) goto exit; } ebitmap_union(bitmap, attr->types); } else if (node->flavor == CIL_TYPEALIAS) { struct cil_alias *alias = (struct cil_alias *)datum; struct cil_type *type = alias->actual; if (ebitmap_set_bit(bitmap, type->value, 1)) { cil_log(CIL_ERR, "Failed to set type bit\n"); ebitmap_destroy(bitmap); goto exit; } } else { struct cil_type *type = (struct cil_type *)datum; if (ebitmap_set_bit(bitmap, type->value, 1)) { cil_log(CIL_ERR, "Failed to set type bit\n"); ebitmap_destroy(bitmap); goto exit; } } return SEPOL_OK; exit: return rc; } static int __evaluate_user_expression(struct cil_userattribute *attr, struct cil_db *db) { int rc; attr->users = cil_malloc(sizeof(*attr->users)); rc = __cil_expr_list_to_bitmap(attr->expr_list, attr->users, db->num_users, db); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Failed to expand user attribute to bitmap\n"); ebitmap_destroy(attr->users); free(attr->users); attr->users = NULL; } return rc; } static int __cil_user_to_bitmap(struct cil_symtab_datum *datum, ebitmap_t *bitmap, struct cil_db *db) { int rc = SEPOL_ERR; struct cil_tree_node *node = datum->nodes->head->data; struct cil_userattribute *attr = NULL; struct cil_user *user = NULL; ebitmap_init(bitmap); if (node->flavor == CIL_USERATTRIBUTE) { attr = (struct cil_userattribute *)datum; if (attr->users == NULL) { rc = __evaluate_user_expression(attr, db); if (rc != SEPOL_OK) { goto exit; } } ebitmap_union(bitmap, attr->users); } else { user = (struct cil_user *)datum; if (ebitmap_set_bit(bitmap, user->value, 1)) { cil_log(CIL_ERR, "Failed to set user bit\n"); ebitmap_destroy(bitmap); goto exit; } } return SEPOL_OK; exit: return rc; } static int __evaluate_role_expression(struct cil_roleattribute *attr, struct cil_db *db) { int rc; attr->roles = cil_malloc(sizeof(*attr->roles)); rc = __cil_expr_list_to_bitmap(attr->expr_list, attr->roles, db->num_roles, db); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Failed to expand role attribute to bitmap\n"); ebitmap_destroy(attr->roles); free(attr->roles); attr->roles = NULL; } return rc; } static int __cil_role_to_bitmap(struct cil_symtab_datum *datum, ebitmap_t *bitmap, struct cil_db *db) { int rc = SEPOL_ERR; struct cil_tree_node *node = datum->nodes->head->data; ebitmap_init(bitmap); if (node->flavor == CIL_ROLEATTRIBUTE) { struct cil_roleattribute *attr = (struct cil_roleattribute *)datum; if (attr->roles == NULL) { rc = __evaluate_role_expression(attr, db); if (rc != SEPOL_OK) goto exit; } ebitmap_union(bitmap, attr->roles); } else { struct cil_role *role = (struct cil_role *)datum; if (ebitmap_set_bit(bitmap, role->value, 1)) { cil_log(CIL_ERR, "Failed to set role bit\n"); ebitmap_destroy(bitmap); goto exit; } } return SEPOL_OK; exit: return rc; } static int __evaluate_permissionx_expression(struct cil_permissionx *permx, struct cil_db *db) { int rc; permx->perms = cil_malloc(sizeof(*permx->perms)); ebitmap_init(permx->perms); rc = __cil_expr_to_bitmap(permx->expr_str, permx->perms, 0x10000, db); // max is one more than 0xFFFF if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Failed to expand permissionx expression\n"); ebitmap_destroy(permx->perms); free(permx->perms); permx->perms = NULL; } return rc; } static int __cil_permx_str_to_int(char *permx_str, uint16_t *val) { char *endptr = NULL; long lval = strtol(permx_str, &endptr, 0); if (*endptr != '\0') { cil_log(CIL_ERR, "permissionx value %s not valid number\n", permx_str); goto exit; } if (lval < 0x0000 || lval > 0xFFFF) { cil_log(CIL_ERR, "permissionx value %s must be between 0x0000 and 0xFFFF\n", permx_str); goto exit; } *val = (uint16_t)lval; return SEPOL_OK; exit: return SEPOL_ERR; } static int __cil_permx_to_bitmap(struct cil_symtab_datum *datum, ebitmap_t *bitmap, __attribute__((unused)) struct cil_db *db) { int rc = SEPOL_ERR; uint16_t val; rc = __cil_permx_str_to_int((char*)datum, &val); if (rc != SEPOL_OK) { goto exit; } ebitmap_init(bitmap); if (ebitmap_set_bit(bitmap, (unsigned int)val, 1)) { cil_log(CIL_ERR, "Failed to set permissionx bit\n"); ebitmap_destroy(bitmap); goto exit; } return SEPOL_OK; exit: return rc; } static int __cil_perm_to_bitmap(struct cil_symtab_datum *datum, ebitmap_t *bitmap, __attribute__((unused)) struct cil_db *db) { struct cil_perm *perm = (struct cil_perm *)datum; unsigned int value = perm->value; ebitmap_init(bitmap); if (ebitmap_set_bit(bitmap, value, 1)) { cil_log(CIL_INFO, "Failed to set perm bit\n"); ebitmap_destroy(bitmap); return SEPOL_ERR; } return SEPOL_OK; } static int __evaluate_cat_expression(struct cil_cats *cats, struct cil_db *db) { int rc = SEPOL_ERR; ebitmap_t bitmap; struct cil_list *new; struct cil_list_item *curr; if (cats->evaluated == CIL_TRUE) { return SEPOL_OK; } if (cil_verify_is_list(cats->datum_expr, CIL_CAT)) { return SEPOL_OK; } ebitmap_init(&bitmap); rc = __cil_expr_to_bitmap(cats->datum_expr, &bitmap, db->num_cats, db); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Failed to expand category expression to bitmap\n"); ebitmap_destroy(&bitmap); goto exit; } cil_list_init(&new, CIL_CAT); cil_list_for_each(curr, db->catorder) { struct cil_cat *cat = curr->data; if (ebitmap_get_bit(&bitmap, cat->value)) { cil_list_append(new, CIL_DATUM, cat); } } ebitmap_destroy(&bitmap); cil_list_destroy(&cats->datum_expr, CIL_FALSE); cats->datum_expr = new; cats->evaluated = CIL_TRUE; return SEPOL_OK; exit: return rc; } static int __cil_cat_to_bitmap(struct cil_symtab_datum *datum, ebitmap_t *bitmap, struct cil_db *db) { int rc = SEPOL_ERR; struct cil_tree_node *node = datum->nodes->head->data; ebitmap_init(bitmap); if (node->flavor == CIL_CATSET) { struct cil_catset *catset = (struct cil_catset *)datum; struct cil_list_item *curr; if (catset->cats->evaluated == CIL_FALSE) { rc = __evaluate_cat_expression(catset->cats, db); if (rc != SEPOL_OK) goto exit; } for (curr = catset->cats->datum_expr->head; curr; curr = curr->next) { struct cil_cat *cat = (struct cil_cat *)curr->data; if (ebitmap_set_bit(bitmap, cat->value, 1)) { cil_log(CIL_ERR, "Failed to set cat bit\n"); ebitmap_destroy(bitmap); goto exit; } } } else if (node->flavor == CIL_CATALIAS) { struct cil_alias *alias = (struct cil_alias *)datum; struct cil_cat *cat = alias->actual; if (ebitmap_set_bit(bitmap, cat->value, 1)) { cil_log(CIL_ERR, "Failed to set cat bit\n"); ebitmap_destroy(bitmap); goto exit; } } else { struct cil_cat *cat = (struct cil_cat *)datum; if (ebitmap_set_bit(bitmap, cat->value, 1)) { cil_log(CIL_ERR, "Failed to set cat bit\n"); ebitmap_destroy(bitmap); goto exit; } } return SEPOL_OK; exit: return rc; } static int __cil_cat_expr_range_to_bitmap_helper(struct cil_list_item *i1, struct cil_list_item *i2, ebitmap_t *bitmap) { int rc = SEPOL_ERR; struct cil_symtab_datum *d1 = i1->data; struct cil_symtab_datum *d2 = i2->data; struct cil_tree_node *n1 = d1->nodes->head->data; struct cil_tree_node *n2 = d2->nodes->head->data; struct cil_cat *c1 = (struct cil_cat *)d1; struct cil_cat *c2 = (struct cil_cat *)d2; if (n1->flavor == CIL_CATSET || n2->flavor == CIL_CATSET) { cil_log(CIL_ERR, "Category sets cannot be used in a category range\n"); goto exit; } if (n1->flavor == CIL_CATALIAS) { struct cil_alias *alias = (struct cil_alias *)d1; c1 = alias->actual; } if (n2->flavor == CIL_CATALIAS) { struct cil_alias *alias = (struct cil_alias *)d2; c2 = alias->actual; } if (c1->value > c2->value) { cil_log(CIL_ERR, "Invalid category range\n"); goto exit; } if (ebitmap_init_range(bitmap, c1->value, c2->value)) { cil_log(CIL_ERR, "Failed to set cat bit\n"); ebitmap_destroy(bitmap); goto exit; } return SEPOL_OK; exit: return rc; } static int __cil_permissionx_expr_range_to_bitmap_helper(struct cil_list_item *i1, struct cil_list_item *i2, ebitmap_t *bitmap) { int rc = SEPOL_ERR; char *p1 = i1->data; char *p2 = i2->data; uint16_t v1; uint16_t v2; rc = __cil_permx_str_to_int(p1, &v1); if (rc != SEPOL_OK) { goto exit; } rc = __cil_permx_str_to_int(p2, &v2); if (rc != SEPOL_OK) { goto exit; } if (ebitmap_init_range(bitmap, v1, v2)) { cil_log(CIL_ERR, "Failed to set permissionx bits\n"); ebitmap_destroy(bitmap); goto exit; } return SEPOL_OK; exit: return rc; } static int __cil_expr_to_bitmap_helper(struct cil_list_item *curr, enum cil_flavor flavor, ebitmap_t *bitmap, int max, struct cil_db *db) { int rc = SEPOL_ERR; if (curr->flavor == CIL_DATUM) { switch (flavor) { case CIL_TYPE: rc = __cil_type_to_bitmap(curr->data, bitmap, db); break; case CIL_ROLE: rc = __cil_role_to_bitmap(curr->data, bitmap, db); break; case CIL_USER: rc = __cil_user_to_bitmap(curr->data, bitmap, db); break; case CIL_PERM: rc = __cil_perm_to_bitmap(curr->data, bitmap, db); break; case CIL_CAT: rc = __cil_cat_to_bitmap(curr->data, bitmap, db); break; default: rc = SEPOL_ERR; } } else if (curr->flavor == CIL_LIST) { struct cil_list *l = curr->data; ebitmap_init(bitmap); rc = __cil_expr_to_bitmap(l, bitmap, max, db); if (rc != SEPOL_OK) { ebitmap_destroy(bitmap); } } else if (flavor == CIL_PERMISSIONX) { // permissionx expressions aren't resolved into anything, so curr->flavor // is just a CIL_STRING, not a CIL_DATUM, so just check on flavor for those rc = __cil_permx_to_bitmap(curr->data, bitmap, db); } return rc; } static int __cil_expr_to_bitmap(struct cil_list *expr, ebitmap_t *out, int max, struct cil_db *db) { int rc = SEPOL_ERR; struct cil_list_item *curr; enum cil_flavor flavor; ebitmap_t tmp, b1, b2; if (expr == NULL || expr->head == NULL) { return SEPOL_OK; } curr = expr->head; flavor = expr->flavor; ebitmap_init(&tmp); if (curr->flavor == CIL_OP) { enum cil_flavor op = (enum cil_flavor)(uintptr_t)curr->data; if (op == CIL_ALL) { rc = ebitmap_init_range(&tmp, 0, max - 1); 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) { rc = __cil_cat_expr_range_to_bitmap_helper(curr->next, curr->next->next, &tmp); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "Failed to expand category range\n"); goto exit; } } else if (flavor == CIL_PERMISSIONX) { rc = __cil_permissionx_expr_range_to_bitmap_helper(curr->next, curr->next->next, &tmp); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "Failed to expand category range\n"); goto exit; } } else { cil_log(CIL_INFO, "Range operation only supported for categories permissionx\n"); rc = SEPOL_ERR; goto exit; } } else { rc = __cil_expr_to_bitmap_helper(curr->next, flavor, &b1, max, db); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "Failed to get first operand bitmap\n"); goto exit; } if (op == CIL_NOT) { rc = ebitmap_not(&tmp, &b1, max); ebitmap_destroy(&b1); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "Failed to NOT bitmap\n"); ebitmap_destroy(&tmp); goto exit; } } else { rc = __cil_expr_to_bitmap_helper(curr->next->next, flavor, &b2, max, db); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "Failed to get second operand bitmap\n"); ebitmap_destroy(&b1); goto exit; } if (op == CIL_OR) { rc = ebitmap_or(&tmp, &b1, &b2); } else if (op == CIL_AND) { rc = ebitmap_and(&tmp, &b1, &b2); } else if (op == CIL_XOR) { rc = ebitmap_xor(&tmp, &b1, &b2); } else { rc = SEPOL_ERR; } ebitmap_destroy(&b1); ebitmap_destroy(&b2); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "Failed to apply operator to bitmaps\n"); ebitmap_destroy(&tmp); goto exit; } } } } else { ebitmap_init(&tmp); for (;curr; curr = curr->next) { rc = __cil_expr_to_bitmap_helper(curr, flavor, &b2, max, db); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "Failed to get operand in list\n"); ebitmap_destroy(&tmp); goto exit; } b1 = tmp; rc = ebitmap_or(&tmp, &b1, &b2); ebitmap_destroy(&b1); ebitmap_destroy(&b2); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "Failed to OR operands in list\n"); ebitmap_destroy(&tmp); goto exit; } } } ebitmap_union(out, &tmp); ebitmap_destroy(&tmp); return SEPOL_OK; exit: return rc; } static int __cil_expr_list_to_bitmap(struct cil_list *expr_list, ebitmap_t *out, int max, struct cil_db *db) { int rc = SEPOL_ERR; struct cil_list_item *expr; ebitmap_init(out); if (expr_list == NULL) { return SEPOL_OK; } cil_list_for_each(expr, expr_list) { ebitmap_t bitmap; struct cil_list *l = (struct cil_list *)expr->data; ebitmap_init(&bitmap); rc = __cil_expr_to_bitmap(l, &bitmap, max, db); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "Failed to expand expression list to bitmap\n"); ebitmap_destroy(&bitmap); goto exit; } ebitmap_union(out, &bitmap); ebitmap_destroy(&bitmap); } return SEPOL_OK; exit: return SEPOL_ERR; } static int cil_typeattribute_used(struct cil_typeattribute *attr, struct cil_db *db) { if (!attr->used) { return CIL_FALSE; } if (attr->used & CIL_ATTR_EXPAND_FALSE) { return CIL_TRUE; } if (attr->used & CIL_ATTR_EXPAND_TRUE) { return CIL_FALSE; } if (attr->used & CIL_ATTR_CONSTRAINT) { return CIL_TRUE; } if (db->attrs_expand_generated || attr->used == CIL_ATTR_NEVERALLOW) { if (strcmp(DATUM(attr)->name, GEN_REQUIRE_ATTR) == 0) { return CIL_FALSE; } else if (strstr(DATUM(attr)->name, TYPEATTR_INFIX) != NULL) { return CIL_FALSE; } if (attr->used == CIL_ATTR_NEVERALLOW) { return CIL_TRUE; } } if (attr->used == CIL_ATTR_AVRULE) { if (ebitmap_cardinality(attr->types) < db->attrs_expand_size) { return CIL_FALSE; } } return CIL_TRUE; } static void __mark_neverallow_attrs(struct cil_list *expr_list) { struct cil_list_item *curr; if (!expr_list) { return; } cil_list_for_each(curr, expr_list) { if (curr->flavor == CIL_DATUM) { if (FLAVOR(curr->data) == CIL_TYPEATTRIBUTE) { struct cil_typeattribute *attr = curr->data; if (strstr(DATUM(attr)->name, TYPEATTR_INFIX)) { __mark_neverallow_attrs(attr->expr_list); } else { attr->used |= CIL_ATTR_NEVERALLOW; } } } else if (curr->flavor == CIL_LIST) { __mark_neverallow_attrs(curr->data); } } } static int __cil_post_db_neverallow_attr_helper(struct cil_tree_node *node, uint32_t *finished, __attribute__((unused)) void *extra_args) { switch (node->flavor) { case CIL_BLOCK: { struct cil_block *blk = node->data; if (blk->is_abstract == CIL_TRUE) { *finished = CIL_TREE_SKIP_HEAD; } break; } case CIL_MACRO: { *finished = CIL_TREE_SKIP_HEAD; break; } case CIL_TYPEATTRIBUTE: { struct cil_typeattribute *attr = node->data; if ((attr->used & CIL_ATTR_NEVERALLOW) && strstr(DATUM(attr)->name, TYPEATTR_INFIX)) { __mark_neverallow_attrs(attr->expr_list); } break; } default: break; } return SEPOL_OK; } static int __cil_post_db_attr_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args) { int rc = SEPOL_ERR; struct cil_db *db = extra_args; switch (node->flavor) { case CIL_BLOCK: { struct cil_block *blk = node->data; if (blk->is_abstract == CIL_TRUE) { *finished = CIL_TREE_SKIP_HEAD; } break; } case CIL_MACRO: { *finished = CIL_TREE_SKIP_HEAD; break; } case CIL_TYPEATTRIBUTE: { struct cil_typeattribute *attr = node->data; if (attr->types == NULL) { rc = __evaluate_type_expression(attr, db); if (rc != SEPOL_OK) goto exit; } attr->keep = cil_typeattribute_used(attr, db); break; } case CIL_ROLEATTRIBUTE: { struct cil_roleattribute *attr = node->data; if (attr->roles == NULL) { rc = __evaluate_role_expression(attr, db); if (rc != SEPOL_OK) goto exit; } break; } case CIL_AVRULEX: { struct cil_avrule *rule = node->data; if (rule->perms.x.permx_str == NULL) { rc = __evaluate_permissionx_expression(rule->perms.x.permx, db); if (rc != SEPOL_OK) goto exit; } break; } case CIL_PERMISSIONX: { struct cil_permissionx *permx = node->data; rc = __evaluate_permissionx_expression(permx, db); if (rc != SEPOL_OK) goto exit; break; } case CIL_USERATTRIBUTE: { struct cil_userattribute *attr = node->data; if (attr->users == NULL) { rc = __evaluate_user_expression(attr, db); if (rc != SEPOL_OK) { goto exit; } } break; } default: break; } return SEPOL_OK; exit: return rc; } static int __cil_role_assign_types(struct cil_role *role, struct cil_symtab_datum *datum) { struct cil_tree_node *node = datum->nodes->head->data; if (role->types == NULL) { role->types = cil_malloc(sizeof(*role->types)); ebitmap_init(role->types); } if (node->flavor == CIL_TYPE) { struct cil_type *type = (struct cil_type *)datum; if (ebitmap_set_bit(role->types, type->value, 1)) { cil_log(CIL_INFO, "Failed to set bit in role types bitmap\n"); goto exit; } } else if (node->flavor == CIL_TYPEALIAS) { struct cil_alias *alias = (struct cil_alias *)datum; struct cil_type *type = alias->actual; if (ebitmap_set_bit(role->types, type->value, 1)) { cil_log(CIL_INFO, "Failed to set bit in role types bitmap\n"); goto exit; } } else if (node->flavor == CIL_TYPEATTRIBUTE) { struct cil_typeattribute *attr = (struct cil_typeattribute *)datum; ebitmap_union(role->types, attr->types); } return SEPOL_OK; exit: return SEPOL_ERR; } static int __cil_post_db_roletype_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args) { int rc = SEPOL_ERR; struct cil_db *db = extra_args; switch (node->flavor) { case CIL_BLOCK: { struct cil_block *blk = node->data; if (blk->is_abstract == CIL_TRUE) { *finished = CIL_TREE_SKIP_HEAD; } break; } case CIL_MACRO: { *finished = CIL_TREE_SKIP_HEAD; break; } case CIL_ROLETYPE: { struct cil_roletype *roletype = node->data; struct cil_symtab_datum *role_datum = roletype->role; struct cil_symtab_datum *type_datum = roletype->type; struct cil_tree_node *role_node = role_datum->nodes->head->data; if (role_node->flavor == CIL_ROLEATTRIBUTE) { struct cil_roleattribute *attr = roletype->role; ebitmap_node_t *rnode; unsigned int i; ebitmap_for_each_positive_bit(attr->roles, rnode, i) { struct cil_role *role = NULL; role = db->val_to_role[i]; rc = __cil_role_assign_types(role, type_datum); if (rc != SEPOL_OK) { goto exit; } } } else { struct cil_role *role = roletype->role; rc = __cil_role_assign_types(role, type_datum); if (rc != SEPOL_OK) { goto exit; } } break; } default: break; } return SEPOL_OK; exit: cil_log(CIL_INFO, "cil_post_db_roletype_helper failed\n"); return rc; } static int __cil_user_assign_roles(struct cil_user *user, struct cil_symtab_datum *datum) { struct cil_tree_node *node = datum->nodes->head->data; struct cil_role *role = NULL; struct cil_roleattribute *attr = NULL; if (user->roles == NULL) { user->roles = cil_malloc(sizeof(*user->roles)); ebitmap_init(user->roles); } if (node->flavor == CIL_ROLE) { role = (struct cil_role *)datum; if (ebitmap_set_bit(user->roles, role->value, 1)) { cil_log(CIL_INFO, "Failed to set bit in user roles bitmap\n"); goto exit; } } else if (node->flavor == CIL_ROLEATTRIBUTE) { attr = (struct cil_roleattribute *)datum; ebitmap_union(user->roles, attr->roles); } return SEPOL_OK; exit: return SEPOL_ERR; } static int __cil_post_db_userrole_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args) { int rc = SEPOL_ERR; struct cil_db *db = extra_args; struct cil_block *blk = NULL; struct cil_userrole *userrole = NULL; struct cil_symtab_datum *user_datum = NULL; struct cil_symtab_datum *role_datum = NULL; struct cil_tree_node *user_node = NULL; struct cil_userattribute *u_attr = NULL; unsigned int i; struct cil_user *user = NULL; ebitmap_node_t *unode = NULL; switch (node->flavor) { case CIL_BLOCK: { blk = node->data; if (blk->is_abstract == CIL_TRUE) { *finished = CIL_TREE_SKIP_HEAD; } break; } case CIL_MACRO: { *finished = CIL_TREE_SKIP_HEAD; break; } case CIL_USERROLE: { userrole = node->data; user_datum = userrole->user; role_datum = userrole->role; user_node = user_datum->nodes->head->data; if (user_node->flavor == CIL_USERATTRIBUTE) { u_attr = userrole->user; ebitmap_for_each_positive_bit(u_attr->users, unode, i) { user = db->val_to_user[i]; rc = __cil_user_assign_roles(user, role_datum); if (rc != SEPOL_OK) { goto exit; } } } else { user = userrole->user; rc = __cil_user_assign_roles(user, role_datum); if (rc != SEPOL_OK) { goto exit; } } break; } default: break; } return SEPOL_OK; exit: cil_log(CIL_INFO, "cil_post_db_userrole_helper failed\n"); return rc; } static int __evaluate_level_expression(struct cil_level *level, struct cil_db *db) { if (level->cats != NULL) { return __evaluate_cat_expression(level->cats, db); } return SEPOL_OK; } static int __evaluate_levelrange_expression(struct cil_levelrange *levelrange, struct cil_db *db) { int rc = SEPOL_OK; if (levelrange->low != NULL && levelrange->low->cats != NULL) { rc = __evaluate_cat_expression(levelrange->low->cats, db); if (rc != SEPOL_OK) { goto exit; } } if (levelrange->high != NULL && levelrange->high->cats != NULL) { rc = __evaluate_cat_expression(levelrange->high->cats, db); if (rc != SEPOL_OK) { goto exit; } } exit: return rc; } static int __cil_post_db_cat_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args) { int rc = SEPOL_ERR; struct cil_db *db = extra_args; switch (node->flavor) { case CIL_BLOCK: { struct cil_block *blk = node->data; if (blk->is_abstract == CIL_TRUE) { *finished = CIL_TREE_SKIP_HEAD; } break; } case CIL_MACRO: { *finished = CIL_TREE_SKIP_HEAD; break; } case CIL_CATSET: { struct cil_catset *catset = node->data; rc = __evaluate_cat_expression(catset->cats, db); if (rc != SEPOL_OK) { goto exit; } break; } case CIL_SENSCAT: { struct cil_senscat *senscat = node->data; rc = __evaluate_cat_expression(senscat->cats, db); if (rc != SEPOL_OK) { goto exit; } break; } case CIL_LEVEL: { rc = __evaluate_level_expression(node->data, db); if (rc != SEPOL_OK) { goto exit; } break; } case CIL_LEVELRANGE: { rc = __evaluate_levelrange_expression(node->data, db); if (rc != SEPOL_OK) { goto exit; } break; } case CIL_USER: { struct cil_user *user = node->data; rc = __evaluate_level_expression(user->dftlevel, db); if (rc != SEPOL_OK) { goto exit; } rc = __evaluate_levelrange_expression(user->range, db); if (rc != SEPOL_OK) { goto exit; } break; } case CIL_SELINUXUSERDEFAULT: case CIL_SELINUXUSER: { struct cil_selinuxuser *selinuxuser = node->data; rc = __evaluate_levelrange_expression(selinuxuser->range, db); if (rc != SEPOL_OK) { goto exit; } break; } case CIL_RANGETRANSITION: { struct cil_rangetransition *rangetrans = node->data; rc = __evaluate_levelrange_expression(rangetrans->range, db); if (rc != SEPOL_OK) { goto exit; } break; } case CIL_CONTEXT: { struct cil_context *context = node->data; rc = __evaluate_levelrange_expression(context->range, db); if (rc != SEPOL_OK) { goto exit; } break; } case CIL_SIDCONTEXT: { struct cil_sidcontext *sidcontext = node->data; rc = __evaluate_levelrange_expression(sidcontext->context->range, db); if (rc != SEPOL_OK) { goto exit; } break; } case CIL_FILECON: { struct cil_filecon *filecon = node->data; if (filecon->context) { rc = __evaluate_levelrange_expression(filecon->context->range, db); if (rc != SEPOL_OK) { goto exit; } } break; } case CIL_IBPKEYCON: { struct cil_ibpkeycon *ibpkeycon = node->data; rc = __evaluate_levelrange_expression(ibpkeycon->context->range, db); if (rc != SEPOL_OK) goto exit; break; } case CIL_IBENDPORTCON: { struct cil_ibendportcon *ibendportcon = node->data; rc = __evaluate_levelrange_expression(ibendportcon->context->range, db); if (rc != SEPOL_OK) goto exit; break; } case CIL_PORTCON: { struct cil_portcon *portcon = node->data; rc = __evaluate_levelrange_expression(portcon->context->range, db); if (rc != SEPOL_OK) { goto exit; } break; } case CIL_NODECON: { struct cil_nodecon *nodecon = node->data; rc = __evaluate_levelrange_expression(nodecon->context->range, db); if (rc != SEPOL_OK) { goto exit; } break; } case CIL_GENFSCON: { struct cil_genfscon *genfscon = node->data; rc = __evaluate_levelrange_expression(genfscon->context->range, db); if (rc != SEPOL_OK) { goto exit; } break; } case CIL_NETIFCON: { struct cil_netifcon *netifcon = node->data; rc = __evaluate_levelrange_expression(netifcon->if_context->range, db); if (rc != SEPOL_OK) { goto exit; } rc = __evaluate_levelrange_expression(netifcon->packet_context->range, db); if (rc != SEPOL_OK) { goto exit; } break; } case CIL_PIRQCON: { struct cil_pirqcon *pirqcon = node->data; rc = __evaluate_levelrange_expression(pirqcon->context->range, db); if (rc != SEPOL_OK) { goto exit; } break; } case CIL_IOMEMCON: { struct cil_iomemcon *iomemcon = node->data; rc = __evaluate_levelrange_expression(iomemcon->context->range, db); if (rc != SEPOL_OK) { goto exit; } break; } case CIL_IOPORTCON: { struct cil_ioportcon *ioportcon = node->data; rc = __evaluate_levelrange_expression(ioportcon->context->range, db); if (rc != SEPOL_OK) { goto exit; } break; } case CIL_PCIDEVICECON: { struct cil_pcidevicecon *pcidevicecon = node->data; rc = __evaluate_levelrange_expression(pcidevicecon->context->range, db); if (rc != SEPOL_OK) { goto exit; } break; } case CIL_DEVICETREECON: { struct cil_devicetreecon *devicetreecon = node->data; rc = __evaluate_levelrange_expression(devicetreecon->context->range, db); if (rc != SEPOL_OK) { goto exit; } break; } case CIL_FSUSE: { struct cil_fsuse *fsuse = node->data; rc = __evaluate_levelrange_expression(fsuse->context->range, db); if (rc != SEPOL_OK) { goto exit; } break; } default: break; } return SEPOL_OK; exit: return rc; } struct perm_to_list { enum cil_flavor flavor; ebitmap_t *perms; struct cil_list *new_list; }; static int __perm_bits_to_list(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, void *args) { struct perm_to_list *perm_args = (struct perm_to_list *)args; ebitmap_t *perms = perm_args->perms; struct cil_list *new_list = perm_args->new_list; struct cil_perm *perm = (struct cil_perm *)d; unsigned int value = perm->value; if (!ebitmap_get_bit(perms, value)) { return SEPOL_OK; } cil_list_append(new_list, CIL_DATUM, d); return SEPOL_OK; } static int __evaluate_perm_expression(struct cil_list *perms, enum cil_flavor flavor, symtab_t *class_symtab, symtab_t *common_symtab, unsigned int num_perms, struct cil_list **new_list, struct cil_db *db) { int rc = SEPOL_ERR; struct perm_to_list args; ebitmap_t bitmap; if (cil_verify_is_list(perms, CIL_PERM)) { return SEPOL_OK; } ebitmap_init(&bitmap); rc = __cil_expr_to_bitmap(perms, &bitmap, num_perms, db); if (rc != SEPOL_OK) { ebitmap_destroy(&bitmap); goto exit; } cil_list_init(new_list, flavor); args.flavor = flavor; args.perms = &bitmap; args.new_list = *new_list; cil_symtab_map(class_symtab, __perm_bits_to_list, &args); if (common_symtab != NULL) { cil_symtab_map(common_symtab, __perm_bits_to_list, &args); } ebitmap_destroy(&bitmap); return SEPOL_OK; exit: return rc; } static int __evaluate_classperms(struct cil_classperms *cp, struct cil_db *db) { int rc = SEPOL_ERR; struct cil_class *class = cp->class; struct cil_class *common = class->common; symtab_t *common_symtab = NULL; struct cil_list *new_list = NULL; if (common) { common_symtab = &common->perms; } rc = __evaluate_perm_expression(cp->perms, CIL_PERM, &class->perms, common_symtab, class->num_perms, &new_list, db); if (rc != SEPOL_OK) { goto exit; } if (new_list == NULL) { return SEPOL_OK; } cil_list_destroy(&cp->perms, CIL_FALSE); cp->perms = new_list; return SEPOL_OK; exit: return rc; } static int __evaluate_classperms_list(struct cil_list *classperms, struct cil_db *db) { int rc = SEPOL_ERR; struct cil_list_item *curr; cil_list_for_each(curr, classperms) { if (curr->flavor == CIL_CLASSPERMS) { struct cil_classperms *cp = curr->data; if (FLAVOR(cp->class) == CIL_CLASS) { rc = __evaluate_classperms(cp, db); if (rc != SEPOL_OK) { goto exit; } } else { /* MAP */ struct cil_list_item *i = NULL; rc = __evaluate_classperms(cp, db); if (rc != SEPOL_OK) { goto exit; } cil_list_for_each(i, cp->perms) { struct cil_perm *cmp = i->data; rc = __evaluate_classperms_list(cmp->classperms, db); if (rc != SEPOL_OK) { goto exit; } } } } else { /* SET */ struct cil_classperms_set *cp_set = curr->data; struct cil_classpermission *cp = cp_set->set; rc = __evaluate_classperms_list(cp->classperms, db); if (rc != SEPOL_OK) { goto exit; } } } return SEPOL_OK; exit: return rc; } struct class_map_args { struct cil_db *db; int rc; }; static int __evaluate_map_perm_classperms(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, void *args) { struct class_map_args *map_args = args; struct cil_perm *cmp = (struct cil_perm *)d; int rc = __evaluate_classperms_list(cmp->classperms, map_args->db); if (rc != SEPOL_OK) { map_args->rc = rc; } return SEPOL_OK; } static int __evaluate_map_class(struct cil_class *mc, struct cil_db *db) { struct class_map_args map_args; map_args.db = db; map_args.rc = SEPOL_OK; cil_symtab_map(&mc->perms, __evaluate_map_perm_classperms, &map_args); return map_args.rc; } static int __cil_post_db_classperms_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args) { int rc = SEPOL_ERR; struct cil_db *db = extra_args; switch (node->flavor) { case CIL_BLOCK: { struct cil_block *blk = node->data; if (blk->is_abstract == CIL_TRUE) { *finished = CIL_TREE_SKIP_HEAD; } break; } case CIL_MACRO: *finished = CIL_TREE_SKIP_HEAD; break; case CIL_MAP_CLASS: { rc = __evaluate_map_class(node->data, db); if (rc != SEPOL_OK) { goto exit; } break; } case CIL_CLASSPERMISSION: { struct cil_classpermission *cp = node->data; rc = __evaluate_classperms_list(cp->classperms, db); if (rc != SEPOL_OK) { goto exit; } break; } case CIL_AVRULE: { struct cil_avrule *avrule = node->data; rc = __evaluate_classperms_list(avrule->perms.classperms, db); if (rc != SEPOL_OK) { goto exit; } break; } case CIL_CONSTRAIN: case CIL_MLSCONSTRAIN: { struct cil_constrain *constrain = node->data; rc = __evaluate_classperms_list(constrain->classperms, db); if (rc != SEPOL_OK) { goto exit; } break; } default: break; } return SEPOL_OK; exit: return rc; } static int __cil_post_report_conflict(struct cil_tree_node *node, uint32_t *finished, void *extra_args) { struct cil_list_item *li = extra_args; if (node->flavor == CIL_BLOCK) { struct cil_block *blk = node->data; if (blk->is_abstract == CIL_TRUE) { *finished = CIL_TREE_SKIP_HEAD; } } else if (node->flavor == CIL_MACRO) { *finished = CIL_TREE_SKIP_HEAD; } else if (node->flavor == li->flavor) { if (node->data == li->data) { char *path = cil_tree_get_cil_path(node); cil_log(CIL_WARN, " at %s:%d\n", path, node->line); } } return SEPOL_OK; } static int __cil_post_process_context_rules(struct cil_sort *sort, int (*compar)(const void *, const void *), int (*concompar)(const void *, const void *), struct cil_db *db, enum cil_flavor flavor, const char *flavor_str) { uint32_t count = sort->count; uint32_t i = 0, j, removed = 0; int conflicting = 0; int rc = SEPOL_OK; enum cil_log_level log_level = cil_get_log_level(); if (count < 2) { return SEPOL_OK; } qsort(sort->array, sort->count, sizeof(sort->array), compar); for (j=1; jarray[i], &sort->array[j]) != 0) { i++; if (conflicting >= 4) { /* 2 rules were written when conflicting == 1 */ cil_log(CIL_WARN, " Only first 4 of %d conflicting rules shown\n", conflicting); } conflicting = 0; } else { removed++; if (!db->multiple_decls || concompar(&sort->array[i], &sort->array[j]) != 0) { rc = SEPOL_ERR; conflicting++; if (log_level >= CIL_WARN) { struct cil_list_item li; int rc2; li.flavor = flavor; if (conflicting == 1) { cil_log(CIL_WARN, "Found conflicting %s rules\n", flavor_str); li.data = sort->array[i]; rc2 = cil_tree_walk(db->ast->root, __cil_post_report_conflict, NULL, NULL, &li); if (rc2 != SEPOL_OK) goto exit; } if (conflicting < 4 || log_level > CIL_WARN) { li.data = sort->array[j]; rc2 = cil_tree_walk(db->ast->root, __cil_post_report_conflict, NULL, NULL, &li); if (rc2 != SEPOL_OK) goto exit; } } } } if (i != j && !conflicting) { sort->array[i] = sort->array[j]; } } sort->count = count - removed; exit: return rc; } static int cil_post_db(struct cil_db *db) { int rc = SEPOL_ERR; rc = cil_tree_walk(db->ast->root, __cil_post_db_count_helper, NULL, NULL, db); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "Failure during cil database count helper\n"); goto exit; } rc = cil_tree_walk(db->ast->root, __cil_post_db_array_helper, NULL, NULL, db); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "Failure during cil database array helper\n"); goto exit; } rc = cil_tree_walk(db->ast->root, __cil_post_db_neverallow_attr_helper, NULL, NULL, db); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "Failed to mark attributes used by generated attributes used in neverallow rules\n"); goto exit; } rc = cil_tree_walk(db->ast->root, __cil_post_db_attr_helper, NULL, NULL, db); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "Failed to create attribute bitmaps\n"); goto exit; } rc = cil_tree_walk(db->ast->root, __cil_post_db_roletype_helper, NULL, NULL, db); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "Failed during roletype association\n"); goto exit; } rc = cil_tree_walk(db->ast->root, __cil_post_db_userrole_helper, NULL, NULL, db); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "Failed during userrole association\n"); goto exit; } rc = cil_tree_walk(db->ast->root, __cil_post_db_classperms_helper, NULL, NULL, db); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "Failed to evaluate class mapping permissions expressions\n"); goto exit; } rc = cil_tree_walk(db->ast->root, __cil_post_db_cat_helper, NULL, NULL, db); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "Failed to evaluate category expressions\n"); goto exit; } rc = __cil_post_process_context_rules(db->netifcon, cil_post_netifcon_compare, cil_post_netifcon_context_compare, db, CIL_NETIFCON, CIL_KEY_NETIFCON); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Problems processing netifcon rules\n"); goto exit; } rc = __cil_post_process_context_rules(db->genfscon, cil_post_genfscon_compare, cil_post_genfscon_context_compare, db, CIL_GENFSCON, CIL_KEY_GENFSCON); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Problems processing genfscon rules\n"); goto exit; } rc = __cil_post_process_context_rules(db->ibpkeycon, cil_post_ibpkeycon_compare, cil_post_ibpkeycon_context_compare, db, CIL_IBPKEYCON, CIL_KEY_IBPKEYCON); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Problems processing ibpkeycon rules\n"); goto exit; } rc = __cil_post_process_context_rules(db->ibendportcon, cil_post_ibendportcon_compare, cil_post_ibendportcon_context_compare, db, CIL_IBENDPORTCON, CIL_KEY_IBENDPORTCON); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Problems processing ibendportcon rules\n"); goto exit; } rc = __cil_post_process_context_rules(db->portcon, cil_post_portcon_compare, cil_post_portcon_context_compare, db, CIL_PORTCON, CIL_KEY_PORTCON); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Problems processing portcon rules\n"); goto exit; } rc = __cil_post_process_context_rules(db->nodecon, cil_post_nodecon_compare, cil_post_nodecon_context_compare, db, CIL_NODECON, CIL_KEY_NODECON); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Problems processing nodecon rules\n"); goto exit; } rc = __cil_post_process_context_rules(db->fsuse, cil_post_fsuse_compare, cil_post_fsuse_context_compare, db, CIL_FSUSE, CIL_KEY_FSUSE); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Problems processing fsuse rules\n"); goto exit; } rc = __cil_post_process_context_rules(db->filecon, cil_post_filecon_compare, cil_post_filecon_context_compare, db, CIL_FILECON, CIL_KEY_FILECON); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Problems processing filecon rules\n"); goto exit; } rc = __cil_post_process_context_rules(db->pirqcon, cil_post_pirqcon_compare, cil_post_pirqcon_context_compare, db, CIL_PIRQCON, CIL_KEY_IOMEMCON); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Problems processing pirqcon rules\n"); goto exit; } rc = __cil_post_process_context_rules(db->iomemcon, cil_post_iomemcon_compare, cil_post_iomemcon_context_compare, db, CIL_IOMEMCON, CIL_KEY_IOMEMCON); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Problems processing iomemcon rules\n"); goto exit; } rc = __cil_post_process_context_rules(db->ioportcon, cil_post_ioportcon_compare, cil_post_ioportcon_context_compare, db, CIL_IOPORTCON, CIL_KEY_IOPORTCON); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Problems processing ioportcon rules\n"); goto exit; } rc = __cil_post_process_context_rules(db->pcidevicecon, cil_post_pcidevicecon_compare, cil_post_pcidevicecon_context_compare, db, CIL_PCIDEVICECON, CIL_KEY_PCIDEVICECON); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Problems processing pcidevicecon rules\n"); goto exit; } rc = __cil_post_process_context_rules(db->devicetreecon, cil_post_devicetreecon_compare, cil_post_devicetreecon_context_compare, db, CIL_DEVICETREECON, CIL_KEY_DEVICETREECON); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Problems processing devicetreecon rules\n"); goto exit; } exit: return rc; } static int cil_post_verify(struct cil_db *db) { int rc = SEPOL_ERR; int avrule_cnt = 0; int handleunknown = -1; int mls = -1; int nseuserdflt = 0; int pass = 0; struct cil_args_verify extra_args; struct cil_complex_symtab csymtab; cil_complex_symtab_init(&csymtab, CIL_CLASS_SYM_SIZE); extra_args.db = db; extra_args.csymtab = &csymtab; extra_args.avrule_cnt = &avrule_cnt; extra_args.handleunknown = &handleunknown; extra_args.mls = &mls; extra_args.nseuserdflt = &nseuserdflt; extra_args.pass = &pass; for (pass = 0; pass < 2; pass++) { rc = cil_tree_walk(db->ast->root, __cil_verify_helper, NULL, NULL, &extra_args); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Failed to verify cil database\n"); goto exit; } } if (db->handle_unknown == -1) { if (handleunknown == -1) { db->handle_unknown = SEPOL_DENY_UNKNOWN; } else { db->handle_unknown = handleunknown; } } if (db->mls == -1) { if (mls == -1) { db->mls = CIL_FALSE; } else { db->mls = mls; } } if (avrule_cnt == 0) { cil_log(CIL_ERR, "Policy must include at least one avrule\n"); rc = SEPOL_ERR; goto exit; } if (nseuserdflt > 1) { cil_log(CIL_ERR, "Policy cannot contain more than one selinuxuserdefault, found: %d\n", nseuserdflt); rc = SEPOL_ERR; goto exit; } exit: cil_complex_symtab_destroy(&csymtab); return rc; } static int cil_pre_verify(struct cil_db *db) { int rc = SEPOL_ERR; struct cil_args_verify extra_args; extra_args.db = db; rc = cil_tree_walk(db->ast->root, __cil_pre_verify_helper, NULL, NULL, &extra_args); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Failed to verify cil database\n"); goto exit; } exit: return rc; } int cil_post_process(struct cil_db *db) { int rc = SEPOL_ERR; rc = cil_pre_verify(db); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Failed to verify cil database\n"); goto exit; } rc = cil_post_db(db); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Failed post db handling\n"); goto exit; } rc = cil_process_deny_rules_in_ast(db); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Failed to process deny rules\n"); goto exit; } rc = cil_post_verify(db); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Failed to verify cil database\n"); goto exit; } exit: return rc; } libsepol-3.8.1/cil/src/cil_post.h000066400000000000000000000042751476211737200167010ustar00rootroot00000000000000/* * 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_ int cil_post_filecon_compare(const void *a, const void *b); int cil_post_ibpkeycon_compare(const void *a, const void *b); int cil_post_portcon_compare(const void *a, const void *b); int cil_post_ibendportcon_compare(const void *a, const void *b); int cil_post_genfscon_compare(const void *a, const void *b); int cil_post_netifcon_compare(const void *a, const void *b); int cil_post_nodecon_compare(const void *a, const void *b); int cil_post_fsuse_compare(const void *a, const void *b); int cil_post_context_sort(struct cil_db *db); int cil_post_process(struct cil_db *db); #endif libsepol-3.8.1/cil/src/cil_reset_ast.c000066400000000000000000000366761476211737200177120ustar00rootroot00000000000000 #include "cil_internal.h" #include "cil_log.h" #include "cil_list.h" #include "cil_reset_ast.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 void cil_reset_ordered(struct cil_ordered *ordered) { ordered->merged = CIL_FALSE; cil_list_destroy(&ordered->datums, CIL_FALSE); } 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) { /* Must assume that the common has been destroyed */ int num_common_perms = class->num_perms - class->perms.nprim; cil_symtab_map(&class->perms, __class_reset_perm_values, &num_common_perms); /* during a re-resolve, we need to reset the common, so a classcommon * statement isn't seen as a duplicate */ class->num_perms = class->perms.nprim; 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_list_destroy(&perm->classperms, CIL_FALSE); } static inline void cil_reset_classperms(struct cil_classperms *cp) { if (cp == NULL) { return; } cp->class = NULL; cil_list_destroy(&cp->perms, CIL_FALSE); } static void cil_reset_classpermission(struct cil_classpermission *cp) { if (cp == NULL) { return; } cil_list_destroy(&cp->classperms, CIL_FALSE); } static void cil_reset_classperms_set(struct cil_classperms_set *cp_set) { if (cp_set == NULL || cp_set->set == NULL) { return; } if (cp_set->set->datum.name == NULL) { cil_reset_classperms_list(cp_set->set->classperms); } cp_set->set = NULL; } static inline void cil_reset_classperms_list(struct cil_list *cp_list) { struct cil_list_item *curr; if (cp_list == NULL) { return; } cil_list_for_each(curr, cp_list) { if (curr->flavor == CIL_CLASSPERMS) { /* KERNEL or MAP */ cil_reset_classperms(curr->data); } else if (curr->flavor == CIL_CLASSPERMS_SET) { /* SET */ cil_reset_classperms_set(curr->data); } } } static void cil_reset_classpermissionset(struct cil_classpermissionset *cps) { cil_reset_classperms_list(cps->classperms); } static void cil_reset_classmapping(struct cil_classmapping *cm) { cil_reset_classperms_list(cm->classperms); } static void cil_reset_alias(struct cil_alias *alias) { /* reset actual to NULL during a re-resolve */ alias->actual = NULL; } static void cil_reset_user(struct cil_user *user) { /* reset the bounds to NULL during a re-resolve */ user->bounds = NULL; user->dftlevel = NULL; user->range = NULL; } static void cil_reset_userattr(struct cil_userattribute *attr) { struct cil_list_item *expr = NULL; struct cil_list_item *next = NULL; /* during a re-resolve, we need to reset the lists of expression stacks associated with this attribute from a userattribute statement */ if (attr->expr_list != NULL) { /* we don't want to destroy the expression stacks (cil_list) inside * this list cil_list_destroy destroys sublists, so we need to do it * manually */ expr = attr->expr_list->head; while (expr != NULL) { next = expr->next; cil_list_item_destroy(&expr, CIL_FALSE); expr = next; } free(attr->expr_list); attr->expr_list = NULL; } } static void cil_reset_userattributeset(struct cil_userattributeset *uas) { cil_list_destroy(&uas->datum_expr, CIL_FALSE); } static void cil_reset_selinuxuser(struct cil_selinuxuser *selinuxuser) { selinuxuser->user = NULL; if (selinuxuser->range_str == NULL) { cil_reset_levelrange(selinuxuser->range); } else { selinuxuser->range = NULL; } } static void cil_reset_role(struct cil_role *role) { /* reset the bounds to NULL during a re-resolve */ role->bounds = NULL; } static void cil_reset_roleattr(struct cil_roleattribute *attr) { /* during a re-resolve, we need to reset the lists of expression stacks associated with this attribute from a attributeroles statement */ if (attr->expr_list != NULL) { /* we don't want to destroy the expression stacks (cil_list) inside * this list cil_list_destroy destroys sublists, so we need to do it * manually */ struct cil_list_item *expr = attr->expr_list->head; while (expr != NULL) { struct cil_list_item *next = expr->next; cil_list_item_destroy(&expr, CIL_FALSE); expr = next; } free(attr->expr_list); attr->expr_list = NULL; } } static void cil_reset_roleattributeset(struct cil_roleattributeset *ras) { cil_list_destroy(&ras->datum_expr, CIL_FALSE); } static void cil_reset_type(struct cil_type *type) { /* reset the bounds to NULL during a re-resolve */ type->bounds = NULL; } static void cil_reset_typeattr(struct cil_typeattribute *attr) { /* during a re-resolve, we need to reset the lists of expression stacks associated with this attribute from a attributetypes statement */ if (attr->expr_list != NULL) { /* we don't want to destroy the expression stacks (cil_list) inside * this list cil_list_destroy destroys sublists, so we need to do it * manually */ struct cil_list_item *expr = attr->expr_list->head; while (expr != NULL) { struct cil_list_item *next = expr->next; cil_list_item_destroy(&expr, CIL_FALSE); expr = next; } free(attr->expr_list); attr->expr_list = NULL; } attr->used = CIL_FALSE; attr->keep = CIL_FALSE; } static void cil_reset_typeattributeset(struct cil_typeattributeset *tas) { cil_list_destroy(&tas->datum_expr, CIL_FALSE); } static void cil_reset_expandtypeattribute(struct cil_expandtypeattribute *expandattr) { cil_list_destroy(&expandattr->attr_datums, CIL_FALSE); } static void cil_reset_avrule(struct cil_avrule *rule) { cil_reset_classperms_list(rule->perms.classperms); } static void cil_reset_deny_rule(struct cil_deny_rule *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); } else { rangetrans->range = NULL; } } 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) { level->sens = NULL; 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); } else { levelrange->low = NULL; } if (levelrange->high_str == NULL) { cil_reset_level(levelrange->high); } else { levelrange->high = NULL; } } static inline void cil_reset_userlevel(struct cil_userlevel *userlevel) { if (userlevel->level_str == NULL) { cil_reset_level(userlevel->level); } else { userlevel->level = NULL; } } static inline void cil_reset_userrange(struct cil_userrange *userrange) { if (userrange->range_str == NULL) { cil_reset_levelrange(userrange->range); } else { userrange->range = NULL; } } static inline void cil_reset_context(struct cil_context *context) { if (!context) { return; } if (context->range_str == NULL) { cil_reset_levelrange(context->range); } else { context->range = NULL; } } static void cil_reset_sidcontext(struct cil_sidcontext *sidcontext) { if (sidcontext->context_str == NULL) { cil_reset_context(sidcontext->context); } else { sidcontext->context = NULL; } } static void cil_reset_filecon(struct cil_filecon *filecon) { if (filecon->context_str == NULL) { cil_reset_context(filecon->context); } else { filecon->context = NULL; } } static void cil_reset_ibpkeycon(struct cil_ibpkeycon *ibpkeycon) { if (ibpkeycon->context_str == NULL) { cil_reset_context(ibpkeycon->context); } else { ibpkeycon->context = NULL; } } static void cil_reset_portcon(struct cil_portcon *portcon) { if (portcon->context_str == NULL) { cil_reset_context(portcon->context); } else { portcon->context = NULL; } } static void cil_reset_nodecon(struct cil_nodecon *nodecon) { if (nodecon->context_str == NULL) { cil_reset_context(nodecon->context); } else { nodecon->context = NULL; } } static void cil_reset_genfscon(struct cil_genfscon *genfscon) { if (genfscon->context_str == NULL) { cil_reset_context(genfscon->context); } else { genfscon->context = NULL; } } static void cil_reset_netifcon(struct cil_netifcon *netifcon) { if (netifcon->if_context_str == NULL) { cil_reset_context(netifcon->if_context); } else { netifcon->if_context = NULL; } if (netifcon->packet_context_str == NULL) { cil_reset_context(netifcon->packet_context); } else { netifcon->packet_context = NULL; } } static void cil_reset_ibendportcon(struct cil_ibendportcon *ibendportcon) { if (ibendportcon->context_str == NULL) { cil_reset_context(ibendportcon->context); } else { ibendportcon->context = NULL; } } static void cil_reset_pirqcon(struct cil_pirqcon *pirqcon) { if (pirqcon->context_str == NULL) { cil_reset_context(pirqcon->context); } else { pirqcon->context = NULL; } } static void cil_reset_iomemcon(struct cil_iomemcon *iomemcon) { if (iomemcon->context_str == NULL) { cil_reset_context(iomemcon->context); } else { iomemcon->context = NULL; } } static void cil_reset_ioportcon(struct cil_ioportcon *ioportcon) { if (ioportcon->context_str == NULL) { cil_reset_context(ioportcon->context); } else { ioportcon->context = NULL; } } static void cil_reset_pcidevicecon(struct cil_pcidevicecon *pcidevicecon) { if (pcidevicecon->context_str == NULL) { cil_reset_context(pcidevicecon->context); } else { pcidevicecon->context = NULL; } } static void cil_reset_devicetreecon(struct cil_devicetreecon *devicetreecon) { if (devicetreecon->context_str == NULL) { cil_reset_context(devicetreecon->context); } else { devicetreecon->context = NULL; } } static void cil_reset_fsuse(struct cil_fsuse *fsuse) { if (fsuse->context_str == NULL) { cil_reset_context(fsuse->context); } else { fsuse->context = NULL; } } 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); } static int __cil_reset_node(struct cil_tree_node *node, __attribute__((unused)) uint32_t *finished, __attribute__((unused)) void *extra_args) { switch (node->flavor) { case CIL_CLASS: cil_reset_class(node->data); break; case CIL_PERM: case CIL_MAP_PERM: cil_reset_perm(node->data); break; case CIL_CLASSPERMISSION: cil_reset_classpermission(node->data); break; case CIL_CLASSPERMISSIONSET: cil_reset_classpermissionset(node->data); break; case CIL_CLASSMAPPING: cil_reset_classmapping(node->data); break; case CIL_TYPEALIAS: case CIL_SENSALIAS: case CIL_CATALIAS: cil_reset_alias(node->data); break; case CIL_USERRANGE: cil_reset_userrange(node->data); break; case CIL_USERLEVEL: cil_reset_userlevel(node->data); break; case CIL_USER: cil_reset_user(node->data); break; case CIL_USERATTRIBUTE: cil_reset_userattr(node->data); break; case CIL_USERATTRIBUTESET: cil_reset_userattributeset(node->data); break; case CIL_SELINUXUSERDEFAULT: case CIL_SELINUXUSER: cil_reset_selinuxuser(node->data); break; case CIL_ROLE: cil_reset_role(node->data); break; case CIL_ROLEATTRIBUTE: cil_reset_roleattr(node->data); break; case CIL_ROLEATTRIBUTESET: cil_reset_roleattributeset(node->data); break; case CIL_TYPE: cil_reset_type(node->data); break; case CIL_TYPEATTRIBUTE: cil_reset_typeattr(node->data); break; case CIL_TYPEATTRIBUTESET: cil_reset_typeattributeset(node->data); break; case CIL_EXPANDTYPEATTRIBUTE: cil_reset_expandtypeattribute(node->data); break; case CIL_RANGETRANSITION: cil_reset_rangetransition(node->data); break; case CIL_AVRULE: cil_reset_avrule(node->data); break; case CIL_DENY_RULE: cil_reset_deny_rule(node->data); break; case CIL_SENS: cil_reset_sens(node->data); break; case CIL_CAT: cil_reset_cat(node->data); break; case CIL_SENSCAT: cil_reset_senscat(node->data); break; case CIL_CATSET: cil_reset_catset(node->data); break; case CIL_LEVEL: cil_reset_level(node->data); break; case CIL_LEVELRANGE: cil_reset_levelrange(node->data); break; case CIL_CONTEXT: cil_reset_context(node->data); break; case CIL_SIDCONTEXT: cil_reset_sidcontext(node->data); break; case CIL_FILECON: cil_reset_filecon(node->data); break; case CIL_IBPKEYCON: cil_reset_ibpkeycon(node->data); break; case CIL_IBENDPORTCON: cil_reset_ibendportcon(node->data); break; case CIL_PORTCON: cil_reset_portcon(node->data); break; case CIL_NODECON: cil_reset_nodecon(node->data); break; case CIL_GENFSCON: cil_reset_genfscon(node->data); break; case CIL_NETIFCON: cil_reset_netifcon(node->data); break; case CIL_PIRQCON: cil_reset_pirqcon(node->data); break; case CIL_IOMEMCON: cil_reset_iomemcon(node->data); break; case CIL_IOPORTCON: cil_reset_ioportcon(node->data); break; case CIL_PCIDEVICECON: cil_reset_pcidevicecon(node->data); break; case CIL_DEVICETREECON: cil_reset_devicetreecon(node->data); break; case CIL_FSUSE: cil_reset_fsuse(node->data); break; case CIL_SID: cil_reset_sid(node->data); break; case CIL_CONSTRAIN: case CIL_MLSCONSTRAIN: cil_reset_constrain(node->data); break; case CIL_VALIDATETRANS: case CIL_MLSVALIDATETRANS: cil_reset_validatetrans(node->data); break; case CIL_DEFAULTUSER: case CIL_DEFAULTROLE: case CIL_DEFAULTTYPE: cil_reset_default(node->data); break; case CIL_DEFAULTRANGE: cil_reset_defaultrange(node->data); break; case CIL_BOOLEANIF: cil_reset_booleanif(node->data); break; case CIL_SIDORDER: case CIL_CLASSORDER: case CIL_CATORDER: case CIL_SENSITIVITYORDER: cil_reset_ordered(node->data); break; case CIL_TUNABLEIF: case CIL_CALL: break; /* Not effected by optional block disabling */ case CIL_MACRO: break; /* Nothing to reset */ default: break; } return SEPOL_OK; } int cil_reset_ast(struct cil_tree_node *current) { int rc = SEPOL_ERR; rc = cil_tree_walk(current, __cil_reset_node, NULL, NULL, NULL); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Failed to reset AST\n"); return SEPOL_ERR; } return SEPOL_OK; } libsepol-3.8.1/cil/src/cil_reset_ast.h000066400000000000000000000002331476211737200176730ustar00rootroot00000000000000#ifndef CIL_RESET_AST_H_ #define CIL_RESET_AST_H_ #include "cil_tree.h" int cil_reset_ast(struct cil_tree_node *current); #endif /* CIL_RESET_AST_H_ */ libsepol-3.8.1/cil/src/cil_resolve_ast.c000066400000000000000000003346431476211737200202420ustar00rootroot00000000000000/* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #include #include #include #include #include "cil_internal.h" #include "cil_flavor.h" #include "cil_log.h" #include "cil_mem.h" #include "cil_tree.h" #include "cil_list.h" #include "cil_build_ast.h" #include "cil_resolve_ast.h" #include "cil_reset_ast.h" #include "cil_copy_ast.h" #include "cil_verify.h" #include "cil_strpool.h" #include "cil_symtab.h" #include "cil_stack.h" struct cil_args_resolve { struct cil_db *db; enum cil_pass pass; uint32_t *changed; struct cil_list *to_destroy; struct cil_tree_node *block; struct cil_tree_node *macro; struct cil_tree_node *optional; struct cil_tree_node *disabled_optional; struct cil_tree_node *boolif; struct cil_list *sidorder_lists; struct cil_list *classorder_lists; struct cil_list *unordered_classorder_lists; struct cil_list *catorder_lists; struct cil_list *sensitivityorder_lists; struct cil_list *in_list_before; struct cil_list *in_list_after; struct cil_list *abstract_blocks; }; static int __cil_resolve_perms(symtab_t *class_symtab, symtab_t *common_symtab, struct cil_list *perm_strs, struct cil_list **perm_datums, enum cil_flavor class_flavor) { int rc = SEPOL_ERR; struct cil_list_item *curr; cil_list_init(perm_datums, perm_strs->flavor); cil_list_for_each(curr, perm_strs) { if (curr->flavor == CIL_LIST) { struct cil_list *sub_list; rc = __cil_resolve_perms(class_symtab, common_symtab, curr->data, &sub_list, class_flavor); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Failed to resolve permission list\n"); goto exit; } cil_list_append(*perm_datums, CIL_LIST, sub_list); } else if (curr->flavor == CIL_STRING) { struct cil_symtab_datum *perm_datum = NULL; rc = cil_symtab_get_datum(class_symtab, curr->data, &perm_datum); if (rc == SEPOL_ENOENT) { if (common_symtab) { rc = cil_symtab_get_datum(common_symtab, curr->data, &perm_datum); } } if (rc != SEPOL_OK) { if (class_flavor == CIL_MAP_CLASS) { cil_log(CIL_ERR, "Failed to resolve permission %s for map class\n", (char*)curr->data); } else { 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: cil_list_destroy(perm_datums, CIL_FALSE); return rc; } int cil_resolve_classperms(struct cil_tree_node *current, struct cil_classperms *cp, struct cil_db *db) { int rc = SEPOL_ERR; struct cil_symtab_datum *datum = NULL; symtab_t *common_symtab = NULL; struct cil_class *class; if (cp->class) { return SEPOL_OK; } rc = cil_resolve_name(current, cp->class_str, CIL_SYM_CLASSES, db, &datum); if (rc != SEPOL_OK) { goto exit; } class = (struct cil_class *)datum; if (class->common != NULL) { common_symtab = &class->common->perms; } cp->class = class; rc = __cil_resolve_perms(&class->perms, common_symtab, cp->perm_strs, &cp->perms, FLAVOR(datum)); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: return rc; } static int cil_resolve_classperms_set(struct cil_tree_node *current, struct cil_classperms_set *cp_set, struct cil_db *db) { int rc = SEPOL_ERR; struct cil_symtab_datum *datum = NULL; rc = cil_resolve_name(current, cp_set->set_str, CIL_SYM_CLASSPERMSETS, db, &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, db); 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, struct cil_db *db) { 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, db); if (rc != SEPOL_OK) { goto exit; } } else { rc = cil_resolve_classperms_set(current, curr->data, db); 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, struct cil_db *db) { int rc = SEPOL_ERR; 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, db, &datum); if (rc != SEPOL_OK) { goto exit; } if (!datum->fqn) { cil_tree_log(current, CIL_ERR, "Anonymous classpermission used in a classpermissionset"); rc = SEPOL_ERR; goto exit; } rc = cil_resolve_classperms_list(current, cps->classperms, db); if (rc != SEPOL_OK) { goto exit; } cp = (struct cil_classpermission *)datum; cps->set = cp; 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; } static void cil_type_used(struct cil_symtab_datum *datum, int used) { struct cil_typeattribute *attr = NULL; if (FLAVOR(datum) == CIL_TYPEATTRIBUTE) { attr = (struct cil_typeattribute*)datum; attr->used |= used; if ((attr->used & CIL_ATTR_EXPAND_TRUE) && (attr->used & CIL_ATTR_EXPAND_FALSE)) { cil_log(CIL_WARN, "Conflicting use of expandtypeattribute. " "Expandtypeattribute was set to both true or false for %s. " "Resolving to false. \n", attr->datum.name); attr->used &= ~CIL_ATTR_EXPAND_TRUE; } } } static int cil_resolve_permissionx(struct cil_tree_node *current, struct cil_permissionx *permx, struct cil_db *db) { struct cil_symtab_datum *obj_datum = NULL; int rc = SEPOL_ERR; rc = cil_resolve_name(current, permx->obj_str, CIL_SYM_CLASSES, db, &obj_datum); if (rc != SEPOL_OK) { goto exit; } permx->obj = (struct cil_class*)obj_datum; return SEPOL_OK; exit: return rc; } int cil_resolve_avrule(struct cil_tree_node *current, struct cil_db *db) { struct cil_avrule *rule = current->data; struct cil_symtab_datum *src_datum = NULL; struct cil_symtab_datum *tgt_datum = NULL; struct cil_symtab_datum *permx_datum = NULL; int used; int rc = SEPOL_ERR; rc = cil_resolve_name(current, rule->src_str, CIL_SYM_TYPES, db, &src_datum); if (rc != SEPOL_OK) { goto exit; } rule->src = src_datum; if (rule->tgt_str == CIL_KEY_SELF) { rule->tgt = db->selftype; } else if (rule->tgt_str == CIL_KEY_NOTSELF) { rule->tgt = db->notselftype; } else if (rule->tgt_str == CIL_KEY_OTHER) { rule->tgt = db->othertype; } else { rc = cil_resolve_name(current, rule->tgt_str, CIL_SYM_TYPES, db, &tgt_datum); if (rc != SEPOL_OK) { goto exit; } rule->tgt = tgt_datum; used = (rule->rule_kind == CIL_AVRULE_NEVERALLOW) ? CIL_ATTR_NEVERALLOW : CIL_ATTR_AVRULE; cil_type_used(src_datum, used); /* src not used if tgt is self */ cil_type_used(tgt_datum, used); } if (!rule->is_extended) { rc = cil_resolve_classperms_list(current, rule->perms.classperms, db); if (rc != SEPOL_OK) { goto exit; } } else { if (rule->perms.x.permx_str != NULL) { rc = cil_resolve_name(current, rule->perms.x.permx_str, CIL_SYM_PERMX, db, &permx_datum); if (rc != SEPOL_OK) { goto exit; } rule->perms.x.permx = (struct cil_permissionx*)permx_datum; } else { rc = cil_resolve_permissionx(current, rule->perms.x.permx, db); if (rc != SEPOL_OK) { goto exit; } } } return SEPOL_OK; exit: return rc; } int cil_resolve_deny_rule(struct cil_tree_node *current, struct cil_db *db) { struct cil_deny_rule *rule = 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, rule->src_str, CIL_SYM_TYPES, db, &src_datum); if (rc != SEPOL_OK) { goto exit; } rule->src = src_datum; if (rule->tgt_str == CIL_KEY_SELF) { rule->tgt = db->selftype; } else if (rule->tgt_str == CIL_KEY_NOTSELF) { rule->tgt = db->notselftype; } else if (rule->tgt_str == CIL_KEY_OTHER) { rule->tgt = db->othertype; } else { rc = cil_resolve_name(current, rule->tgt_str, CIL_SYM_TYPES, db, &tgt_datum); if (rc != SEPOL_OK) { goto exit; } rule->tgt = tgt_datum; } rc = cil_resolve_classperms_list(current, rule->classperms, db); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: return rc; } int cil_resolve_type_rule(struct cil_tree_node *current, struct cil_db *db) { 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, db, &src_datum); if (rc != SEPOL_OK) { goto exit; } rule->src = src_datum; if (rule->tgt_str == CIL_KEY_SELF) { rule->tgt = db->selftype; } else { rc = cil_resolve_name(current, rule->tgt_str, CIL_SYM_TYPES, db, &tgt_datum); if (rc != SEPOL_OK) { goto exit; } rule->tgt = tgt_datum; } rc = cil_resolve_name(current, rule->obj_str, CIL_SYM_CLASSES, db, &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, db, &result_datum); if (rc != SEPOL_OK) { goto exit; } result_node = NODE(result_datum); 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, struct cil_db *db) { 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, db, &attr_datum); if (rc != SEPOL_OK) { goto exit; } attr_node = NODE(attr_datum); 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, db); 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; } static int cil_resolve_expandtypeattribute(struct cil_tree_node *current, struct cil_db *db) { struct cil_expandtypeattribute *expandattr = current->data; struct cil_symtab_datum *attr_datum = NULL; struct cil_tree_node *attr_node = NULL; struct cil_list_item *curr; int used; int rc = SEPOL_ERR; cil_list_init(&expandattr->attr_datums, CIL_TYPE); cil_list_for_each(curr, expandattr->attr_strs) { rc = cil_resolve_name(current, (char *)curr->data, CIL_SYM_TYPES, db, &attr_datum); if (rc != SEPOL_OK) { goto exit; } attr_node = NODE(attr_datum); if (attr_node->flavor != CIL_TYPEATTRIBUTE) { rc = SEPOL_ERR; cil_log(CIL_ERR, "Attribute type not an attribute\n"); goto exit; } used = expandattr->expand ? CIL_ATTR_EXPAND_TRUE : CIL_ATTR_EXPAND_FALSE; cil_type_used(attr_datum, used); cil_list_append(expandattr->attr_datums, CIL_TYPE, attr_datum); } return SEPOL_OK; exit: return rc; } static int cil_resolve_aliasactual(struct cil_tree_node *current, struct cil_db *db, enum cil_flavor flavor, enum cil_flavor alias_flavor) { int rc = SEPOL_ERR; enum cil_sym_index sym_index; struct cil_aliasactual *aliasactual = current->data; struct cil_symtab_datum *alias_datum = NULL; struct cil_symtab_datum *actual_datum = NULL; struct cil_alias *alias; rc = cil_flavor_to_symtab_index(flavor, &sym_index); if (rc != SEPOL_OK) { goto exit; } rc = cil_resolve_name_keep_aliases(current, aliasactual->alias_str, sym_index, db, &alias_datum); if (rc != SEPOL_OK) { goto exit; } if (FLAVOR(alias_datum) != alias_flavor) { cil_log(CIL_ERR, "%s is not an alias\n",alias_datum->name); rc = SEPOL_ERR; goto exit; } rc = cil_resolve_name(current, aliasactual->actual_str, sym_index, db, &actual_datum); if (rc != SEPOL_OK) { goto exit; } if (FLAVOR(actual_datum) != flavor && FLAVOR(actual_datum) != alias_flavor) { cil_log(CIL_ERR, "%s is a %s, but aliases a %s\n", alias_datum->name, cil_node_to_string(NODE(alias_datum)), cil_node_to_string(NODE(actual_datum))); rc = SEPOL_ERR; goto exit; } alias = (struct cil_alias *)alias_datum; aliasactual->alias = alias_datum; if (alias->actual != NULL) { cil_log(CIL_ERR, "%s %s cannot bind more than one value\n", cil_node_to_string(NODE(alias_datum)), alias_datum->name); rc = SEPOL_ERR; goto exit; } alias->actual = actual_datum; aliasactual->actual = actual_datum; return SEPOL_OK; exit: return rc; } static int cil_resolve_alias_to_actual(struct cil_tree_node *current, enum cil_flavor flavor) { struct cil_alias *alias = current->data; struct cil_alias *a1 = current->data; struct cil_alias *a2 = current->data; struct cil_tree_node *a1_node = NULL; int steps = 0; int limit = 2; if (alias->actual == NULL) { cil_tree_log(current, CIL_ERR, "Alias declared but not used"); return SEPOL_ERR; } a1_node = a1->datum.nodes->head->data; while (flavor != a1_node->flavor) { if (a1->actual == NULL) { cil_tree_log(current, CIL_ERR, "Alias %s references an unused alias %s", alias->datum.name, a1->datum.name); return SEPOL_ERR; } 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, struct cil_db *db) { 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, db, &type_datum); if (rc != SEPOL_OK) { goto exit; } type_node = NODE(type_datum); 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, struct cil_db *db) { 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, db, &src_datum); if (rc != SEPOL_OK) { goto exit; } nametypetrans->src = src_datum; if (nametypetrans->tgt_str == CIL_KEY_SELF) { nametypetrans->tgt = db->selftype; } else { rc = cil_resolve_name(current, nametypetrans->tgt_str, CIL_SYM_TYPES, db, &tgt_datum); if (rc != SEPOL_OK) { goto exit; } nametypetrans->tgt = tgt_datum; } rc = cil_resolve_name(current, nametypetrans->obj_str, CIL_SYM_CLASSES, db, &obj_datum); if (rc != SEPOL_OK) { goto exit; } nametypetrans->obj = (struct cil_class*)obj_datum; if (!nametypetrans->name) { rc = cil_resolve_name(current, nametypetrans->name_str, CIL_SYM_STRINGS, db, &name_datum); if (rc != SEPOL_OK) { goto exit; } nametypetrans->name = name_datum; } rc = cil_resolve_name(current, nametypetrans->result_str, CIL_SYM_TYPES, db, &result_datum); if (rc != SEPOL_OK) { goto exit; } result_node = NODE(result_datum); 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, struct cil_db *db) { 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, db, &src_datum); if (rc != SEPOL_OK) { goto exit; } rangetrans->src = src_datum; rc = cil_resolve_name(current, rangetrans->exec_str, CIL_SYM_TYPES, db, &exec_datum); if (rc != SEPOL_OK) { goto exit; } rangetrans->exec = exec_datum; rc = cil_resolve_name(current, rangetrans->obj_str, CIL_SYM_CLASSES, db, &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, db, &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, db); if (rc != SEPOL_OK) { goto exit; } } } else { rc = cil_resolve_levelrange(current, rangetrans->range, db); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: return rc; } static 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, struct cil_db *db) { 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, db, &class_datum); if (rc != SEPOL_OK) { goto exit; } if (NODE(class_datum)->flavor != CIL_CLASS) { cil_log(CIL_ERR, "Class %s is not a kernel class and cannot be associated with common %s\n", clscom->class_str, clscom->common_str); rc = SEPOL_ERR; goto exit; } rc = cil_resolve_name(current, clscom->common_str, CIL_SYM_COMMONS, db, &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 associated with more than one common\n"); rc = SEPOL_ERR; goto exit; } class->common = common; clscom->class = class; clscom->common = common; cil_symtab_map(&class->perms, __class_update_perm_values, &common->num_perms); class->num_perms += common->num_perms; if (class->num_perms > CIL_PERMS_PER_CLASS) { cil_tree_log(current, CIL_ERR, "Too many permissions in class '%s' when including common permissions", class->datum.name); rc = SEPOL_ERR; goto exit; } return SEPOL_OK; exit: return rc; } int cil_resolve_classmapping(struct cil_tree_node *current, struct cil_db *db) { 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, db, &datum); if (rc != SEPOL_OK) { goto exit; } map = (struct cil_class*)datum; mapping->map_class = map; rc = cil_symtab_get_datum(&map->perms, mapping->map_perm_str, &datum); if (rc != SEPOL_OK) { goto exit; } mp = (struct cil_perm*)datum; mapping->map_perm = mp; rc = cil_resolve_classperms_list(current, mapping->classperms, db); 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, struct cil_db *db) { 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, db, &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, db, &role_datum); if (rc != SEPOL_OK) { goto exit; } userrole->role = role_datum; return SEPOL_OK; exit: return rc; } int cil_resolve_userlevel(struct cil_tree_node *current, struct cil_db *db) { struct cil_userlevel *usrlvl = current->data; struct cil_symtab_datum *user_datum = NULL; struct cil_symtab_datum *lvl_datum = NULL; struct cil_user *user = NULL; struct cil_tree_node *user_node = NULL; int rc = SEPOL_ERR; rc = cil_resolve_name(current, usrlvl->user_str, CIL_SYM_USERS, db, &user_datum); if (rc != SEPOL_OK) { goto exit; } user_node = NODE(user_datum); if (user_node->flavor != CIL_USER) { cil_log(CIL_ERR, "Userlevel must be a user\n"); rc = SEPOL_ERR; goto exit; } user = (struct cil_user*)user_datum; usrlvl->user = user; if (usrlvl->level_str != NULL) { rc = cil_resolve_name(current, usrlvl->level_str, CIL_SYM_LEVELS, db, &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, db); if (rc != SEPOL_OK) { goto exit; } } } else if (usrlvl->level != NULL) { rc = cil_resolve_level(current, usrlvl->level, db); 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, struct cil_db *db) { struct cil_userrange *userrange = current->data; struct cil_symtab_datum *user_datum = NULL; struct cil_symtab_datum *range_datum = NULL; struct cil_user *user = NULL; struct cil_tree_node *user_node = NULL; int rc = SEPOL_ERR; rc = cil_resolve_name(current, userrange->user_str, CIL_SYM_USERS, db, &user_datum); if (rc != SEPOL_OK) { goto exit; } user_node = NODE(user_datum); if (user_node->flavor != CIL_USER) { cil_log(CIL_ERR, "Userrange must be a user: %s\n", user_datum->fqn); rc = SEPOL_ERR; goto exit; } user = (struct cil_user*)user_datum; userrange->user = user; if (userrange->range_str != NULL) { rc = cil_resolve_name(current, userrange->range_str, CIL_SYM_LEVELRANGES, db, &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, db); if (rc != SEPOL_OK) { goto exit; } } } else if (userrange->range != NULL) { rc = cil_resolve_levelrange(current, userrange->range, db); 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, struct cil_db *db) { struct cil_userprefix *userprefix = current->data; struct cil_symtab_datum *user_datum = NULL; struct cil_tree_node *user_node = NULL; int rc = SEPOL_ERR; rc = cil_resolve_name(current, userprefix->user_str, CIL_SYM_USERS, db, &user_datum); if (rc != SEPOL_OK) { goto exit; } user_node = NODE(user_datum); if (user_node->flavor != CIL_USER) { cil_log(CIL_ERR, "Userprefix must be a user: %s\n", user_datum->fqn); rc = SEPOL_ERR; goto exit; } userprefix->user = (struct cil_user*)user_datum; exit: return rc; } int cil_resolve_selinuxuser(struct cil_tree_node *current, struct cil_db *db) { struct cil_selinuxuser *selinuxuser = current->data; struct cil_symtab_datum *user_datum = NULL; struct cil_symtab_datum *lvlrange_datum = NULL; struct cil_tree_node *user_node = NULL; int rc = SEPOL_ERR; rc = cil_resolve_name(current, selinuxuser->user_str, CIL_SYM_USERS, db, &user_datum); if (rc != SEPOL_OK) { goto exit; } user_node = NODE(user_datum); if (user_node->flavor != CIL_USER) { cil_log(CIL_ERR, "Selinuxuser must be a user: %s\n", user_datum->fqn); rc = SEPOL_ERR; goto exit; } selinuxuser->user = (struct cil_user*)user_datum; if (selinuxuser->range_str != NULL) { rc = cil_resolve_name(current, selinuxuser->range_str, CIL_SYM_LEVELRANGES, db, &lvlrange_datum); if (rc != SEPOL_OK) { goto exit; } selinuxuser->range = (struct cil_levelrange*)lvlrange_datum; /* This could still be an anonymous levelrange even if range_str is set, if range_str is a param_str*/ if (selinuxuser->range->datum.name == NULL) { rc = cil_resolve_levelrange(current, selinuxuser->range, db); if (rc != SEPOL_OK) { goto exit; } } } else if (selinuxuser->range != NULL) { rc = cil_resolve_levelrange(current, selinuxuser->range, db); if (rc != SEPOL_OK) { goto exit; } } rc = SEPOL_OK; exit: return rc; } int cil_resolve_roletype(struct cil_tree_node *current, struct cil_db *db) { 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, db, &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, db, &type_datum); if (rc != SEPOL_OK) { goto exit; } roletype->type = (struct cil_type*)type_datum; return SEPOL_OK; exit: return rc; } int cil_resolve_roletransition(struct cil_tree_node *current, struct cil_db *db) { 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, db, &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, db, &tgt_datum); if (rc != SEPOL_OK) { goto exit; } roletrans->tgt = tgt_datum; rc = cil_resolve_name(current, roletrans->obj_str, CIL_SYM_CLASSES, db, &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, db, &result_datum); if (rc != SEPOL_OK) { goto exit; } node = NODE(result_datum); if (node->flavor != CIL_ROLE) { rc = SEPOL_ERR; 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, struct cil_db *db) { 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, db, &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, db, &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, struct cil_db *db) { 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, db, &attr_datum); if (rc != SEPOL_OK) { goto exit; } attr_node = NODE(attr_datum); 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, db); 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; } static 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); } static 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; } static void __cil_ordered_find_next_match(struct cil_list_item **i, struct cil_list_item **j, struct cil_list_item **p) { struct cil_list_item *pstart = *p; struct cil_list_item *jstart = *j; while (*i) { *p = pstart; *j = jstart; while (*j) { if ((*i)->data == (*j)->data) { return; } *p = *j; *j = (*j)->next; } *i = (*i)->next; } } static int __cil_ordered_lists_merge(struct cil_list *old, struct cil_list *new) { struct cil_list_item *ofirst = old->head; struct cil_list_item *ocurr = NULL; struct cil_list_item *oprev = 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 */ return __cil_ordered_list_insert(old, NULL, nfirst, NULL); } ncurr = nfirst; ocurr = ofirst; oprev = NULL; while (ncurr && ocurr) { __cil_ordered_find_next_match(&ncurr, &ocurr, &oprev); if (!ncurr || !ocurr) { break; } if (ncurr != nfirst) { rc = __cil_ordered_list_insert(old, oprev, nfirst, ncurr); if (rc != SEPOL_OK) { return rc; } } ncurr = ncurr->next; nfirst = ncurr; oprev = ocurr; ocurr = ocurr->next; } if (!ncurr) { if (!nfirst) { /* Done */ return SEPOL_OK; } else { /* Can't merge yet */ return SEPOL_ERR; } } if (ncurr && !ocurr) { /* some remaining */ rc = __cil_ordered_list_insert(old, oprev, ncurr, NULL); if (rc != SEPOL_OK) { return rc; } } return SEPOL_OK; } static int insert_unordered(struct cil_list *merged, struct cil_list *unordered_list) { struct cil_tree_node *node; struct cil_ordered *unordered; struct cil_list_item *curr = NULL; struct cil_list_item *item = NULL; struct cil_list_item *ret = NULL; int rc = SEPOL_ERR; cil_list_for_each(curr, unordered_list) { node = curr->data; unordered = node->data; cil_list_for_each(item, unordered->datums) { if (cil_list_contains(merged, item->data)) { /* item was declared in an ordered statement, which supersedes * all unordered statements */ if (item->flavor == CIL_CLASS) { cil_log(CIL_WARN, "Ignoring '%s' as it has already been declared in classorder.\n", ((struct cil_class*)(item->data))->datum.name); } continue; } ret = __cil_ordered_item_insert(merged, merged->tail, item); if (ret == NULL) { rc = SEPOL_ERR; goto exit; } } } rc = SEPOL_OK; exit: return rc; } static struct cil_list *__cil_ordered_lists_merge_all(struct cil_list **ordered_lists, struct cil_list **unordered_lists) { struct cil_list *composite = NULL; struct cil_tree_node *node; struct cil_ordered *ordered; struct cil_list_item *curr = NULL; int changed = CIL_TRUE; int waiting = 1; int rc = SEPOL_ERR; cil_list_init(&composite, (*ordered_lists)->flavor); while (waiting && changed == CIL_TRUE) { changed = CIL_FALSE; waiting = 0; cil_list_for_each(curr, *ordered_lists) { node = curr->data; ordered = node->data; if (ordered->merged == CIL_FALSE) { rc = __cil_ordered_lists_merge(composite, ordered->datums); if (rc != SEPOL_OK) { /* Can't merge yet */ waiting++; } else { ordered->merged = CIL_TRUE; changed = CIL_TRUE; } } } if (waiting > 0 && changed == CIL_FALSE) { cil_list_for_each(curr, *ordered_lists) { node = curr->data; ordered = node->data; if (ordered->merged == CIL_FALSE) { cil_tree_log(node, CIL_ERR, "Unable to merge ordered list"); } } goto exit; } } rc = cil_verify_completed_ordered_list(composite, *ordered_lists); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Unable to validate ordering\n"); goto exit; } if (unordered_lists != NULL) { rc = insert_unordered(composite, *unordered_lists); if (rc != SEPOL_OK) { goto exit; } } return composite; exit: cil_list_destroy(&composite, CIL_FALSE); return NULL; } int cil_resolve_classorder(struct cil_tree_node *current, struct cil_db *db, struct cil_list *classorder_list, struct cil_list *unordered_classorder_list) { struct cil_ordered *ordered = current->data; struct cil_list_item *curr = NULL; struct cil_symtab_datum *datum = NULL; int rc = SEPOL_ERR; int unordered = CIL_FALSE; cil_list_init(&ordered->datums, CIL_DATUM); cil_list_for_each(curr, ordered->strs) { if (curr->data == CIL_KEY_UNORDERED) { unordered = CIL_TRUE; continue; } rc = cil_resolve_name(current, (char *)curr->data, CIL_SYM_CLASSES, db, &datum); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Failed to resolve class %s in classorder\n", (char *)curr->data); rc = SEPOL_ERR; goto exit; } if (FLAVOR(datum) != CIL_CLASS) { cil_log(CIL_ERR, "%s is not a class. Only classes are allowed in classorder statements\n", datum->name); rc = SEPOL_ERR; goto exit; } cil_list_append(ordered->datums, CIL_CLASS, datum); } if (unordered) { cil_list_append(unordered_classorder_list, CIL_CLASSORDER, current); } else { cil_list_append(classorder_list, CIL_CLASSORDER, current); } return SEPOL_OK; exit: cil_list_destroy(&ordered->datums, CIL_FALSE); return rc; } int cil_resolve_sidorder(struct cil_tree_node *current, struct cil_db *db, struct cil_list *sidorder_list) { struct cil_ordered *ordered = current->data; struct cil_list_item *curr = NULL; struct cil_symtab_datum *datum = NULL; int rc = SEPOL_ERR; cil_list_init(&ordered->datums, CIL_DATUM); cil_list_for_each(curr, ordered->strs) { rc = cil_resolve_name(current, (char *)curr->data, CIL_SYM_SIDS, db, &datum); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Failed to resolve sid %s in sidorder\n", (char *)curr->data); goto exit; } if (FLAVOR(datum) != CIL_SID) { cil_log(CIL_ERR, "%s is not a sid. Only sids are allowed in sidorder statements\n", datum->name); rc = SEPOL_ERR; goto exit; } cil_list_append(ordered->datums, CIL_SID, datum); } cil_list_append(sidorder_list, CIL_SIDORDER, current); return SEPOL_OK; exit: cil_list_destroy(&ordered->datums, CIL_FALSE); return rc; } static 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, struct cil_db *db, struct cil_list *catorder_list) { struct cil_ordered *ordered = current->data; struct cil_list_item *curr = NULL; struct cil_symtab_datum *datum; int rc = SEPOL_ERR; cil_list_init(&ordered->datums, CIL_DATUM); cil_list_for_each(curr, ordered->strs) { rc = cil_resolve_name(current, (char *)curr->data, CIL_SYM_CATS, db, &datum); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Failed to resolve category %s in categoryorder\n", (char *)curr->data); goto exit; } if (FLAVOR(datum) != CIL_CAT) { cil_log(CIL_ERR, "%s is not a category. Only categories are allowed in categoryorder statements\n", datum->name); rc = SEPOL_ERR; goto exit; } cil_list_append(ordered->datums, CIL_CAT, datum); } cil_list_append(catorder_list, CIL_CATORDER, current); return SEPOL_OK; exit: cil_list_destroy(&ordered->datums, CIL_FALSE); return rc; } int cil_resolve_sensitivityorder(struct cil_tree_node *current, struct cil_db *db, struct cil_list *sensitivityorder_list) { struct cil_ordered *ordered = current->data; struct cil_list_item *curr = NULL; struct cil_symtab_datum *datum = NULL; int rc = SEPOL_ERR; cil_list_init(&ordered->datums, CIL_DATUM); cil_list_for_each(curr, ordered->strs) { rc = cil_resolve_name(current, (char *)curr->data, CIL_SYM_SENS, db, &datum); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Failed to resolve sensitivity %s in sensitivityorder\n", (char *)curr->data); goto exit; } if (FLAVOR(datum) != CIL_SENS) { cil_log(CIL_ERR, "%s is not a sensitivity. Only sensitivities are allowed in sensitivityorder statements\n", datum->name); rc = SEPOL_ERR; goto exit; } cil_list_append(ordered->datums, CIL_SENS, datum); } cil_list_append(sensitivityorder_list, CIL_SENSITIVITYORDER, current); return SEPOL_OK; exit: cil_list_destroy(&ordered->datums, CIL_FALSE); return rc; } static int cil_resolve_cats(struct cil_tree_node *current, struct cil_cats *cats, struct cil_db *db) { int rc = SEPOL_ERR; rc = cil_resolve_expr(CIL_CATSET, cats->str_expr, &cats->datum_expr, current, db); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: return rc; } int cil_resolve_catset(struct cil_tree_node *current, struct cil_catset *catset, struct cil_db *db) { return cil_resolve_cats(current, catset->cats, db); } int cil_resolve_senscat(struct cil_tree_node *current, struct cil_db *db) { 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, db, &sens_datum); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Failed to find sensitivity\n"); goto exit; } rc = cil_resolve_cats(current, senscat->cats, db); 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, struct cil_db *db) { struct cil_symtab_datum *sens_datum = NULL; int rc = SEPOL_ERR; if (level->sens) { return SEPOL_OK; } rc = cil_resolve_name(current, (char*)level->sens_str, CIL_SYM_SENS, db, &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, db); 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, struct cil_db *db) { 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, db, &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, db); if (rc != SEPOL_OK) { goto exit; } } } else if (lvlrange->low != NULL) { rc = cil_resolve_level(current, lvlrange->low, db); if (rc != SEPOL_OK) { goto exit; } } if (lvlrange->high_str != NULL) { rc = cil_resolve_name(current, lvlrange->high_str, CIL_SYM_LEVELS, db, &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, db); if (rc != SEPOL_OK) { goto exit; } } } else if (lvlrange->high != NULL) { rc = cil_resolve_level(current, lvlrange->high, db); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: return rc; } int cil_resolve_constrain(struct cil_tree_node *current, struct cil_db *db) { struct cil_constrain *cons = current->data; int rc = SEPOL_ERR; rc = cil_resolve_classperms_list(current, cons->classperms, db); if (rc != SEPOL_OK) { goto exit; } rc = cil_resolve_expr(CIL_CONSTRAIN, cons->str_expr, &cons->datum_expr, current, db); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: return rc; } int cil_resolve_validatetrans(struct cil_tree_node *current, struct cil_db *db) { struct cil_validatetrans *validtrans = current->data; struct cil_symtab_datum *class_datum = NULL; int rc = SEPOL_ERR; rc = cil_resolve_name(current, validtrans->class_str, CIL_SYM_CLASSES, db, &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, db); 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, struct cil_db *db) { struct cil_symtab_datum *user_datum = NULL; struct cil_symtab_datum *role_datum = NULL; struct cil_symtab_datum *type_datum = NULL; struct cil_tree_node *node = NULL; struct cil_symtab_datum *lvlrange_datum = NULL; int rc = SEPOL_ERR; rc = cil_resolve_name(current, context->user_str, CIL_SYM_USERS, db, &user_datum); if (rc != SEPOL_OK) { goto exit; } node = NODE(user_datum); if (node->flavor != CIL_USER) { cil_log(CIL_ERR, "Context user must be a user: %s\n", user_datum->fqn); rc = SEPOL_ERR; goto exit; } context->user = (struct cil_user*)user_datum; rc = cil_resolve_name(current, context->role_str, CIL_SYM_ROLES, db, &role_datum); if (rc != SEPOL_OK) { goto exit; } node = NODE(role_datum); if (node->flavor != CIL_ROLE) { rc = SEPOL_ERR; cil_log(CIL_ERR, "Context role not a role: %s\n", role_datum->fqn); goto exit; } context->role = (struct cil_role*)role_datum; rc = cil_resolve_name(current, context->type_str, CIL_SYM_TYPES, db, &type_datum); if (rc != SEPOL_OK) { goto exit; } node = NODE(type_datum); if (node->flavor != CIL_TYPE && node->flavor != CIL_TYPEALIAS) { rc = SEPOL_ERR; cil_log(CIL_ERR, "Type not a type or type alias\n"); goto exit; } context->type = type_datum; if (context->range_str != NULL) { rc = cil_resolve_name(current, context->range_str, CIL_SYM_LEVELRANGES, db, &lvlrange_datum); if (rc != SEPOL_OK) { goto exit; } context->range = (struct cil_levelrange*)lvlrange_datum; /* This could still be an anonymous levelrange even if levelrange_str is set, if levelrange_str is a param_str*/ if (context->range->datum.name == NULL) { rc = cil_resolve_levelrange(current, context->range, db); if (rc != SEPOL_OK) { goto exit; } } } else if (context->range != NULL) { rc = cil_resolve_levelrange(current, context->range, db); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: return rc; } int cil_resolve_filecon(struct cil_tree_node *current, struct cil_db *db) { struct cil_filecon *filecon = current->data; struct cil_symtab_datum *context_datum = NULL; struct cil_symtab_datum *path_datum = NULL; int rc = SEPOL_ERR; if (!filecon->path) { rc = cil_resolve_name(current, filecon->path_str, CIL_SYM_STRINGS, db, &path_datum); if (rc != SEPOL_OK) { return rc; } filecon->path = path_datum; } if (filecon->context_str != NULL) { rc = cil_resolve_name(current, filecon->context_str, CIL_SYM_CONTEXTS, db, &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, db); if (rc != SEPOL_OK) { return rc; } } return SEPOL_OK; } int cil_resolve_ibpkeycon(struct cil_tree_node *current, struct cil_db *db) { struct cil_ibpkeycon *ibpkeycon = current->data; struct cil_symtab_datum *context_datum = NULL; int rc = SEPOL_ERR; if (ibpkeycon->context_str) { rc = cil_resolve_name(current, ibpkeycon->context_str, CIL_SYM_CONTEXTS, db, &context_datum); if (rc != SEPOL_OK) goto exit; ibpkeycon->context = (struct cil_context *)context_datum; } else { rc = cil_resolve_context(current, ibpkeycon->context, db); if (rc != SEPOL_OK) goto exit; } return SEPOL_OK; exit: return rc; } int cil_resolve_portcon(struct cil_tree_node *current, struct cil_db *db) { 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, db, &context_datum); if (rc != SEPOL_OK) { goto exit; } portcon->context = (struct cil_context*)context_datum; } else { rc = cil_resolve_context(current, portcon->context, db); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: return rc; } int cil_resolve_genfscon(struct cil_tree_node *current, struct cil_db *db) { 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, db, &context_datum); if (rc != SEPOL_OK) { goto exit; } genfscon->context = (struct cil_context*)context_datum; } else { rc = cil_resolve_context(current, genfscon->context, db); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: return rc; } int cil_resolve_nodecon(struct cil_tree_node *current, struct cil_db *db) { 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, db, &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, db, &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, db, &context_datum); if (rc != SEPOL_OK) { goto exit; } nodecon->context = (struct cil_context*)context_datum; } else { rc = cil_resolve_context(current, nodecon->context, db); 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, struct cil_db *db) { 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, db, &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, db); if (rc != SEPOL_OK) { goto exit; } } if (netifcon->packet_context_str != NULL) { rc = cil_resolve_name(current, netifcon->packet_context_str, CIL_SYM_CONTEXTS, db, &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, db); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: return rc; } int cil_resolve_ibendportcon(struct cil_tree_node *current, struct cil_db *db) { struct cil_ibendportcon *ibendportcon = current->data; struct cil_symtab_datum *con_datum = NULL; int rc = SEPOL_ERR; if (ibendportcon->context_str) { rc = cil_resolve_name(current, ibendportcon->context_str, CIL_SYM_CONTEXTS, db, &con_datum); if (rc != SEPOL_OK) goto exit; ibendportcon->context = (struct cil_context *)con_datum; } else { rc = cil_resolve_context(current, ibendportcon->context, db); if (rc != SEPOL_OK) goto exit; } return SEPOL_OK; exit: return rc; } int cil_resolve_pirqcon(struct cil_tree_node *current, struct cil_db *db) { 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, db, &context_datum); if (rc != SEPOL_OK) { goto exit; } pirqcon->context = (struct cil_context*)context_datum; } else { rc = cil_resolve_context(current, pirqcon->context, db); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: return rc; } int cil_resolve_iomemcon(struct cil_tree_node *current, struct cil_db *db) { 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, db, &context_datum); if (rc != SEPOL_OK) { goto exit; } iomemcon->context = (struct cil_context*)context_datum; } else { rc = cil_resolve_context(current, iomemcon->context, db); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: return rc; } int cil_resolve_ioportcon(struct cil_tree_node *current, struct cil_db *db) { 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, db, &context_datum); if (rc != SEPOL_OK) { goto exit; } ioportcon->context = (struct cil_context*)context_datum; } else { rc = cil_resolve_context(current, ioportcon->context, db); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: return rc; } int cil_resolve_pcidevicecon(struct cil_tree_node *current, struct cil_db *db) { 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, db, &context_datum); if (rc != SEPOL_OK) { goto exit; } pcidevicecon->context = (struct cil_context*)context_datum; } else { rc = cil_resolve_context(current, pcidevicecon->context, db); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: return rc; } static int cil_resolve_devicetreecon(struct cil_tree_node *current, struct cil_db *db) { struct cil_devicetreecon *devicetreecon = current->data; struct cil_symtab_datum *context_datum = NULL; int rc = SEPOL_ERR; if (devicetreecon->context_str != NULL) { rc = cil_resolve_name(current, devicetreecon->context_str, CIL_SYM_CONTEXTS, db, &context_datum); if (rc != SEPOL_OK) { goto exit; } devicetreecon->context = (struct cil_context*)context_datum; } else { rc = cil_resolve_context(current, devicetreecon->context, db); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: return rc; } int cil_resolve_fsuse(struct cil_tree_node *current, struct cil_db *db) { 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, db, &context_datum); if (rc != SEPOL_OK) { goto exit; } fsuse->context = (struct cil_context*)context_datum; } else { rc = cil_resolve_context(current, fsuse->context, db); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: return rc; } int cil_resolve_sidcontext(struct cil_tree_node *current, struct cil_db *db) { 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, db, &sid_datum); if (rc != SEPOL_OK) { goto exit; } sid = (struct cil_sid*)sid_datum; sidcon->sid = sid; if (sidcon->context_str != NULL) { rc = cil_resolve_name(current, sidcon->context_str, CIL_SYM_CONTEXTS, db, &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, db); 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; } static int cil_resolve_blockinherit_link(struct cil_tree_node *current, struct cil_db *db) { struct cil_blockinherit *inherit = current->data; struct cil_symtab_datum *block_datum = NULL; struct cil_tree_node *node = NULL; int rc = SEPOL_ERR; rc = cil_resolve_name(current, inherit->block_str, CIL_SYM_BLOCKS, db, &block_datum); if (rc != SEPOL_OK) { goto exit; } node = NODE(block_datum); if (node->flavor != CIL_BLOCK) { cil_log(CIL_ERR, "%s is not a block\n", cil_node_to_string(node)); rc = SEPOL_ERR; goto exit; } inherit->block = (struct cil_block *)block_datum; if (inherit->block->bi_nodes == NULL) { cil_list_init(&inherit->block->bi_nodes, CIL_NODE); } cil_list_append(inherit->block->bi_nodes, CIL_NODE, current); return SEPOL_OK; exit: return rc; } static int cil_resolve_blockinherit_copy(struct cil_tree_node *current, struct cil_db *db) { struct cil_block *block = current->data; struct cil_list_item *item = NULL; int rc = SEPOL_ERR; // This block is not inherited if (block->bi_nodes == NULL) { rc = SEPOL_OK; goto exit; } // Make sure this is the original block and not a merged block from a blockinherit if (current != block->datum.nodes->head->data) { rc = SEPOL_OK; goto exit; } cil_list_for_each(item, block->bi_nodes) { rc = cil_copy_ast(db, current, item->data); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Failed to copy block contents into blockinherit\n"); goto exit; } } return SEPOL_OK; exit: return rc; } static void cil_mark_subtree_abstract(struct cil_tree_node *node) { struct cil_block *block = node->data; block->is_abstract = CIL_TRUE; for (node = node->cl_head; node; node = node->next) { if (node->flavor == CIL_BLOCK) { cil_mark_subtree_abstract(node); } } } static int cil_resolve_blockabstract(struct cil_tree_node *current, struct cil_db *db, struct cil_list *abstract_blocks) { 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, db, &block_datum); if (rc != SEPOL_OK) { goto exit; } block_node = NODE(block_datum); if (block_node->flavor != CIL_BLOCK) { cil_log(CIL_ERR, "Failed to resolve blockabstract to a block, rc: %d\n", rc); rc = SEPOL_ERR; goto exit; } abstract->block = (struct cil_block *)block_datum; cil_list_append(abstract_blocks, CIL_NODE, block_node); return SEPOL_OK; exit: return rc; } int cil_resolve_in(struct cil_tree_node *current, struct cil_db *db) { struct cil_in *in = 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, in->block_str, CIL_SYM_BLOCKS, db, &block_datum); if (rc != SEPOL_OK) { goto exit; } in->block = (struct cil_block *)block_datum; block_node = NODE(block_datum); if (block_node->flavor == CIL_OPTIONAL) { if (block_datum->nodes && block_datum->nodes->head != block_datum->nodes->tail) { cil_tree_log(current, CIL_ERR, "Multiple optional blocks referred to by in-statement"); cil_tree_log(block_node, CIL_ERR, "First optional block"); rc = SEPOL_ERR; goto exit; } } rc = cil_copy_ast(db, current, block_node); if (rc != SEPOL_OK) { cil_tree_log(current, CIL_ERR, "Failed to copy in-statement"); goto exit; } cil_tree_children_destroy(current); return SEPOL_OK; exit: return rc; } static int cil_resolve_in_list(struct cil_list *in_list, struct cil_db *db) { 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, in_list) { if (curr->flavor != CIL_NODE) { continue; } node = curr->data; in = node->data; rc = cil_resolve_name(node, in->block_str, CIL_SYM_BLOCKS, db, &block_datum); if (rc != SEPOL_OK) { unresolved++; last_failed_node = node; } else { rc = cil_resolve_in(node, db); if (rc != SEPOL_OK) { goto exit; } resolved++; curr->data = NULL; curr->flavor = CIL_NONE; } } if (unresolved > 0 && resolved == 0) { cil_tree_log(last_failed_node, CIL_ERR, "Failed to resolve in-statement"); rc = SEPOL_ERR; goto exit; } } while (unresolved > 0); rc = SEPOL_OK; exit: return rc; } static int cil_resolve_bounds(struct cil_tree_node *current, struct cil_db *db, enum cil_flavor flavor, enum cil_flavor attr_flavor) { int rc = SEPOL_ERR; struct cil_bounds *bounds = current->data; enum cil_sym_index index; struct cil_symtab_datum *parent_datum = NULL; struct cil_symtab_datum *child_datum = NULL; rc = cil_flavor_to_symtab_index(flavor, &index); if (rc != SEPOL_OK) { goto exit; } rc = cil_resolve_name(current, bounds->parent_str, index, db, &parent_datum); if (rc != SEPOL_OK) { goto exit; } if (FLAVOR(parent_datum) == attr_flavor) { cil_log(CIL_ERR, "Bounds parent %s is an attribute\n", bounds->parent_str); rc = SEPOL_ERR; goto exit; } rc = cil_resolve_name(current, bounds->child_str, index, db, &child_datum); if (rc != SEPOL_OK) { goto exit; } if (FLAVOR(child_datum) == attr_flavor) { cil_log(CIL_ERR, "Bounds child %s is an attribute\n", bounds->child_str); rc = SEPOL_ERR; goto exit; } switch (flavor) { case CIL_USER: { struct cil_user *user = (struct cil_user *)child_datum; if (user->bounds != NULL) { cil_tree_log(NODE(user->bounds), CIL_ERR, "User %s already bound by parent", bounds->child_str); rc = SEPOL_ERR; goto exit; } user->bounds = (struct cil_user *)parent_datum; break; } case CIL_ROLE: { struct cil_role *role = (struct cil_role *)child_datum; if (role->bounds != NULL) { cil_tree_log(NODE(role->bounds), CIL_ERR, "Role %s already bound by parent", bounds->child_str); rc = SEPOL_ERR; goto exit; } role->bounds = (struct cil_role *)parent_datum; break; } case CIL_TYPE: { struct cil_type *type = (struct cil_type *)child_datum; if (type->bounds != NULL) { cil_tree_log(NODE(type->bounds), CIL_ERR, "Type %s already bound by parent", bounds->child_str); rc = SEPOL_ERR; goto exit; } type->bounds = (struct cil_type *)parent_datum; break; } default: break; } return SEPOL_OK; exit: cil_tree_log(current, CIL_ERR, "Bad bounds statement"); return rc; } static int cil_resolve_default(struct cil_tree_node *current, struct cil_db *db) { 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, db, &datum); if (rc != SEPOL_OK) { goto exit; } cil_list_append(def->class_datums, CIL_CLASS, datum); } return SEPOL_OK; exit: return rc; } static int cil_resolve_defaultrange(struct cil_tree_node *current, struct cil_db *db) { 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, db, &datum); if (rc != SEPOL_OK) { goto exit; } cil_list_append(def->class_datums, CIL_CLASS, datum); } return SEPOL_OK; exit: return rc; } static void cil_print_recursive_call(struct cil_tree_node *call_node, struct cil_tree_node *terminating_node) { struct cil_list *trace = NULL; struct cil_list_item * item = NULL; struct cil_tree_node *curr = NULL; cil_list_init(&trace, CIL_NODE); for (curr = call_node; curr != terminating_node; curr = curr->parent) { if (curr->flavor == CIL_CALL) { if (curr != call_node) { cil_list_prepend(trace, CIL_NODE, NODE(((struct cil_call *)curr->data)->macro)); } cil_list_prepend(trace, CIL_NODE, curr); } } if (terminating_node->flavor == CIL_MACRO) { cil_list_prepend(trace, CIL_NODE, terminating_node); } else { cil_list_prepend(trace, CIL_NODE, NODE(((struct cil_call *)terminating_node->data)->macro)); } cil_list_for_each(item, trace) { curr = item->data; if (curr->flavor == CIL_MACRO) { cil_tree_log(curr, CIL_ERR, "macro %s", DATUM(curr->data)->name); } else { cil_tree_log(curr, CIL_ERR, "call %s", ((struct cil_call *)curr->data)->macro_str); } } cil_list_destroy(&trace, CIL_FALSE); } static int cil_check_recursive_call(struct cil_tree_node *call_node, struct cil_tree_node *macro_node) { struct cil_tree_node *curr = NULL; struct cil_call * call = NULL; int rc = SEPOL_ERR; for (curr = call_node; curr != NULL; curr = curr->parent) { if (curr->flavor == CIL_CALL) { if (curr == call_node) { continue; } call = curr->data; if (call->macro != macro_node->data) { continue; } } else if (curr->flavor == CIL_MACRO) { if (curr != macro_node) { rc = SEPOL_OK; goto exit; } } else { continue; } cil_log(CIL_ERR, "Recursive macro call found:\n"); cil_print_recursive_call(call_node, curr); rc = SEPOL_ERR; goto exit; } rc = SEPOL_OK; exit: return rc; } static int cil_build_call_args(struct cil_tree_node *call_node, struct cil_call *call, struct cil_macro *macro, struct cil_db *db) { struct cil_list_item *item; struct cil_args *arg = NULL; struct cil_tree_node *arg_node = NULL; int rc = SEPOL_ERR; if (macro->params == NULL) { if (call->args_tree == NULL) { return SEPOL_OK; } else { cil_tree_log(call_node, CIL_ERR, "Unexpected arguments"); return SEPOL_ERR; } } if (call->args_tree == NULL) { cil_tree_log(call_node, CIL_ERR, "Missing arguments"); return SEPOL_ERR; } arg_node = call->args_tree->root->cl_head; cil_list_init(&call->args, CIL_LIST_ITEM); cil_list_for_each(item, macro->params) { enum cil_flavor flavor = ((struct cil_param*)item->data)->flavor; if (arg_node == NULL) { cil_tree_log(call_node, CIL_ERR, "Missing arguments"); rc = SEPOL_ERR; goto exit; } if (item->flavor != CIL_PARAM) { rc = SEPOL_ERR; goto exit; } cil_args_init(&arg); switch (flavor) { case CIL_DECLARED_STRING: { struct cil_symtab_datum *string; if (arg_node->data == NULL) { cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter"); cil_destroy_args(arg); rc = SEPOL_ERR; goto exit; } string = cil_gen_declared_string(db, arg_node->data, call_node); if (string) { arg->arg = string; } else { arg->arg_str = arg_node->data; } } break; case CIL_TYPE: if (arg_node->data == NULL) { cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter"); cil_destroy_args(arg); rc = SEPOL_ERR; goto exit; } arg->arg_str = arg_node->data; break; case CIL_ROLE: if (arg_node->data == NULL) { cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter"); cil_destroy_args(arg); rc = SEPOL_ERR; goto exit; } arg->arg_str = arg_node->data; break; case CIL_USER: if (arg_node->data == NULL) { cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter"); cil_destroy_args(arg); rc = SEPOL_ERR; goto exit; } arg->arg_str = arg_node->data; break; case CIL_SENS: if (arg_node->data == NULL) { cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter"); cil_destroy_args(arg); rc = SEPOL_ERR; goto exit; } arg->arg_str = arg_node->data; break; case CIL_CAT: if (arg_node->data == NULL) { cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter"); cil_destroy_args(arg); rc = SEPOL_ERR; goto exit; } arg->arg_str = arg_node->data; break; case CIL_BOOL: if (arg_node->data == NULL) { cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter"); cil_destroy_args(arg); rc = SEPOL_ERR; goto exit; } arg->arg_str = arg_node->data; break; case CIL_CATSET: { if (arg_node->cl_head != NULL) { struct cil_catset *catset = NULL; struct cil_tree_node *cat_node = NULL; cil_catset_init(&catset); rc = cil_fill_cats(arg_node, &catset->cats); if (rc != SEPOL_OK) { cil_destroy_catset(catset); cil_destroy_args(arg); goto exit; } cil_tree_node_init(&cat_node); cat_node->flavor = CIL_CATSET; cat_node->data = catset; cil_list_append(((struct cil_symtab_datum*)catset)->nodes, CIL_LIST_ITEM, cat_node); arg->arg = (struct cil_symtab_datum*)catset; } else if (arg_node->data == NULL) { cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter"); cil_destroy_args(arg); rc = SEPOL_ERR; goto exit; } else { arg->arg_str = arg_node->data; } break; } case CIL_LEVEL: { if (arg_node->cl_head != NULL) { struct cil_level *level = NULL; struct cil_tree_node *lvl_node = NULL; cil_level_init(&level); rc = cil_fill_level(arg_node->cl_head, level); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Failed to create anonymous level, rc: %d\n", rc); cil_destroy_level(level); cil_destroy_args(arg); goto exit; } cil_tree_node_init(&lvl_node); lvl_node->flavor = CIL_LEVEL; lvl_node->data = level; cil_list_append(((struct cil_symtab_datum*)level)->nodes, CIL_LIST_ITEM, lvl_node); arg->arg = (struct cil_symtab_datum*)level; } else if (arg_node->data == NULL) { cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter"); cil_destroy_args(arg); rc = SEPOL_ERR; goto exit; } else { arg->arg_str = arg_node->data; } break; } case CIL_LEVELRANGE: { if (arg_node->cl_head != NULL) { struct cil_levelrange *range = NULL; struct cil_tree_node *range_node = NULL; cil_levelrange_init(&range); rc = cil_fill_levelrange(arg_node->cl_head, range); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Failed to create anonymous levelrange, rc: %d\n", rc); cil_destroy_levelrange(range); cil_destroy_args(arg); goto exit; } cil_tree_node_init(&range_node); range_node->flavor = CIL_LEVELRANGE; range_node->data = range; cil_list_append(((struct cil_symtab_datum*)range)->nodes, CIL_LIST_ITEM, range_node); arg->arg = (struct cil_symtab_datum*)range; } else if (arg_node->data == NULL) { cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter"); cil_destroy_args(arg); rc = SEPOL_ERR; goto exit; } else { arg->arg_str = arg_node->data; } break; } case CIL_IPADDR: { if (arg_node->data == NULL) { cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter"); cil_destroy_args(arg); rc = SEPOL_ERR; goto exit; } else if (strchr(arg_node->data, '.') || strchr(arg_node->data, ':')) { struct cil_ipaddr *ipaddr = NULL; struct cil_tree_node *addr_node = NULL; cil_ipaddr_init(&ipaddr); rc = cil_fill_ipaddr(arg_node, ipaddr); if (rc != SEPOL_OK) { cil_tree_log(call_node, CIL_ERR, "Failed to create anonymous ip address"); cil_destroy_ipaddr(ipaddr); cil_destroy_args(arg); goto exit; } cil_tree_node_init(&addr_node); addr_node->flavor = CIL_IPADDR; addr_node->data = ipaddr; cil_list_append(DATUM(ipaddr)->nodes, CIL_LIST_ITEM, addr_node); arg->arg = DATUM(ipaddr); } else { arg->arg_str = arg_node->data; } break; } case CIL_CLASS: if (arg_node->data == NULL) { cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter"); cil_destroy_args(arg); rc = SEPOL_ERR; goto exit; } arg->arg_str = arg_node->data; break; case CIL_MAP_CLASS: if (arg_node->data == NULL) { cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter"); cil_destroy_args(arg); rc = SEPOL_ERR; goto exit; } arg->arg_str = arg_node->data; break; case CIL_CLASSPERMISSION: { if (arg_node->cl_head != NULL) { struct cil_classpermission *cp = NULL; struct cil_tree_node *cp_node = NULL; cil_classpermission_init(&cp); rc = cil_fill_classperms_list(arg_node, &cp->classperms); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Failed to create anonymous classpermission\n"); cil_destroy_classpermission(cp); cil_destroy_args(arg); goto exit; } cil_tree_node_init(&cp_node); cp_node->flavor = CIL_CLASSPERMISSION; cp_node->data = cp; cil_list_append(cp->datum.nodes, CIL_LIST_ITEM, cp_node); arg->arg = (struct cil_symtab_datum*)cp; } else if (arg_node->data == NULL) { cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter"); cil_destroy_args(arg); rc = SEPOL_ERR; goto exit; } else { arg->arg_str = arg_node->data; } break; } default: cil_log(CIL_ERR, "Unexpected flavor: %d\n", (((struct cil_param*)item->data)->flavor)); cil_destroy_args(arg); rc = SEPOL_ERR; goto exit; } arg->param_str = ((struct cil_param*)item->data)->str; arg->flavor = flavor; cil_list_append(call->args, CIL_ARGS, arg); arg_node = arg_node->next; } if (arg_node != NULL) { cil_tree_log(call_node, CIL_ERR, "Unexpected arguments"); rc = SEPOL_ERR; goto exit; } return SEPOL_OK; exit: return rc; } static int cil_resolve_call(struct cil_tree_node *current, struct cil_db *db) { struct cil_call *call = current->data; struct cil_tree_node *macro_node = NULL; struct cil_symtab_datum *macro_datum = NULL; int rc = SEPOL_ERR; if (call->copied) { return SEPOL_OK; } rc = cil_resolve_name(current, call->macro_str, CIL_SYM_BLOCKS, db, ¯o_datum); if (rc != SEPOL_OK) { goto exit; } macro_node = NODE(macro_datum); if (macro_node->flavor != CIL_MACRO) { cil_tree_log(current, CIL_ERR, "Failed to resolve %s to a macro", call->macro_str); rc = SEPOL_ERR; goto exit; } call->macro = (struct cil_macro*)macro_datum; rc = cil_build_call_args(current, call, call->macro, db); if (rc != SEPOL_OK) { goto exit; } rc = cil_check_recursive_call(current, macro_node); if (rc != SEPOL_OK) { goto exit; } rc = cil_copy_ast(db, macro_node, current); if (rc != SEPOL_OK) { cil_tree_log(current, CIL_ERR, "Failed to copy macro %s to call", macro_datum->name); goto exit; } call->copied = 1; return SEPOL_OK; exit: return rc; } static int cil_resolve_call_args(struct cil_tree_node *current, struct cil_db *db) { struct cil_call *call = current->data; int rc = SEPOL_ERR; enum cil_sym_index sym_index = CIL_SYM_UNKNOWN; struct cil_list_item *item; if (call->args == NULL) { rc = SEPOL_OK; goto exit; } cil_list_for_each(item, 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_DECLARED_STRING: if (arg->arg != NULL) { continue; /* No need to resolve */ } else { sym_index = CIL_SYM_STRINGS; } 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) { struct cil_symtab_datum *datum; struct cil_tree_node *n; rc = cil_resolve_name(current, arg->arg_str, sym_index, db, &datum); if (rc != SEPOL_OK) { cil_tree_log(current, CIL_ERR, "Failed to resolve %s in call argument list", arg->arg_str); goto exit; } arg->arg = datum; n = NODE(datum); while (n && n->flavor != CIL_ROOT) { if (n == current) { symtab_t *s = datum->symtab; /* Call arg should not resolve to declaration in the call * Need to remove datum temporarily to resolve to a datum outside * the call. */ cil_symtab_remove_datum(datum); rc = cil_resolve_name(current, arg->arg_str, sym_index, db, &(arg->arg)); if (rc != SEPOL_OK) { cil_tree_log(current, CIL_ERR, "Failed to resolve %s in call argument list", arg->arg_str); goto exit; } rc = cil_symtab_insert(s, datum->name, datum, NULL); if (rc != SEPOL_OK) { cil_tree_log(current, CIL_ERR, "Failed to re-insert datum while resolving %s in call argument list", arg->arg_str); goto exit; } break; } n = n->parent; } } } return SEPOL_OK; exit: return rc; } int cil_resolve_name_call_args(struct cil_call *call, char *name, enum cil_sym_index sym_index, struct cil_symtab_datum **datum) { struct cil_list_item *item; enum cil_sym_index param_index = CIL_SYM_UNKNOWN; int rc = SEPOL_ERR; if (call == NULL || name == NULL) { goto exit; } if (call->args == NULL) { goto exit; } cil_list_for_each(item, call->args) { struct cil_args * arg = item->data; rc = cil_flavor_to_symtab_index(arg->flavor, ¶m_index); if (param_index == sym_index) { if (name == arg->param_str) { *datum = arg->arg; rc = *datum ? SEPOL_OK : SEPOL_ERR; 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, struct cil_db *db) { 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; struct cil_list *datum_sub_expr; enum cil_flavor op = CIL_NONE; 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, db, &res_datum); if (rc != SEPOL_OK) { goto exit; } if (sym_index == CIL_SYM_CATS && NODE(res_datum)->flavor == CIL_CATSET) { struct cil_catset *catset = (struct cil_catset *)res_datum; if (op == CIL_RANGE) { cil_tree_log(parent, CIL_ERR, "Category set not allowed in category range"); rc = SEPOL_ERR; goto exit; } if (!res_datum->name) { /* Anonymous category sets need to be resolved when encountered */ if (!catset->cats->datum_expr) { rc = cil_resolve_expr(expr_type, catset->cats->str_expr, &catset->cats->datum_expr, parent, db); if (rc != SEPOL_OK) { goto exit; } } cil_copy_list(catset->cats->datum_expr, &datum_sub_expr); cil_list_append(*datum_expr, CIL_LIST, datum_sub_expr); } else { cil_list_append(*datum_expr, CIL_DATUM, res_datum); } } else { if (sym_index == CIL_SYM_TYPES && (expr_type == CIL_CONSTRAIN || expr_type == CIL_VALIDATETRANS)) { cil_type_used(res_datum, CIL_ATTR_CONSTRAINT); } cil_list_append(*datum_expr, CIL_DATUM, res_datum); } break; case CIL_LIST: { rc = cil_resolve_expr(expr_type, curr->data, &datum_sub_expr, parent, db); if (rc != SEPOL_OK) { goto exit; } cil_list_append(*datum_expr, CIL_LIST, datum_sub_expr); break; } default: if (curr->flavor == CIL_OP) { op = (enum cil_flavor)(uintptr_t)curr->data; } cil_list_append(*datum_expr, curr->flavor, curr->data); break; } } return SEPOL_OK; exit: cil_list_destroy(datum_expr, CIL_FALSE); return rc; } int cil_resolve_boolif(struct cil_tree_node *current, struct cil_db *db) { 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, db); 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)(uintptr_t)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, struct cil_db *db) { 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; rc = cil_resolve_expr(CIL_TUNABLEIF, tif->str_expr, &tif->datum_expr, current, db); if (rc != SEPOL_OK) { goto exit; } result = __cil_evaluate_tunable_expr(tif->datum_expr->head); if (current->cl_head != NULL && current->cl_head->flavor == CIL_CONDBLOCK) { cb = current->cl_head->data; if (cb->flavor == CIL_CONDTRUE) { true_node = current->cl_head; } else if (cb->flavor == CIL_CONDFALSE) { false_node = current->cl_head; } } if (current->cl_head != NULL && current->cl_head->next != NULL && current->cl_head->next->flavor == CIL_CONDBLOCK) { cb = current->cl_head->next->data; if (cb->flavor == CIL_CONDTRUE) { true_node = current->cl_head->next; } else if (cb->flavor == CIL_CONDFALSE) { false_node = current->cl_head->next; } } if (result == CIL_TRUE) { if (true_node != NULL) { rc = cil_copy_ast(db, true_node, current->parent); if (rc != SEPOL_OK) { goto exit; } } } else { if (false_node != NULL) { rc = cil_copy_ast(db, false_node, current->parent); if (rc != SEPOL_OK) { goto exit; } } } cil_tree_children_destroy(current); current->cl_head = NULL; current->cl_tail = NULL; return SEPOL_OK; exit: return rc; } int cil_resolve_userattributeset(struct cil_tree_node *current, struct cil_db *db) { int rc = SEPOL_ERR; struct cil_userattributeset *attrusers = current->data; struct cil_symtab_datum *attr_datum = NULL; struct cil_tree_node *attr_node = NULL; struct cil_userattribute *attr = NULL; rc = cil_resolve_name(current, attrusers->attr_str, CIL_SYM_USERS, db, &attr_datum); if (rc != SEPOL_OK) { goto exit; } attr_node = NODE(attr_datum); if (attr_node->flavor != CIL_USERATTRIBUTE) { rc = SEPOL_ERR; cil_log(CIL_ERR, "Attribute user not an attribute\n"); goto exit; } attr = (struct cil_userattribute*)attr_datum; attrusers->attr = attr; rc = cil_resolve_expr(CIL_USERATTRIBUTESET, attrusers->str_expr, &attrusers->datum_expr, current, db); if (rc != SEPOL_OK) { goto exit; } if (attr->expr_list == NULL) { cil_list_init(&attr->expr_list, CIL_USERATTRIBUTE); } cil_list_append(attr->expr_list, CIL_LIST, attrusers->datum_expr); return SEPOL_OK; exit: return rc; } /* * Degenerate inheritance leads to exponential growth of the policy * It can take many forms, but here is one example. * ... * (blockinherit ba) * (block b0 * (block b1 * (block b2 * (block b3 * ... * ) * (blockinherit b3) * ) * (blockinherit b2) * ) * (blockinherit b1) * ) * (blockinherit b0) * ... * This leads to 2^4 copies of the content of block b3, 2^3 copies of the * contents of block b2, etc. */ static unsigned cil_count_actual(struct cil_tree_node *node) { unsigned count = 0; if (node->flavor == CIL_BLOCKINHERIT) { count += 1; } for (node = node->cl_head; node; node = node->next) { count += cil_count_actual(node); } return count; } static int cil_check_inheritances(struct cil_tree_node *node, unsigned max, unsigned *count, struct cil_stack *stack, unsigned *loop) { int rc; if (node->flavor == CIL_BLOCKINHERIT) { struct cil_blockinherit *bi = node->data; *count += 1; if (*count > max) { cil_tree_log(node, CIL_ERR, "Degenerate inheritance detected"); return SEPOL_ERR; } if (bi->block) { struct cil_tree_node *block_node = NODE(bi->block); struct cil_stack_item *item; int i = 0; cil_stack_for_each(stack, i, item) { if (block_node == (struct cil_tree_node *)item->data) { *loop = CIL_TRUE; cil_tree_log(block_node, CIL_ERR, "Block inheritance loop found"); cil_tree_log(node, CIL_ERR, " blockinherit"); return SEPOL_ERR; } } cil_stack_push(stack, CIL_BLOCK, block_node); rc = cil_check_inheritances(block_node, max, count, stack, loop); cil_stack_pop(stack); if (rc != SEPOL_OK) { if (*loop == CIL_TRUE) { cil_tree_log(node, CIL_ERR, " blockinherit"); } return SEPOL_ERR; } } } for (node = node->cl_head; node; node = node->next) { rc = cil_check_inheritances(node, max, count, stack, loop); if (rc != SEPOL_OK) { return SEPOL_ERR; } } return SEPOL_OK; } static int cil_check_for_bad_inheritance(struct cil_tree_node *node) { unsigned num_actual, max; unsigned num_potential = 0; unsigned loop = CIL_FALSE; struct cil_stack *stack; int rc; num_actual = cil_count_actual(node); max = num_actual * CIL_DEGENERATE_INHERITANCE_GROWTH; if (max < CIL_DEGENERATE_INHERITANCE_MINIMUM) { max = CIL_DEGENERATE_INHERITANCE_MINIMUM; } cil_stack_init(&stack); rc = cil_check_inheritances(node, max, &num_potential, stack, &loop); cil_stack_destroy(&stack); return rc; } static int __cil_resolve_ast_node(struct cil_tree_node *node, struct cil_args_resolve *args) { int rc = SEPOL_OK; struct cil_db *db = args->db; enum cil_pass pass = 0; pass = args->pass; switch (pass) { case CIL_PASS_TIF: if (node->flavor == CIL_TUNABLEIF) { rc = cil_resolve_tunif(node, db); } break; case CIL_PASS_IN_BEFORE: 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 struct cil_in *in = node->data; if (in->is_after == CIL_FALSE) { cil_list_prepend(args->in_list_before, CIL_NODE, node); } } break; case CIL_PASS_BLKIN_LINK: if (node->flavor == CIL_BLOCKINHERIT) { rc = cil_resolve_blockinherit_link(node, db); } break; case CIL_PASS_BLKIN_COPY: if (node->flavor == CIL_BLOCK) { rc = cil_resolve_blockinherit_copy(node, db); } break; case CIL_PASS_BLKABS: if (node->flavor == CIL_BLOCKABSTRACT) { rc = cil_resolve_blockabstract(node, db, args->abstract_blocks); } break; case CIL_PASS_IN_AFTER: 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 struct cil_in *in = node->data; if (in->is_after == CIL_TRUE) { cil_list_prepend(args->in_list_after, CIL_NODE, node); } } break; case CIL_PASS_CALL1: if (node->flavor == CIL_CALL && args->macro == NULL) { rc = cil_resolve_call(node, db); } break; case CIL_PASS_CALL2: if (node->flavor == CIL_CALL && args->macro == NULL) { rc = cil_resolve_call_args(node, db); } break; case CIL_PASS_ALIAS1: switch (node->flavor) { case CIL_TYPEALIASACTUAL: rc = cil_resolve_aliasactual(node, db, CIL_TYPE, CIL_TYPEALIAS); break; case CIL_SENSALIASACTUAL: rc = cil_resolve_aliasactual(node, db, CIL_SENS, CIL_SENSALIAS); break; case CIL_CATALIASACTUAL: rc = cil_resolve_aliasactual(node, db, CIL_CAT, CIL_CATALIAS); break; default: break; } break; case CIL_PASS_ALIAS2: switch (node->flavor) { case CIL_TYPEALIAS: rc = cil_resolve_alias_to_actual(node, CIL_TYPE); break; case CIL_SENSALIAS: rc = cil_resolve_alias_to_actual(node, CIL_SENS); break; case CIL_CATALIAS: rc = cil_resolve_alias_to_actual(node, CIL_CAT); break; default: break; } break; case CIL_PASS_MISC1: switch (node->flavor) { case CIL_SIDORDER: rc = cil_resolve_sidorder(node, db, args->sidorder_lists); break; case CIL_CLASSORDER: rc = cil_resolve_classorder(node, db, args->classorder_lists, args->unordered_classorder_lists); break; case CIL_CATORDER: rc = cil_resolve_catorder(node, db, args->catorder_lists); break; case CIL_SENSITIVITYORDER: rc = cil_resolve_sensitivityorder(node, db, args->sensitivityorder_lists); break; case CIL_BOOLEANIF: rc = cil_resolve_boolif(node, db); break; default: break; } break; case CIL_PASS_MLS: switch (node->flavor) { case CIL_CATSET: rc = cil_resolve_catset(node, (struct cil_catset*)node->data, db); break; default: break; } break; case CIL_PASS_MISC2: switch (node->flavor) { case CIL_SENSCAT: rc = cil_resolve_senscat(node, db); break; case CIL_CLASSCOMMON: rc = cil_resolve_classcommon(node, db); break; default: break; } break; case CIL_PASS_MISC3: switch (node->flavor) { case CIL_TYPEATTRIBUTESET: rc = cil_resolve_typeattributeset(node, db); break; case CIL_EXPANDTYPEATTRIBUTE: rc = cil_resolve_expandtypeattribute(node, db); break; case CIL_TYPEBOUNDS: rc = cil_resolve_bounds(node, db, CIL_TYPE, CIL_TYPEATTRIBUTE); break; case CIL_TYPEPERMISSIVE: rc = cil_resolve_typepermissive(node, db); break; case CIL_NAMETYPETRANSITION: rc = cil_resolve_nametypetransition(node, db); break; case CIL_RANGETRANSITION: rc = cil_resolve_rangetransition(node, db); break; case CIL_CLASSPERMISSIONSET: rc = cil_resolve_classpermissionset(node, (struct cil_classpermissionset*)node->data, db); break; case CIL_CLASSMAPPING: rc = cil_resolve_classmapping(node, db); break; case CIL_AVRULE: case CIL_AVRULEX: rc = cil_resolve_avrule(node, db); break; case CIL_PERMISSIONX: rc = cil_resolve_permissionx(node, (struct cil_permissionx*)node->data, db); break; case CIL_DENY_RULE: rc = cil_resolve_deny_rule(node, db); break; case CIL_TYPE_RULE: rc = cil_resolve_type_rule(node, db); break; case CIL_USERROLE: rc = cil_resolve_userrole(node, db); break; case CIL_USERLEVEL: rc = cil_resolve_userlevel(node, db); break; case CIL_USERRANGE: rc = cil_resolve_userrange(node, db); break; case CIL_USERBOUNDS: rc = cil_resolve_bounds(node, db, CIL_USER, CIL_USERATTRIBUTE); break; case CIL_USERPREFIX: rc = cil_resolve_userprefix(node, db); break; case CIL_SELINUXUSER: case CIL_SELINUXUSERDEFAULT: rc = cil_resolve_selinuxuser(node, db); break; case CIL_ROLEATTRIBUTESET: rc = cil_resolve_roleattributeset(node, db); break; case CIL_ROLETYPE: rc = cil_resolve_roletype(node, db); break; case CIL_ROLETRANSITION: rc = cil_resolve_roletransition(node, db); break; case CIL_ROLEALLOW: rc = cil_resolve_roleallow(node, db); break; case CIL_ROLEBOUNDS: rc = cil_resolve_bounds(node, db, CIL_ROLE, CIL_ROLEATTRIBUTE); break; case CIL_LEVEL: rc = cil_resolve_level(node, (struct cil_level*)node->data, db); break; case CIL_LEVELRANGE: rc = cil_resolve_levelrange(node, (struct cil_levelrange*)node->data, db); break; case CIL_CONSTRAIN: rc = cil_resolve_constrain(node, db); break; case CIL_MLSCONSTRAIN: rc = cil_resolve_constrain(node, db); break; case CIL_VALIDATETRANS: case CIL_MLSVALIDATETRANS: rc = cil_resolve_validatetrans(node, db); break; case CIL_CONTEXT: rc = cil_resolve_context(node, (struct cil_context*)node->data, db); break; case CIL_FILECON: rc = cil_resolve_filecon(node, db); break; case CIL_IBPKEYCON: rc = cil_resolve_ibpkeycon(node, db); break; case CIL_PORTCON: rc = cil_resolve_portcon(node, db); break; case CIL_NODECON: rc = cil_resolve_nodecon(node, db); break; case CIL_GENFSCON: rc = cil_resolve_genfscon(node, db); break; case CIL_NETIFCON: rc = cil_resolve_netifcon(node, db); break; case CIL_IBENDPORTCON: rc = cil_resolve_ibendportcon(node, db); break; case CIL_PIRQCON: rc = cil_resolve_pirqcon(node, db); break; case CIL_IOMEMCON: rc = cil_resolve_iomemcon(node, db); break; case CIL_IOPORTCON: rc = cil_resolve_ioportcon(node, db); break; case CIL_PCIDEVICECON: rc = cil_resolve_pcidevicecon(node, db); break; case CIL_DEVICETREECON: rc = cil_resolve_devicetreecon(node, db); break; case CIL_FSUSE: rc = cil_resolve_fsuse(node, db); break; case CIL_SIDCONTEXT: rc = cil_resolve_sidcontext(node, db); break; case CIL_DEFAULTUSER: case CIL_DEFAULTROLE: case CIL_DEFAULTTYPE: rc = cil_resolve_default(node, db); break; case CIL_DEFAULTRANGE: rc = cil_resolve_defaultrange(node, db); break; case CIL_USERATTRIBUTESET: rc = cil_resolve_userattributeset(node, db); break; default: break; } break; default: break; } return rc; } static int __cil_resolve_ast_node_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args) { int rc = SEPOL_OK; struct cil_args_resolve *args = extra_args; enum cil_pass pass = args->pass; struct cil_tree_node *block = args->block; struct cil_tree_node *macro = args->macro; struct cil_tree_node *optional = args->optional; struct cil_tree_node *boolif = args->boolif; if (node == NULL) { goto exit; } if (block != NULL) { if (node->flavor == CIL_CAT || node->flavor == CIL_SENS) { cil_tree_log(node, CIL_ERR, "%s is not allowed in block", cil_node_to_string(node)); rc = SEPOL_ERR; goto exit; } } if (macro != NULL) { if (node->flavor == CIL_TUNABLE || node->flavor == CIL_IN || node->flavor == CIL_BLOCK || node->flavor == CIL_BLOCKINHERIT || node->flavor == CIL_BLOCKABSTRACT || node->flavor == CIL_MACRO) { cil_tree_log(node, CIL_ERR, "%s is not allowed in macro", cil_node_to_string(node)); rc = SEPOL_ERR; goto exit; } } if (optional != NULL) { if (node->flavor == CIL_TUNABLE || node->flavor == CIL_IN || node->flavor == CIL_BLOCK || node->flavor == CIL_BLOCKABSTRACT || node->flavor == CIL_MACRO) { cil_tree_log(node, CIL_ERR, "%s is not allowed in optional", cil_node_to_string(node)); rc = SEPOL_ERR; goto exit; } } if (boolif != NULL) { if (node->flavor != CIL_TUNABLEIF && node->flavor != CIL_CALL && node->flavor != CIL_CONDBLOCK && node->flavor != CIL_AVRULE && node->flavor != CIL_TYPE_RULE && node->flavor != CIL_NAMETYPETRANSITION && ((args->db->policy_version < POLICYDB_VERSION_COND_XPERMS) || (node->flavor != CIL_AVRULEX))) { rc = SEPOL_ERR; } else if (node->flavor == CIL_AVRULE || node->flavor == CIL_AVRULEX) { struct cil_avrule *rule = node->data; if (rule->rule_kind == CIL_AVRULE_NEVERALLOW) { rc = SEPOL_ERR; } } if (rc == SEPOL_ERR) { if (((struct cil_booleanif*)boolif->data)->preserved_tunable) { cil_tree_log(node, CIL_ERR, "%s is not allowed in tunableif being treated as a booleanif", cil_node_to_string(node)); } else { cil_tree_log(node, CIL_ERR, "%s is not allowed in booleanif", cil_node_to_string(node)); } goto exit; } } if (node->flavor == CIL_MACRO) { if (pass > CIL_PASS_IN_AFTER) { *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, args); if (rc == SEPOL_ENOENT) { if (optional == NULL) { cil_tree_log(node, CIL_ERR, "Failed to resolve %s statement", cil_node_to_string(node)); } else { if (!args->disabled_optional) { args->disabled_optional = optional; } cil_tree_log(node, CIL_INFO, "Failed to resolve %s statement", cil_node_to_string(node)); cil_tree_log(optional, CIL_INFO, "Disabling optional '%s'", DATUM(optional->data)->name); rc = SEPOL_OK; } goto exit; } return rc; exit: return rc; } static 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 *parent = NULL; if (current == NULL || extra_args == NULL) { goto exit; } parent = current->parent; if (parent->flavor == CIL_BLOCK) { args->block = parent; } else if (parent->flavor == CIL_MACRO) { args->macro = parent; } else if (parent->flavor == CIL_OPTIONAL) { args->optional = parent; } else if (parent->flavor == CIL_BOOLEANIF) { args->boolif = parent; } return SEPOL_OK; exit: return rc; } static 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_BLOCK) { struct cil_tree_node *n = parent->parent; args->block = NULL; while (n && n->flavor != CIL_ROOT) { if (n->flavor == CIL_BLOCK) { args->block = n; break; } n = n->parent; } } else if (parent->flavor == CIL_MACRO) { args->macro = NULL; } else if (parent->flavor == CIL_OPTIONAL) { struct cil_tree_node *n = parent->parent; if (args->disabled_optional == parent) { *(args->changed) = CIL_TRUE; cil_list_append(args->to_destroy, CIL_NODE, parent); args->disabled_optional = NULL; } args->optional = NULL; while (n && n->flavor != CIL_ROOT) { if (n->flavor == CIL_OPTIONAL) { args->optional = n; break; } n = n->parent; } } 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) { return rc; } extra_args.db = db; extra_args.pass = pass; extra_args.changed = &changed; extra_args.block = NULL; extra_args.macro = NULL; extra_args.optional = NULL; extra_args.disabled_optional = NULL; extra_args.boolif= NULL; extra_args.sidorder_lists = NULL; extra_args.classorder_lists = NULL; extra_args.unordered_classorder_lists = NULL; extra_args.catorder_lists = NULL; extra_args.sensitivityorder_lists = NULL; extra_args.in_list_before = NULL; extra_args.in_list_after = NULL; extra_args.abstract_blocks = NULL; cil_list_init(&extra_args.to_destroy, CIL_NODE); cil_list_init(&extra_args.sidorder_lists, CIL_SIDORDER); cil_list_init(&extra_args.classorder_lists, CIL_CLASSORDER); cil_list_init(&extra_args.unordered_classorder_lists, CIL_CLASSORDER); cil_list_init(&extra_args.catorder_lists, CIL_CATORDER); cil_list_init(&extra_args.sensitivityorder_lists, CIL_SENSITIVITYORDER); cil_list_init(&extra_args.in_list_before, CIL_IN); cil_list_init(&extra_args.in_list_after, CIL_IN); cil_list_init(&extra_args.abstract_blocks, CIL_NODE); 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_BEFORE) { rc = cil_resolve_in_list(extra_args.in_list_before, db); if (rc != SEPOL_OK) { goto exit; } cil_list_destroy(&extra_args.in_list_before, CIL_FALSE); } else if (pass == CIL_PASS_IN_AFTER) { rc = cil_resolve_in_list(extra_args.in_list_after, db); if (rc != SEPOL_OK) { goto exit; } cil_list_destroy(&extra_args.in_list_after, CIL_FALSE); } if (pass == CIL_PASS_BLKABS) { struct cil_list_item *item; cil_list_for_each(item, extra_args.abstract_blocks) { cil_mark_subtree_abstract(item->data); } } if (pass == CIL_PASS_BLKIN_LINK) { rc = cil_check_for_bad_inheritance(current); if (rc != SEPOL_OK) { rc = SEPOL_ERR; goto exit; } } if (pass == CIL_PASS_MISC1) { db->sidorder = __cil_ordered_lists_merge_all(&extra_args.sidorder_lists, NULL); if (db->sidorder == NULL) { rc = SEPOL_ERR; goto exit; } db->classorder = __cil_ordered_lists_merge_all(&extra_args.classorder_lists, &extra_args.unordered_classorder_lists); if (db->classorder == NULL) { rc = SEPOL_ERR; goto exit; } db->catorder = __cil_ordered_lists_merge_all(&extra_args.catorder_lists, NULL); if (db->catorder == NULL) { rc = SEPOL_ERR; goto exit; } cil_set_cat_values(db->catorder, db); db->sensitivityorder = __cil_ordered_lists_merge_all(&extra_args.sensitivityorder_lists, NULL); if (db->sensitivityorder == NULL) { rc = SEPOL_ERR; goto exit; } rc = __cil_verify_ordered(current, CIL_SID); if (rc != SEPOL_OK) { goto exit; } rc = __cil_verify_ordered(current, CIL_CLASS); if (rc != SEPOL_OK) { goto exit; } rc = __cil_verify_ordered(current, CIL_CAT); if (rc != SEPOL_OK) { goto exit; } rc = __cil_verify_ordered(current, CIL_SENS); if (rc != SEPOL_OK) { goto exit; } } if (changed) { struct cil_list_item *item; if (pass > CIL_PASS_CALL1) { int has_decls = CIL_FALSE; cil_list_for_each(item, extra_args.to_destroy) { has_decls = cil_tree_subtree_has_decl(item->data); if (has_decls) { break; } } if (has_decls) { /* Need to re-resolve because an optional was disabled that * contained one or more declarations. * Everything that needs to be reset comes after the * CIL_PASS_CALL2 pass. We 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_list_destroy(&extra_args.sidorder_lists, CIL_FALSE); cil_list_destroy(&extra_args.classorder_lists, CIL_FALSE); cil_list_destroy(&extra_args.catorder_lists, CIL_FALSE); cil_list_destroy(&extra_args.sensitivityorder_lists, CIL_FALSE); cil_list_destroy(&extra_args.unordered_classorder_lists, CIL_FALSE); cil_list_init(&extra_args.sidorder_lists, CIL_SIDORDER); cil_list_init(&extra_args.classorder_lists, CIL_CLASSORDER); cil_list_init(&extra_args.unordered_classorder_lists, CIL_CLASSORDER); cil_list_init(&extra_args.catorder_lists, CIL_CATORDER); cil_list_init(&extra_args.sensitivityorder_lists, CIL_SENSITIVITYORDER); 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; } } } cil_list_for_each(item, extra_args.to_destroy) { cil_tree_children_destroy(item->data); } cil_list_destroy(&extra_args.to_destroy, CIL_FALSE); cil_list_init(&extra_args.to_destroy, CIL_NODE); changed = 0; } } rc = __cil_verify_initsids(db->sidorder); if (rc != SEPOL_OK) { goto exit; } rc = SEPOL_OK; exit: cil_list_destroy(&extra_args.sidorder_lists, CIL_FALSE); cil_list_destroy(&extra_args.classorder_lists, CIL_FALSE); cil_list_destroy(&extra_args.catorder_lists, CIL_FALSE); cil_list_destroy(&extra_args.sensitivityorder_lists, CIL_FALSE); cil_list_destroy(&extra_args.unordered_classorder_lists, CIL_FALSE); cil_list_destroy(&extra_args.to_destroy, CIL_FALSE); cil_list_destroy(&extra_args.in_list_before, CIL_FALSE); cil_list_destroy(&extra_args.in_list_after, CIL_FALSE); cil_list_destroy(&extra_args.abstract_blocks, CIL_FALSE); return rc; } static int __cil_resolve_name_with_root(struct cil_db *db, char *name, enum cil_sym_index sym_index, struct cil_symtab_datum **datum) { symtab_t *symtab = &((struct cil_root *)db->ast->root->data)->symtab[sym_index]; return cil_symtab_get_datum(symtab, name, datum); } static int __cil_resolve_name_with_parents(struct cil_tree_node *node, char *name, enum cil_sym_index sym_index, struct cil_symtab_datum **datum) { int rc = SEPOL_ERR; symtab_t *symtab = NULL; while (node != NULL && rc != SEPOL_OK) { switch (node->flavor) { case CIL_ROOT: goto exit; break; case CIL_BLOCK: { struct cil_block *block = node->data; if (!block->is_abstract) { symtab = &block->symtab[sym_index]; rc = cil_symtab_get_datum(symtab, name, datum); } } break; case CIL_BLOCKINHERIT: { struct cil_blockinherit *inherit = node->data; rc = __cil_resolve_name_with_parents(node->parent, name, sym_index, datum); if (rc != SEPOL_OK) { /* Continue search in original block's parent */ rc = __cil_resolve_name_with_parents(NODE(inherit->block)->parent, name, sym_index, datum); goto exit; } } break; case CIL_MACRO: { struct cil_macro *macro = node->data; symtab = ¯o->symtab[sym_index]; rc = cil_symtab_get_datum(symtab, name, datum); } break; case CIL_CALL: { struct cil_call *call = node->data; struct cil_macro *macro = call->macro; symtab = ¯o->symtab[sym_index]; rc = cil_symtab_get_datum(symtab, name, datum); if (rc == SEPOL_OK) { /* If the name was declared in the macro, just look on the call side */ rc = SEPOL_ERR; } else { rc = cil_resolve_name_call_args(call, name, sym_index, datum); if (rc != SEPOL_OK) { /* Continue search in macro's parent */ rc = __cil_resolve_name_with_parents(NODE(call->macro)->parent, name, sym_index, datum); } } } break; case CIL_IN: /* In block symtabs only exist before resolving the AST */ case CIL_CONDBLOCK: /* Cond block symtabs only exist before resolving the AST */ default: break; } node = node->parent; } exit: return rc; } static int __cil_resolve_name_helper(struct cil_db *db, struct cil_tree_node *node, char *name, enum cil_sym_index sym_index, struct cil_symtab_datum **datum) { int rc = SEPOL_ERR; rc = __cil_resolve_name_with_parents(node, name, sym_index, datum); if (rc != SEPOL_OK) { rc = __cil_resolve_name_with_root(db, name, sym_index, datum); } return rc; } int cil_resolve_name(struct cil_tree_node *ast_node, char *name, enum cil_sym_index sym_index, struct cil_db *db, struct cil_symtab_datum **datum) { int rc = SEPOL_ERR; struct cil_tree_node *node = NULL; rc = cil_resolve_name_keep_aliases(ast_node, name, sym_index, db, datum); if (rc != SEPOL_OK) { goto exit; } /* If this datum is an alias, then return the actual node * This depends on aliases already being processed */ node = NODE(*datum); if (node->flavor == CIL_TYPEALIAS || node->flavor == CIL_SENSALIAS || node->flavor == CIL_CATALIAS) { struct cil_alias *alias = (struct cil_alias *)(*datum); if (alias->actual) { *datum = alias->actual; } } rc = SEPOL_OK; exit: return rc; } int cil_resolve_name_keep_aliases(struct cil_tree_node *ast_node, char *name, enum cil_sym_index sym_index, struct cil_db *db, struct cil_symtab_datum **datum) { int rc = SEPOL_ERR; struct cil_tree_node *node = NULL; if (name == NULL || sym_index >= CIL_SYM_NUM) { cil_log(CIL_ERR, "Invalid call to cil_resolve_name\n"); goto exit; } *datum = NULL; if (db->qualified_names || strchr(name,'.') == NULL) { /* Using qualified names or No '.' in name */ rc = __cil_resolve_name_helper(db, ast_node->parent, name, sym_index, datum); if (rc != SEPOL_OK) { goto exit; } } else { char *sp = NULL; char *name_dup = cil_strdup(name); char *current = strtok_r(name_dup, ".", &sp); char *next = strtok_r(NULL, ".", &sp); symtab_t *symtab = NULL; if (current == NULL) { /* Only dots */ cil_tree_log(ast_node, CIL_ERR, "Invalid name %s", name); free(name_dup); goto exit; } node = ast_node; if (*name == '.') { /* Leading '.' */ symtab = &((struct cil_root *)db->ast->root->data)->symtab[CIL_SYM_BLOCKS]; } else { rc = __cil_resolve_name_helper(db, node->parent, current, CIL_SYM_BLOCKS, datum); if (rc != SEPOL_OK) { free(name_dup); goto exit; } symtab = (*datum)->symtab; } /* Keep looking up blocks by name until only last part of name remains */ while (next != NULL) { rc = cil_symtab_get_datum(symtab, current, datum); if (rc != SEPOL_OK) { free(name_dup); goto exit; } node = NODE(*datum); if (node->flavor == CIL_BLOCK) { symtab = &((struct cil_block*)node->data)->symtab[CIL_SYM_BLOCKS]; } else { if (ast_node->flavor != CIL_IN) { cil_log(CIL_WARN, "Can only use %s name for name resolution in \"in\" blocks\n", cil_node_to_string(node)); free(name_dup); rc = SEPOL_ERR; goto exit; } if (node->flavor == CIL_MACRO) { struct cil_macro *macro = node->data; symtab = ¯o->symtab[sym_index]; } } current = next; next = strtok_r(NULL, ".", &sp); } symtab = &(symtab[sym_index]); rc = cil_symtab_get_datum(symtab, current, datum); free(name_dup); if (rc != SEPOL_OK) { goto exit; } } rc = SEPOL_OK; exit: if (rc != SEPOL_OK) { *datum = NULL; } return rc; } libsepol-3.8.1/cil/src/cil_resolve_ast.h000066400000000000000000000165461476211737200202460ustar00rootroot00000000000000/* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #ifndef CIL_RESOLVE_AST_H_ #define CIL_RESOLVE_AST_H_ #include #include "cil_internal.h" #include "cil_tree.h" int cil_resolve_classorder(struct cil_tree_node *current, struct cil_db *db, struct cil_list *classorder_list, struct cil_list *unordered_classorder_list); int cil_resolve_classperms(struct cil_tree_node *current, struct cil_classperms *cp, struct cil_db *db); int cil_resolve_classpermissionset(struct cil_tree_node *current, struct cil_classpermissionset *cps, struct cil_db *db); int cil_resolve_classperms_list(struct cil_tree_node *current, struct cil_list *cp_list, struct cil_db *db); int cil_resolve_avrule(struct cil_tree_node *current, struct cil_db *db); int cil_resolve_deny_rule(struct cil_tree_node *current, struct cil_db *db); int cil_resolve_type_rule(struct cil_tree_node *current, struct cil_db *db); int cil_resolve_typeattributeset(struct cil_tree_node *current, struct cil_db *db); int cil_resolve_typealias(struct cil_tree_node *current, struct cil_db *db); int cil_resolve_typebounds(struct cil_tree_node *current, struct cil_db *db); int cil_resolve_typepermissive(struct cil_tree_node *current, struct cil_db *db); int cil_resolve_nametypetransition(struct cil_tree_node *current, struct cil_db *db); int cil_resolve_rangetransition(struct cil_tree_node *current, struct cil_db *db); int cil_resolve_classcommon(struct cil_tree_node *current, struct cil_db *db); int cil_resolve_classmapping(struct cil_tree_node *current, struct cil_db *db); int cil_resolve_userrole(struct cil_tree_node *current, struct cil_db *db); int cil_resolve_userlevel(struct cil_tree_node *current, struct cil_db *db); int cil_resolve_userrange(struct cil_tree_node *current, struct cil_db *db); int cil_resolve_userbounds(struct cil_tree_node *current, struct cil_db *db); int cil_resolve_userprefix(struct cil_tree_node *current, struct cil_db *db); int cil_resolve_userattributeset(struct cil_tree_node *current, struct cil_db *db); int cil_resolve_selinuxuser(struct cil_tree_node *current, struct cil_db *db); int cil_resolve_roletype(struct cil_tree_node *current, struct cil_db *db); int cil_resolve_roletransition(struct cil_tree_node *current, struct cil_db *db); int cil_resolve_roleallow(struct cil_tree_node *current, struct cil_db *db); int cil_resolve_roleattributeset(struct cil_tree_node *current, struct cil_db *db); int cil_resolve_rolebounds(struct cil_tree_node *current, struct cil_db *db); int cil_resolve_sensalias(struct cil_tree_node *current, struct cil_db *db); int cil_resolve_catalias(struct cil_tree_node *current, struct cil_db *db); int cil_resolve_catorder(struct cil_tree_node *current, struct cil_db *db, struct cil_list *catorder_list); int cil_resolve_sensitivityorder(struct cil_tree_node *current, struct cil_db *db, struct cil_list *sensitivityorder_list); int cil_resolve_cat_list(struct cil_tree_node *current, struct cil_list *cat_list, struct cil_list *res_cat_list, struct cil_db *db); int cil_resolve_catset(struct cil_tree_node *current, struct cil_catset *catset, struct cil_db *db); int cil_resolve_senscat(struct cil_tree_node *current, struct cil_db *db); int cil_resolve_level(struct cil_tree_node *current, struct cil_level *level, struct cil_db *db); int cil_resolve_levelrange(struct cil_tree_node *current, struct cil_levelrange *levelrange, struct cil_db *db); int cil_resolve_constrain(struct cil_tree_node *current, struct cil_db *db); int cil_resolve_validatetrans(struct cil_tree_node *current, struct cil_db *db); int cil_resolve_context(struct cil_tree_node *current, struct cil_context *context, struct cil_db *db); int cil_resolve_filecon(struct cil_tree_node *current, struct cil_db *db); int cil_resolve_ibpkeycon(struct cil_tree_node *current, struct cil_db *db); int cil_resolve_ibendportcon(struct cil_tree_node *current, struct cil_db *db); int cil_resolve_portcon(struct cil_tree_node *current, struct cil_db *db); int cil_resolve_genfscon(struct cil_tree_node *current, struct cil_db *db); int cil_resolve_nodecon(struct cil_tree_node *current, struct cil_db *db); int cil_resolve_netifcon(struct cil_tree_node *current, struct cil_db *db); int cil_resolve_pirqcon(struct cil_tree_node *current, struct cil_db *db); int cil_resolve_iomemcon(struct cil_tree_node *current, struct cil_db *db); int cil_resolve_ioportcon(struct cil_tree_node *current, struct cil_db *db); int cil_resolve_pcidevicecon(struct cil_tree_node *current, struct cil_db *db); int cil_resolve_fsuse(struct cil_tree_node *current, struct cil_db *db); int cil_resolve_sidcontext(struct cil_tree_node *current, struct cil_db *db); int cil_resolve_sidorder(struct cil_tree_node *current, struct cil_db *db, struct cil_list *sidorder_list); int cil_resolve_blockinherit(struct cil_tree_node *current, struct cil_db *db); int cil_resolve_in(struct cil_tree_node *current, struct cil_db *db); int cil_resolve_call1(struct cil_tree_node *current, struct cil_db *db); int cil_resolve_call2(struct cil_tree_node *, struct cil_db *db); 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, struct cil_db *db); int cil_resolve_boolif(struct cil_tree_node *current, struct cil_db *db); int cil_evaluate_expr(struct cil_list *datum_expr, uint16_t *result); int cil_resolve_tunif(struct cil_tree_node *current, struct cil_db *db); 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, struct cil_db *db, struct cil_symtab_datum **datum); int cil_resolve_name_keep_aliases(struct cil_tree_node *ast_node, char *name, enum cil_sym_index sym_index, struct cil_db *db, struct cil_symtab_datum **datum); #endif /* CIL_RESOLVE_AST_H_ */ libsepol-3.8.1/cil/src/cil_stack.c000066400000000000000000000063141476211737200170100ustar00rootroot00000000000000/* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #include #include "cil_internal.h" #include "cil_log.h" #include "cil_mem.h" #include "cil_stack.h" #define CIL_STACK_INIT_SIZE 16 void cil_stack_init(struct cil_stack **stack) { struct cil_stack *new_stack = cil_malloc(sizeof(*new_stack)); new_stack->stack = cil_malloc(sizeof(*(new_stack->stack)) * CIL_STACK_INIT_SIZE); new_stack->size = CIL_STACK_INIT_SIZE; new_stack->pos = -1; *stack = new_stack; } void cil_stack_destroy(struct cil_stack **stack) { if (stack == NULL || *stack == NULL) { return; } free((*stack)->stack); free(*stack); *stack = NULL; } void cil_stack_empty(struct cil_stack *stack) { stack->pos = -1; } int cil_stack_is_empty(struct cil_stack *stack) { return (stack->pos == -1); } int cil_stack_number_of_items(struct cil_stack *stack) { return stack->pos + 1; } void cil_stack_push(struct cil_stack *stack, enum cil_flavor flavor, void *data) { stack->pos++; if (stack->pos == stack->size) { stack->size *= 2; stack->stack = cil_realloc(stack->stack, sizeof(*stack->stack) * stack->size); } stack->stack[stack->pos].flavor = flavor; stack->stack[stack->pos].data = data; } struct cil_stack_item *cil_stack_pop(struct cil_stack *stack) { if (stack->pos == -1) { return NULL; } stack->pos--; return &stack->stack[stack->pos + 1]; } struct cil_stack_item *cil_stack_peek(struct cil_stack *stack) { if (stack->pos < 0) { return NULL; } return &stack->stack[stack->pos]; } struct cil_stack_item *cil_stack_peek_at(struct cil_stack *stack, int pos) { int peekpos = stack->pos - pos; if (peekpos < 0 || peekpos > stack->pos) { return NULL; } return &stack->stack[peekpos]; } libsepol-3.8.1/cil/src/cil_stack.h000066400000000000000000000050771476211737200170220ustar00rootroot00000000000000/* * 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); int cil_stack_number_of_items(struct cil_stack *stack); void cil_stack_push(struct cil_stack *stack, enum cil_flavor flavor, void *data); struct cil_stack_item *cil_stack_pop(struct cil_stack *stack); struct cil_stack_item *cil_stack_peek(struct cil_stack *stack); struct cil_stack_item *cil_stack_peek_at(struct cil_stack *stack, int pos); #endif libsepol-3.8.1/cil/src/cil_strpool.c000066400000000000000000000076221476211737200174100ustar00rootroot00000000000000/* * Copyright 2014 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #include #include #include #include #include "cil_mem.h" #include "cil_strpool.h" #include "cil_log.h" #define CIL_STRPOOL_TABLE_SIZE 1 << 15 struct cil_strpool_entry { char *str; }; static pthread_mutex_t cil_strpool_mutex = PTHREAD_MUTEX_INITIALIZER; static unsigned int cil_strpool_readers = 0; static hashtab_t cil_strpool_tab = NULL; static unsigned int cil_strpool_hash(hashtab_t h, const_hashtab_key_t key) { unsigned int hash = 5381; unsigned char c; while ((c = *(unsigned const char *)key++)) hash = ((hash << 5) + hash) ^ c; return hash & (h->size - 1); } static int cil_strpool_compare(hashtab_t h __attribute__ ((unused)), const_hashtab_key_t key1, const_hashtab_key_t key2) { return strcmp(key1, key2); } char *cil_strpool_add(const char *str) { struct cil_strpool_entry *strpool_ref = NULL; pthread_mutex_lock(&cil_strpool_mutex); strpool_ref = hashtab_search(cil_strpool_tab, str); if (strpool_ref == NULL) { int rc; strpool_ref = cil_malloc(sizeof(*strpool_ref)); strpool_ref->str = cil_strdup(str); rc = hashtab_insert(cil_strpool_tab, strpool_ref->str, strpool_ref); if (rc != SEPOL_OK) { pthread_mutex_unlock(&cil_strpool_mutex); cil_log(CIL_ERR, "Failed to allocate memory\n"); exit(1); } } pthread_mutex_unlock(&cil_strpool_mutex); return strpool_ref->str; } static int cil_strpool_entry_destroy(hashtab_key_t k __attribute__ ((unused)), hashtab_datum_t d, void *args __attribute__ ((unused))) { struct cil_strpool_entry *strpool_ref = (struct cil_strpool_entry*)d; free(strpool_ref->str); free(strpool_ref); return SEPOL_OK; } void cil_strpool_init(void) { pthread_mutex_lock(&cil_strpool_mutex); if (cil_strpool_tab == NULL) { cil_strpool_tab = hashtab_create(cil_strpool_hash, cil_strpool_compare, CIL_STRPOOL_TABLE_SIZE); if (cil_strpool_tab == NULL) { pthread_mutex_unlock(&cil_strpool_mutex); cil_log(CIL_ERR, "Failed to allocate memory\n"); exit(1); } } cil_strpool_readers++; pthread_mutex_unlock(&cil_strpool_mutex); } void cil_strpool_destroy(void) { pthread_mutex_lock(&cil_strpool_mutex); cil_strpool_readers--; if (cil_strpool_readers == 0) { hashtab_map(cil_strpool_tab, cil_strpool_entry_destroy, NULL); hashtab_destroy(cil_strpool_tab); cil_strpool_tab = NULL; } pthread_mutex_unlock(&cil_strpool_mutex); } libsepol-3.8.1/cil/src/cil_strpool.h000066400000000000000000000034411476211737200174100ustar00rootroot00000000000000/* * Copyright 2014 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #ifndef CIL_STRPOOL_H_ #define CIL_STRPOOL_H_ #include char *cil_strpool_add(const char *str); void cil_strpool_init(void); void cil_strpool_destroy(void); #endif /* CIL_STRPOOL_H_ */ libsepol-3.8.1/cil/src/cil_symtab.c000066400000000000000000000172201476211737200172000ustar00rootroot00000000000000/* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #include #include #include #include #include #include #include "cil_internal.h" #include "cil_tree.h" #include "cil_symtab.h" #include "cil_mem.h" #include "cil_strpool.h" #include "cil_log.h" __attribute__((noreturn)) __attribute__((format (printf, 1, 2))) static void cil_symtab_error(const char* msg, ...) { va_list ap; va_start(ap, msg); cil_vlog(CIL_ERR, msg, ap); va_end(ap); exit(1); } void cil_symtab_init(symtab_t *symtab, unsigned int size) { int rc = symtab_init(symtab, size); if (rc != SEPOL_OK) { cil_symtab_error("Failed to create symtab\n"); } } void cil_symtab_datum_init(struct cil_symtab_datum *datum) { datum->name = NULL; datum->fqn = NULL; datum->symtab = NULL; cil_list_init(&datum->nodes, CIL_LIST_ITEM); } void cil_symtab_datum_destroy(struct cil_symtab_datum *datum) { cil_list_destroy(&datum->nodes, 0); cil_symtab_remove_datum(datum); } void cil_symtab_datum_remove_node(struct cil_symtab_datum *datum, struct cil_tree_node *node) { if (datum && datum->nodes != NULL) { cil_list_remove(datum->nodes, CIL_NODE, node, 0); if (datum->nodes->head == NULL) { cil_symtab_datum_destroy(datum); } } } /* This both initializes the datum and inserts it into the symtab. Note that cil_symtab_datum_destroy() is the analog to the initializer portion */ int cil_symtab_insert(symtab_t *symtab, hashtab_key_t key, struct cil_symtab_datum *datum, struct cil_tree_node *node) { int rc = hashtab_insert(symtab->table, key, (hashtab_datum_t)datum); if (rc == SEPOL_OK) { datum->name = key; datum->fqn = key; datum->symtab = symtab; symtab->nprim++; if (node) { cil_list_append(datum->nodes, CIL_NODE, node); } } else if (rc != SEPOL_EEXIST) { cil_symtab_error("Failed to insert datum into hashtab\n"); } return rc; } void cil_symtab_remove_datum(struct cil_symtab_datum *datum) { symtab_t *symtab = datum->symtab; if (symtab == NULL) { return; } hashtab_remove(symtab->table, datum->name, NULL, NULL); symtab->nprim--; datum->symtab = NULL; } int cil_symtab_get_datum(symtab_t *symtab, char *key, struct cil_symtab_datum **datum) { *datum = (struct cil_symtab_datum*)hashtab_search(symtab->table, (hashtab_key_t)key); if (*datum == NULL) { return SEPOL_ENOENT; } return SEPOL_OK; } int cil_symtab_map(symtab_t *symtab, int (*apply) (hashtab_key_t k, hashtab_datum_t d, void *args), void *args) { return hashtab_map(symtab->table, apply, args); } static int __cil_symtab_destroy_helper(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, __attribute__((unused)) void *args) { struct cil_symtab_datum *datum = d; datum->symtab = NULL; return SEPOL_OK; } void cil_symtab_destroy(symtab_t *symtab) { if (symtab->table != NULL){ cil_symtab_map(symtab, __cil_symtab_destroy_helper, NULL); hashtab_destroy(symtab->table); symtab->table = NULL; } } static void cil_complex_symtab_hash(struct cil_complex_symtab_key *ckey, int mask, intptr_t *hash) { intptr_t sum = ckey->key1 + ckey->key2 + ckey->key3 + ckey->key4; *hash = (intptr_t)((sum >> 2) & mask); } void cil_complex_symtab_init(struct cil_complex_symtab *symtab, unsigned int size) { symtab->htable = cil_calloc(size, sizeof(struct cil_complex_symtab *)); symtab->nelems = 0; symtab->nslots = size; symtab->mask = size - 1; } int cil_complex_symtab_insert(struct cil_complex_symtab *symtab, struct cil_complex_symtab_key *ckey, struct cil_complex_symtab_datum *datum) { intptr_t hash; struct cil_complex_symtab_node *node = NULL; struct cil_complex_symtab_node *prev = NULL; struct cil_complex_symtab_node *curr = NULL; node = cil_malloc(sizeof(*node)); memset(node, 0, sizeof(*node)); node->ckey = ckey; node->datum = datum; cil_complex_symtab_hash(ckey, symtab->mask, &hash); for (prev = NULL, curr = symtab->htable[hash]; curr != NULL; prev = curr, curr = curr->next) { if (ckey->key1 == curr->ckey->key1 && ckey->key2 == curr->ckey->key2 && ckey->key3 == curr->ckey->key3 && ckey->key4 == curr->ckey->key4) { free(node); return SEPOL_EEXIST; } if (ckey->key1 == curr->ckey->key1 && ckey->key2 < curr->ckey->key2) { break; } if (ckey->key1 == curr->ckey->key1 && ckey->key2 == curr->ckey->key2 && ckey->key3 < curr->ckey->key3) { break; } if (ckey->key1 == curr->ckey->key1 && ckey->key2 == curr->ckey->key2 && ckey->key3 == curr->ckey->key3 && ckey->key4 < curr->ckey->key4) { break; } } if (prev != NULL) { node->next = prev->next; prev->next = node; } else { node->next = symtab->htable[hash]; symtab->htable[hash] = node; } symtab->nelems++; return SEPOL_OK; } void cil_complex_symtab_search(struct cil_complex_symtab *symtab, struct cil_complex_symtab_key *ckey, struct cil_complex_symtab_datum **out) { intptr_t hash; struct cil_complex_symtab_node *curr = NULL; cil_complex_symtab_hash(ckey, symtab->mask, &hash); for (curr = symtab->htable[hash]; curr != NULL; curr = curr->next) { if (ckey->key1 == curr->ckey->key1 && ckey->key2 == curr->ckey->key2 && ckey->key3 == curr->ckey->key3 && ckey->key4 == curr->ckey->key4) { *out = curr->datum; return; } if (ckey->key1 == curr->ckey->key1 && ckey->key2 < curr->ckey->key2) { break; } if (ckey->key1 == curr->ckey->key1 && ckey->key2 == curr->ckey->key2 && ckey->key3 < curr->ckey->key3) { break; } if (ckey->key1 == curr->ckey->key1 && ckey->key2 == curr->ckey->key2 && ckey->key3 == curr->ckey->key3 && ckey->key4 < curr->ckey->key4) { break; } } *out = NULL; } void cil_complex_symtab_destroy(struct cil_complex_symtab *symtab) { struct cil_complex_symtab_node *curr = NULL; struct cil_complex_symtab_node *temp = NULL; unsigned int i; if (symtab == NULL) { return; } for (i = 0; i < symtab->nslots; i++) { curr = symtab->htable[i]; while (curr != NULL) { temp = curr; curr = curr->next; free(temp); } symtab->htable[i] = NULL; } free(symtab->htable); symtab->htable = NULL; symtab->nelems = 0; symtab->nslots = 0; symtab->mask = 0; } libsepol-3.8.1/cil/src/cil_symtab.h000066400000000000000000000070311476211737200172040ustar00rootroot00000000000000/* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #ifndef __CIL_SYMTAB_H_ #define __CIL_SYMTAB_H_ #include #include #include "cil_tree.h" struct cil_symtab_datum { struct cil_list *nodes; char *name; char *fqn; symtab_t *symtab; }; #define DATUM(d) ((struct cil_symtab_datum *)(d)) #define NODE(n) ((struct cil_tree_node *)(DATUM(n)->nodes->head->data)) #define FLAVOR(f) (NODE(f)->flavor) struct cil_complex_symtab_key { intptr_t key1; intptr_t key2; intptr_t key3; intptr_t key4; }; struct cil_complex_symtab_datum { void *data; }; struct cil_complex_symtab_node { struct cil_complex_symtab_key *ckey; struct cil_complex_symtab_datum *datum; struct cil_complex_symtab_node *next; }; struct cil_complex_symtab { struct cil_complex_symtab_node **htable; uint32_t nelems; uint32_t nslots; uint32_t mask; }; void cil_symtab_init(symtab_t *symtab, unsigned int size); void cil_symtab_datum_init(struct cil_symtab_datum *datum); void cil_symtab_datum_destroy(struct cil_symtab_datum *datum); void cil_symtab_datum_remove_node(struct cil_symtab_datum *datum, struct cil_tree_node *node); int cil_symtab_insert(symtab_t *symtab, hashtab_key_t key, struct cil_symtab_datum *datum, struct cil_tree_node *node); void cil_symtab_remove_datum(struct cil_symtab_datum *datum); int cil_symtab_get_datum(symtab_t *symtab, char *key, struct cil_symtab_datum **datum); int cil_symtab_map(symtab_t *symtab, int (*apply) (hashtab_key_t k, hashtab_datum_t d, void *args), void *args); void cil_symtab_destroy(symtab_t *symtab); void cil_complex_symtab_init(struct cil_complex_symtab *symtab, unsigned int size); int cil_complex_symtab_insert(struct cil_complex_symtab *symtab, struct cil_complex_symtab_key *ckey, struct cil_complex_symtab_datum *datum); void cil_complex_symtab_search(struct cil_complex_symtab *symtab, struct cil_complex_symtab_key *ckey, struct cil_complex_symtab_datum **out); void cil_complex_symtab_destroy(struct cil_complex_symtab *symtab); #endif libsepol-3.8.1/cil/src/cil_tree.c000066400000000000000000000222771476211737200166500ustar00rootroot00000000000000/* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #include #include #include #include #include "cil_internal.h" #include "cil_flavor.h" #include "cil_log.h" #include "cil_tree.h" #include "cil_list.h" #include "cil_parser.h" #include "cil_strpool.h" struct cil_tree_node *cil_tree_get_next_path(struct cil_tree_node *node, char **info_kind, uint32_t *hll_line, char **path) { int rc; if (!node) { goto exit; } node = node->parent; while (node) { if (node->flavor == CIL_NODE && node->data == NULL) { if (node->cl_head && node->cl_head->data == CIL_KEY_SRC_INFO) { if (!node->cl_head->next || !node->cl_head->next->next || !node->cl_head->next->next->next) { goto exit; } /* Parse Tree */ *info_kind = node->cl_head->next->data; rc = cil_string_to_uint32(node->cl_head->next->next->data, hll_line, 10); if (rc != SEPOL_OK) { goto exit; } *path = node->cl_head->next->next->next->data; return node; } node = node->parent; } else if (node->flavor == CIL_SRC_INFO) { /* AST */ struct cil_src_info *info = node->data; *info_kind = info->kind; *hll_line = info->hll_line; *path = info->path; return node; } else { if (node->flavor == CIL_CALL) { struct cil_call *call = node->data; node = NODE(call->macro); } else if (node->flavor == CIL_BLOCKINHERIT) { struct cil_blockinherit *inherit = node->data; node = NODE(inherit->block); } else { node = node->parent; } } } exit: *info_kind = NULL; *hll_line = 0; *path = NULL; return NULL; } char *cil_tree_get_cil_path(struct cil_tree_node *node) { char *info_kind; uint32_t hll_line; char *path; while (node) { node = cil_tree_get_next_path(node, &info_kind, &hll_line, &path); if (node && info_kind == CIL_KEY_SRC_CIL) { return path; } } return NULL; } __attribute__((format (printf, 3, 4))) void cil_tree_log(struct cil_tree_node *node, enum cil_log_level lvl, const char* msg, ...) { va_list ap; va_start(ap, msg); cil_vlog(lvl, msg, ap); va_end(ap); if (node) { char *path = NULL; uint32_t hll_offset = node->hll_offset; path = cil_tree_get_cil_path(node); if (path != NULL) { cil_log(lvl, " at %s:%u", path, node->line); } while (node) { do { char *info_kind; uint32_t hll_line; node = cil_tree_get_next_path(node, &info_kind, &hll_line, &path); if (!node || info_kind == CIL_KEY_SRC_CIL) { break; } if (info_kind == CIL_KEY_SRC_HLL_LMS) { hll_line += hll_offset - node->hll_offset - 1; } cil_log(lvl," from %s:%u", path, hll_line); } while (1); } } cil_log(lvl,"\n"); } int cil_tree_subtree_has_decl(struct cil_tree_node *node) { while (node) { if (node->flavor >= CIL_MIN_DECLARATIVE) { return CIL_TRUE; } if (node->cl_head != NULL) { if (cil_tree_subtree_has_decl(node->cl_head)) return CIL_TRUE; } node = node->next; } return CIL_FALSE; } int cil_tree_init(struct cil_tree **tree) { struct cil_tree *new_tree = cil_malloc(sizeof(*new_tree)); cil_tree_node_init(&new_tree->root); *tree = new_tree; return SEPOL_OK; } void cil_tree_destroy(struct cil_tree **tree) { if (tree == NULL || *tree == NULL) { return; } cil_tree_subtree_destroy((*tree)->root); free(*tree); *tree = NULL; } void cil_tree_subtree_destroy(struct cil_tree_node *node) { cil_tree_children_destroy(node); cil_tree_node_destroy(&node); } void cil_tree_children_destroy(struct cil_tree_node *node) { struct cil_tree_node *curr, *next; if (!node) { return; } curr = node->cl_head; while (curr) { next = curr->next; cil_tree_children_destroy(curr); cil_tree_node_destroy(&curr); curr = next; } node->cl_head = NULL; node->cl_tail = NULL; } void cil_tree_node_init(struct cil_tree_node **node) { struct cil_tree_node *new_node = cil_malloc(sizeof(*new_node)); new_node->cl_head = NULL; new_node->cl_tail = NULL; new_node->parent = NULL; new_node->data = NULL; new_node->next = NULL; new_node->flavor = CIL_ROOT; new_node->line = 0; new_node->hll_offset = 0; *node = new_node; } void cil_tree_node_destroy(struct cil_tree_node **node) { struct cil_symtab_datum *datum; if (node == NULL || *node == NULL) { return; } if ((*node)->flavor >= CIL_MIN_DECLARATIVE) { datum = (*node)->data; cil_symtab_datum_remove_node(datum, *node); if (datum->nodes == NULL) { cil_destroy_data(&(*node)->data, (*node)->flavor); } } else { cil_destroy_data(&(*node)->data, (*node)->flavor); } free(*node); *node = NULL; } void cil_tree_node_remove(struct cil_tree_node *node) { struct cil_tree_node *parent, *curr; if (node == NULL || node->parent == NULL) { return; } parent = node->parent; if (parent->cl_head == node) { if (parent->cl_tail == node) { parent->cl_tail = NULL; } parent->cl_head = node->next; cil_tree_node_destroy(&node); return; } curr = parent->cl_head; while (curr && curr->next != node) { curr = curr->next; } if (curr == NULL) { return; } if (parent->cl_tail == node) { parent->cl_tail = curr; } curr->next = node->next; cil_tree_node_destroy(&node); } /* 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 */ static int cil_tree_walk_core(struct cil_tree_node *node, int (*process_node)(struct cil_tree_node *node, uint32_t *finished, void *extra_args), int (*first_child)(struct cil_tree_node *node, void *extra_args), int (*last_child)(struct cil_tree_node *node, void *extra_args), void *extra_args) { int rc = SEPOL_ERR; while (node) { uint32_t finished = CIL_TREE_SKIP_NOTHING; if (process_node != NULL) { rc = (*process_node)(node, &finished, extra_args); if (rc != SEPOL_OK) { cil_tree_log(node, CIL_INFO, "Problem"); return rc; } } if (finished & CIL_TREE_SKIP_NEXT) { return SEPOL_OK; } if (node->cl_head != NULL && !(finished & CIL_TREE_SKIP_HEAD)) { rc = cil_tree_walk(node, process_node, first_child, last_child, extra_args); if (rc != SEPOL_OK) { return rc; } } node = node->next; } return SEPOL_OK; } int cil_tree_walk(struct cil_tree_node *node, int (*process_node)(struct cil_tree_node *node, uint32_t *finished, void *extra_args), int (*first_child)(struct cil_tree_node *node, void *extra_args), int (*last_child)(struct cil_tree_node *node, void *extra_args), void *extra_args) { int rc = SEPOL_ERR; if (!node || !node->cl_head) { return SEPOL_OK; } if (first_child != NULL) { rc = (*first_child)(node->cl_head, extra_args); if (rc != SEPOL_OK) { cil_tree_log(node, CIL_INFO, "Problem"); return rc; } } rc = cil_tree_walk_core(node->cl_head, process_node, first_child, last_child, extra_args); if (rc != SEPOL_OK) { return rc; } if (last_child != NULL) { rc = (*last_child)(node->cl_tail, extra_args); if (rc != SEPOL_OK) { cil_tree_log(node, CIL_INFO, "Problem"); return rc; } } return SEPOL_OK; } libsepol-3.8.1/cil/src/cil_tree.h000066400000000000000000000064461476211737200166550ustar00rootroot00000000000000/* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #ifndef CIL_TREE_H_ #define CIL_TREE_H_ #include #include "cil_flavor.h" #include "cil_list.h" struct cil_tree { struct cil_tree_node *root; }; struct cil_tree_node { struct cil_tree_node *parent; struct cil_tree_node *cl_head; //Head of child_list struct cil_tree_node *cl_tail; //Tail of child_list struct cil_tree_node *next; //Each element in the list points to the next element enum cil_flavor flavor; uint32_t line; uint32_t hll_offset; void *data; }; struct cil_tree_node *cil_tree_get_next_path(struct cil_tree_node *node, char **info_kind, uint32_t *hll_line, char **path); char *cil_tree_get_cil_path(struct cil_tree_node *node); __attribute__((format (printf, 3, 4))) void cil_tree_log(struct cil_tree_node *node, enum cil_log_level lvl, const char* msg, ...); int cil_tree_subtree_has_decl(struct cil_tree_node *node); 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_node_remove(struct cil_tree_node *node); //finished values #define CIL_TREE_SKIP_NOTHING 0 #define CIL_TREE_SKIP_NEXT 1 #define CIL_TREE_SKIP_HEAD 2 #define CIL_TREE_SKIP_ALL (CIL_TREE_SKIP_NOTHING | CIL_TREE_SKIP_NEXT | CIL_TREE_SKIP_HEAD) int cil_tree_walk(struct cil_tree_node *start_node, int (*process_node)(struct cil_tree_node *node, uint32_t *finished, void *extra_args), int (*first_child)(struct cil_tree_node *node, void *extra_args), int (*last_child)(struct cil_tree_node *node, void *extra_args), void *extra_args); #endif /* CIL_TREE_H_ */ libsepol-3.8.1/cil/src/cil_verify.c000066400000000000000000001425351476211737200172150ustar00rootroot00000000000000/* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #include #include #include #include #include #include #include #include #include "cil_internal.h" #include "cil_flavor.h" #include "cil_log.h" #include "cil_mem.h" #include "cil_tree.h" #include "cil_list.h" #include "cil_find.h" #include "cil_stack.h" #include "cil_verify.h" static int __cil_is_reserved_name(const char *name, enum cil_flavor flavor) { switch (flavor) { case CIL_BOOL: case CIL_TUNABLE: if ((name == CIL_KEY_EQ) || (name == CIL_KEY_NEQ)) return CIL_TRUE; break; case CIL_PERM: case CIL_MAP_PERM: case CIL_USER: case CIL_USERATTRIBUTE: case CIL_ROLE: case CIL_ROLEATTRIBUTE: if (name == CIL_KEY_ALL) return CIL_TRUE; break; case CIL_TYPE: case CIL_TYPEATTRIBUTE: case CIL_TYPEALIAS: if ((name == CIL_KEY_ALL) || (name == CIL_KEY_SELF) || (name == CIL_KEY_NOTSELF) || (name == CIL_KEY_OTHER)) return CIL_TRUE; break; case CIL_CAT: case CIL_CATSET: case CIL_CATALIAS: case CIL_PERMISSIONX: if ((name == CIL_KEY_ALL) || (name == CIL_KEY_RANGE)) return CIL_TRUE; break; default: /* All of these are not used in expressions */ return CIL_FALSE; break; } /* Everything not under the default case is also checked for these */ if ((name == CIL_KEY_AND) || (name == CIL_KEY_OR) || (name == CIL_KEY_NOT) || (name == CIL_KEY_XOR)) { return CIL_TRUE; } return CIL_FALSE; } int cil_verify_name(const struct cil_db *db, const char *name, enum cil_flavor flavor) { int rc = SEPOL_ERR; int len; int i = 0; if (name == NULL) { cil_log(CIL_ERR, "Name is NULL\n"); goto exit; } len = strlen(name); if (len >= CIL_MAX_NAME_LENGTH) { cil_log(CIL_ERR, "Name length greater than max name length of %d", CIL_MAX_NAME_LENGTH); rc = SEPOL_ERR; goto exit; } if (!isalpha(name[0])) { cil_log(CIL_ERR, "First character in %s is not a letter\n", name); goto exit; } if (db->qualified_names == CIL_FALSE) { 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; } } } else { for (i = 1; i < len; i++) { if (!isalnum(name[i]) && name[i] != '_' && name[i] != '-' && name[i] != '.') { cil_log(CIL_ERR, "Invalid character \"%c\" in %s\n", name[i], name); goto exit; } } } if (__cil_is_reserved_name(name, flavor)) { cil_log(CIL_ERR, "Name %s is a reserved word\n", 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[], size_t len) { struct cil_tree_node *c = parse_current; size_t i = 0; while (i < len && c != NULL) { if ((s[i] & CIL_SYN_STRING) && c->data != NULL && c->cl_head == NULL) { c = c->next; i++; } else if ((s[i] & CIL_SYN_LIST) && c->data == NULL && c->cl_head != NULL) { c = c->next; i++; } else if ((s[i] & CIL_SYN_EMPTY_LIST) && c->data == NULL && c->cl_head == NULL) { c = c->next; i++; } else if ((s[i] & CIL_SYN_N_LISTS) || (s[i] & CIL_SYN_N_STRINGS)) { while (c != NULL) { if ((s[i] & CIL_SYN_N_LISTS) && c->data == NULL && c->cl_head != NULL) { c = c->next; } else if ((s[i] & CIL_SYN_N_STRINGS) && c->data != NULL && c->cl_head == NULL) { c = c->next; } else { goto exit; } } i++; break; /* Only CIL_SYN_END allowed after these */ } else { goto exit; } } if (i < len && (s[i] & CIL_SYN_END) && c == NULL) { return SEPOL_OK; } exit: cil_log(CIL_ERR, "Invalid syntax\n"); return SEPOL_ERR; } int cil_verify_expr_syntax(struct cil_tree_node *current, enum cil_flavor op, enum cil_flavor expr_flavor) { int rc; enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; int syntax_len = sizeof(syntax)/sizeof(*syntax); switch (op) { case CIL_NOT: syntax[2] = CIL_SYN_END; syntax_len = 3; break; case CIL_AND: case CIL_OR: case CIL_XOR: break; case CIL_EQ: case CIL_NEQ: if (expr_flavor != CIL_BOOL && expr_flavor != CIL_TUNABLE ) { cil_log(CIL_ERR,"Invalid operator (%s) for set expression\n", (char*)current->data); goto exit; } break; case CIL_ALL: if (expr_flavor == CIL_BOOL || expr_flavor == CIL_TUNABLE) { cil_log(CIL_ERR,"Invalid operator (%s) for boolean or tunable expression\n", (char*)current->data); goto exit; } syntax[1] = CIL_SYN_END; syntax_len = 2; break; case CIL_RANGE: if (expr_flavor != CIL_CAT && expr_flavor != CIL_PERMISSIONX) { cil_log(CIL_ERR,"Operator (%s) only valid for catset and permissionx expression\n", (char*)current->data); goto exit; } syntax[1] = CIL_SYN_STRING; syntax[2] = CIL_SYN_STRING; break; case CIL_NONE: /* String or List */ syntax[0] = CIL_SYN_N_STRINGS | CIL_SYN_N_LISTS; syntax[1] = CIL_SYN_END; syntax_len = 2; break; default: cil_log(CIL_ERR,"Unexpected value (%s) for expression operator\n", (char*)current->data); goto exit; } rc = __cil_verify_syntax(current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: return SEPOL_ERR; } int cil_verify_constraint_leaf_expr_syntax(enum cil_flavor l_flavor, enum cil_flavor r_flavor, enum cil_flavor op, enum cil_flavor expr_flavor) { if (r_flavor == CIL_STRING || r_flavor == CIL_LIST) { if (l_flavor == CIL_CONS_L1 || l_flavor == CIL_CONS_L2 || l_flavor == CIL_CONS_H1 || l_flavor == CIL_CONS_H2 ) { cil_log(CIL_ERR, "l1, l2, h1, and h2 cannot be used on the left side with a string or list on the right side\n"); goto exit; } else if (l_flavor == CIL_CONS_U3 || l_flavor == CIL_CONS_R3 || l_flavor == CIL_CONS_T3) { if (expr_flavor != CIL_VALIDATETRANS && expr_flavor != CIL_MLSVALIDATETRANS) { cil_log(CIL_ERR, "u3, r3, and t3 can only be used with (mls)validatetrans rules\n"); goto exit; } } } else { if (r_flavor == CIL_CONS_U1 || r_flavor == CIL_CONS_R1 || r_flavor == CIL_CONS_T1) { cil_log(CIL_ERR, "u1, r1, and t1 are not allowed on the right side\n"); goto exit; } else if (r_flavor == CIL_CONS_U3 || r_flavor == CIL_CONS_R3 || r_flavor == CIL_CONS_T3) { cil_log(CIL_ERR, "u3, r3, and t3 are not allowed on the right side\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_conditional_blocks(struct cil_tree_node *current) { int found_true = CIL_FALSE; int found_false = CIL_FALSE; if (current->cl_head->data == CIL_KEY_CONDTRUE) { found_true = CIL_TRUE; } else if (current->cl_head->data == CIL_KEY_CONDFALSE) { found_false = CIL_TRUE; } else { cil_tree_log(current, CIL_ERR, "Expected true or false block in conditional"); return SEPOL_ERR; } current = current->next; if (current != NULL) { if (current->cl_head->data == CIL_KEY_CONDTRUE) { if (found_true) { cil_tree_log(current, CIL_ERR, "More than one true block in conditional"); return SEPOL_ERR; } } else if (current->cl_head->data == CIL_KEY_CONDFALSE) { if (found_false) { cil_tree_log(current, CIL_ERR, "More than one false block in conditional"); return SEPOL_ERR; } } else { cil_tree_log(current, CIL_ERR, "Expected true or false block in conditional"); return SEPOL_ERR; } } return SEPOL_OK; } int cil_verify_decl_does_not_shadow_macro_parameter(struct cil_macro *macro, struct cil_tree_node *node, const char *name) { struct cil_list_item *item; struct cil_list *param_list = macro->params; if (param_list != NULL) { cil_list_for_each(item, param_list) { struct cil_param *param = item->data; if (param->str == name) { if (param->flavor == node->flavor) { cil_log(CIL_ERR, "Declaration of %s %s shadows a macro parameter with the same flavor\n", cil_node_to_string(node), name); return SEPOL_ERR; } else { cil_log(CIL_WARN, "Declaration of %s %s has same name as a macro parameter with a different flavor\n", cil_node_to_string(node), name); } } } } return SEPOL_OK; } static int cil_verify_no_self_reference(enum cil_flavor flavor, struct cil_symtab_datum *datum, struct cil_stack *stack); static int __verify_no_self_reference_in_expr(struct cil_list *expr, struct cil_stack *stack) { struct cil_list_item *item; int rc = SEPOL_OK; if (!expr) { return SEPOL_OK; } cil_list_for_each(item, expr) { if (item->flavor == CIL_DATUM) { struct cil_symtab_datum* datum = item->data; rc = cil_verify_no_self_reference(FLAVOR(datum), datum, stack); } else if (item->flavor == CIL_LIST) { rc = __verify_no_self_reference_in_expr(item->data, stack); } if (rc != SEPOL_OK) { return SEPOL_ERR; } } return SEPOL_OK; } static int cil_verify_no_self_reference(enum cil_flavor flavor, struct cil_symtab_datum *datum, struct cil_stack *stack) { struct cil_stack_item *item; int i = 0; int rc = SEPOL_OK; cil_stack_for_each(stack, i, item) { struct cil_symtab_datum *prev = item->data; if (datum == prev) { cil_tree_log(NODE(datum), CIL_ERR, "Self-reference found for %s", datum->name); return SEPOL_ERR; } } switch (flavor) { case CIL_USERATTRIBUTE: { struct cil_userattribute *attr = (struct cil_userattribute *)datum; cil_stack_push(stack, CIL_DATUM, datum); rc = __verify_no_self_reference_in_expr(attr->expr_list, stack); cil_stack_pop(stack); break; } case CIL_ROLEATTRIBUTE: { struct cil_roleattribute *attr = (struct cil_roleattribute *)datum; cil_stack_push(stack, CIL_DATUM, datum); rc = __verify_no_self_reference_in_expr(attr->expr_list, stack); cil_stack_pop(stack); break; } case CIL_TYPEATTRIBUTE: { struct cil_typeattribute *attr = (struct cil_typeattribute *)datum; cil_stack_push(stack, CIL_DATUM, datum); rc = __verify_no_self_reference_in_expr(attr->expr_list, stack); cil_stack_pop(stack); break; } case CIL_CATSET: { struct cil_catset *set = (struct cil_catset *)datum; cil_stack_push(stack, CIL_DATUM, datum); rc = __verify_no_self_reference_in_expr(set->cats->datum_expr, stack); cil_stack_pop(stack); break; } default: break; } return rc; } 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; } int cil_verify_completed_ordered_list(struct cil_list *complete, struct cil_list *ordered_lists) { struct cil_list_item *cprev, *ccurr, *cnext; int found_prev, found_next; int rc = SEPOL_OK; found_prev = CIL_FALSE; found_next = CIL_FALSE; cprev = NULL; ccurr = complete->head; cnext = ccurr ? ccurr->next : NULL; while (ccurr) { struct cil_tree_node *node; struct cil_ordered *ordered; struct cil_list_item *curr_list, *oprev, *ocurr, *onext; int change = CIL_FALSE; cil_list_for_each(curr_list, ordered_lists) { node = curr_list->data; ordered = node->data; oprev = NULL; cil_list_for_each(ocurr, ordered->datums) { onext = ocurr ? ocurr->next : NULL; if (ccurr->data == ocurr->data) { if (found_prev == CIL_FALSE && ((!cprev && !oprev) || (cprev && oprev && cprev->data == oprev->data))) { found_prev = CIL_TRUE; change = CIL_TRUE; } if (found_next == CIL_FALSE && ((!cnext && !onext) || (cnext && onext && cnext->data == onext->data))) { found_next = CIL_TRUE; change = CIL_TRUE; } if (found_prev && found_next) { cprev = ccurr; ccurr = cnext; cnext = ccurr ? ccurr->next : NULL; found_prev = CIL_FALSE; found_next = CIL_FALSE; if (!ccurr) { /* Went through the whole list */ return rc; } } } oprev = ocurr; } } if (!change) { rc = SEPOL_ERR; cil_log(CIL_ERR, "Unable to verify the order of %s\n", DATUM(ccurr->data)->fqn); cil_log(CIL_ERR, "Found in the following ordering rules:\n"); cil_list_for_each(curr_list, ordered_lists) { node = curr_list->data; ordered = node->data; cil_list_for_each(ocurr, ordered->datums) { if (ccurr->data == ocurr->data) { cil_tree_log(node, CIL_ERR, " "); } } } cprev = ccurr; ccurr = cnext; cnext = ccurr ? ccurr->next : NULL; found_prev = CIL_FALSE; found_next = CIL_FALSE; } } return rc; } struct cil_args_verify_order { uint32_t *flavor; }; int __cil_verify_ordered_node_helper(struct cil_tree_node *node, __attribute__((unused)) uint32_t *finished, void *extra_args) { struct cil_args_verify_order *args = extra_args; uint32_t *flavor = args->flavor; if (node->flavor == *flavor) { if (node->flavor == CIL_SID) { struct cil_sid *sid = node->data; if (sid->ordered == CIL_FALSE) { cil_tree_log(node, CIL_ERR, "SID %s not in sidorder statement", sid->datum.name); return SEPOL_ERR; } } else if (node->flavor == CIL_CLASS) { struct cil_class *class = node->data; if (class->ordered == CIL_FALSE) { cil_tree_log(node, CIL_ERR, "Class %s not in classorder statement", class->datum.name); return SEPOL_ERR; } } else if (node->flavor == CIL_CAT) { struct cil_cat *cat = node->data; if (cat->ordered == CIL_FALSE) { cil_tree_log(node, CIL_ERR, "Category %s not in categoryorder statement", cat->datum.name); return SEPOL_ERR; } } else if (node->flavor == CIL_SENS) { struct cil_sens *sens = node->data; if (sens->ordered == CIL_FALSE) { cil_tree_log(node, CIL_ERR, "Sensitivity %s not in sensitivityorder statement", sens->datum.name); return SEPOL_ERR; } } } return SEPOL_OK; } int __cil_verify_ordered(struct cil_tree_node *current, enum cil_flavor flavor) { struct cil_args_verify_order extra_args; int rc = SEPOL_ERR; extra_args.flavor = &flavor; rc = cil_tree_walk(current, __cil_verify_ordered_node_helper, NULL, NULL, &extra_args); return rc; } int __cil_verify_initsids(struct cil_list *sids) { int rc = SEPOL_OK; struct cil_list_item *i; if (sids->head == NULL) { cil_log(CIL_ERR, "At least one initial sid must be defined in the policy\n"); return SEPOL_ERR; } cil_list_for_each(i, sids) { struct cil_sid *sid = i->data; if (sid->context == NULL) { struct cil_tree_node *node = sid->datum.nodes->head->data; cil_tree_log(node, CIL_INFO, "No context assigned to SID %s, omitting from policy",sid->datum.name); } } return rc; } static 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; } static 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; } static 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; } static 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; } static 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; } static 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; } static int __cil_verify_named_levelrange(struct cil_db *db, struct cil_tree_node *node) { int rc = SEPOL_ERR; struct cil_levelrange *lr = node->data; rc = __cil_verify_levelrange(db, lr); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: cil_tree_log(node, CIL_ERR, "Invalid named range"); return rc; } static int __cil_verify_user_pre_eval(struct cil_tree_node *node) { int rc = SEPOL_ERR; struct cil_user *user = node->data; if (user->dftlevel == NULL) { cil_log(CIL_ERR, "User %s does not have a default level\n", user->datum.name); goto exit; } else if (user->range == NULL) { cil_log(CIL_ERR, "User %s does not have a level range\n", user->datum.name); goto exit; } else if (user->bounds != NULL) { int steps = 0; int limit = 2; struct cil_user *u1 = user; struct cil_user *u2 = user->bounds; while (u2 != NULL) { if (u1 == u2) { cil_log(CIL_ERR, "Circular bounds found for user %s\n", u1->datum.name); goto exit; } if (steps == limit) { steps = 0; limit *= 2; u1 = u2; } u2 = u2->bounds; steps++; } } return SEPOL_OK; exit: cil_tree_log(node, CIL_ERR, "Invalid user"); return rc; } static int __cil_verify_user_post_eval(struct cil_db *db, struct cil_tree_node *node) { int rc = SEPOL_ERR; struct cil_user *user = node->data; /* Verify user range only if anonymous */ if (user->range->datum.name == NULL) { rc = __cil_verify_levelrange(db, user->range); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: cil_tree_log(node, CIL_ERR, "Invalid user"); return rc; } static int __cil_verify_role(struct cil_tree_node *node) { int rc = SEPOL_ERR; struct cil_role *role = node->data; int steps = 0; int limit = 2; struct cil_role *r1 = role; struct cil_role *r2 = role->bounds; while (r2 != NULL) { if (r1 == r2) { cil_log(CIL_ERR, "Circular bounds found for role %s\n", r1->datum.name); goto exit; } if (steps == limit) { steps = 0; limit *= 2; r1 = r2; } r2 = r2->bounds; steps++; } return SEPOL_OK; exit: cil_tree_log(node, CIL_ERR, "Invalid role"); return rc; } static int __cil_verify_type(struct cil_tree_node *node) { int rc = SEPOL_ERR; struct cil_type *type = node->data; int steps = 0; int limit = 2; struct cil_type *t1 = type; struct cil_type *t2 = type->bounds; while (t2 != NULL) { if (t1 == t2) { cil_log(CIL_ERR, "Circular bounds found for type %s\n", t1->datum.name); goto exit; } if (steps == limit) { steps = 0; limit *= 2; t1 = t2; } t2 = t2->bounds; steps++; } return SEPOL_OK; exit: cil_tree_log(node, CIL_ERR, "Invalid type"); return rc; } static int __cil_verify_context(struct cil_db *db, struct cil_context *ctx) { int rc = SEPOL_ERR; struct cil_user *user = ctx->user; struct cil_role *role = ctx->role; struct cil_type *type = ctx->type; struct cil_level *user_low = user->range->low; struct cil_level *user_high = user->range->high; struct cil_level *ctx_low = ctx->range->low; struct cil_level *ctx_high = ctx->range->high; struct cil_list *sensitivityorder = db->sensitivityorder; struct cil_list_item *curr; int found = CIL_FALSE; if (user->roles != NULL) { if (!ebitmap_get_bit(user->roles, role->value)) { cil_log(CIL_ERR, "Role %s is invalid for user %s\n", ctx->role_str, ctx->user_str); rc = SEPOL_ERR; goto exit; } } else { cil_log(CIL_ERR, "No roles given to the user %s\n", ctx->user_str); rc = SEPOL_ERR; goto exit; } if (role->types != NULL) { if (!ebitmap_get_bit(role->types, type->value)) { cil_log(CIL_ERR, "Type %s is invalid for role %s\n", ctx->type_str, ctx->role_str); rc = SEPOL_ERR; goto exit; } } else { cil_log(CIL_ERR, "No types associated with role %s\n", ctx->role_str); rc = SEPOL_ERR; goto exit; } /* Verify range only when anonymous */ if (ctx->range->datum.name == NULL) { rc = __cil_verify_levelrange(db, ctx->range); if (rc != SEPOL_OK) { goto exit; } } for (curr = sensitivityorder->head; curr != NULL; curr = curr->next) { struct cil_sens *sens = curr->data; if (found == CIL_FALSE) { if (sens == user_low->sens) { found = CIL_TRUE; } else if (sens == ctx_low->sens) { cil_log(CIL_ERR, "Range %s is invalid for user %s\n", ctx->range_str, ctx->user_str); rc = SEPOL_ERR; goto exit; } } if (found == CIL_TRUE) { if (sens == ctx_high->sens) { break; } else if (sens == user_high->sens) { cil_log(CIL_ERR, "Range %s is invalid for user %s\n", ctx->range_str, ctx->user_str); rc = SEPOL_ERR; goto exit; } } } return SEPOL_OK; exit: cil_log(CIL_ERR, "Invalid context\n"); return rc; } static int __cil_verify_named_context(struct cil_db *db, struct cil_tree_node *node) { int rc = SEPOL_ERR; struct cil_context *ctx = node->data; rc = __cil_verify_context(db, ctx); if (rc != SEPOL_OK) { goto exit; } return SEPOL_OK; exit: cil_tree_log(node, CIL_ERR, "Invalid named context"); return rc; } /* static int __cil_verify_rule(struct cil_tree_node *node, struct cil_complex_symtab *symtab) { int rc = SEPOL_ERR; struct cil_type_rule *typerule = NULL; struct cil_roletransition *roletrans = NULL; struct cil_complex_symtab_key ckey; switch (node->flavor) { case CIL_ROLETRANSITION: { roletrans = node->data; ckey.key1 = (intptr_t)roletrans->src; ckey.key2 = (intptr_t)roletrans->tgt; ckey.key3 = (intptr_t)roletrans->obj; ckey.key4 = CIL_ROLETRANSITION; break; } case CIL_TYPE_RULE: { typerule = node->data; ckey.key1 = (intptr_t)typerule->src; ckey.key2 = (intptr_t)typerule->tgt; ckey.key3 = (intptr_t)typerule->obj; ckey.key4 = (intptr_t)typerule->rule_kind; break; } default: break; } rc = cil_complex_symtab_insert(symtab, &ckey, NULL); if (rc == SEPOL_EEXIST) { struct cil_complex_symtab_datum *datum = NULL; cil_complex_symtab_search(symtab, &ckey, &datum); if (datum == NULL) { cil_tree_log(node, CIL_ERR, "Duplicate rule defined"); rc = SEPOL_ERR; goto exit; } } return SEPOL_OK; exit: cil_tree_log(node, CIL_ERR, "Invalid rule"); return rc; } */ static 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: case CIL_AVRULEX: { struct cil_avrule *avrule = NULL; avrule = rule_node->data; if (avrule->rule_kind == CIL_AVRULE_NEVERALLOW) { if (bif->preserved_tunable) { cil_tree_log(node, CIL_ERR, "Neverallow found in tunableif block (treated as a booleanif due to preserve-tunables)"); } else { cil_tree_log(node, CIL_ERR, "Neverallow found in booleanif block"); } rc = SEPOL_ERR; goto exit; } break; } case CIL_DENY_RULE: if (bif->preserved_tunable) { cil_tree_log(node, CIL_ERR, "Not allowed to have a deny rule in a tunableif block (treated as a booleanif due to preserve-tunables)"); } else { cil_tree_log(node, CIL_ERR, "Not allowed to have deny rule in a booleanif block"); } rc = SEPOL_ERR; goto exit; break; case CIL_TYPE_RULE: /* struct cil_type_rule *typerule = NULL; struct cil_tree_node *temp_node = NULL; struct cil_complex_symtab *symtab = extra_args; struct cil_complex_symtab_key ckey; struct cil_complex_symtab_datum datum; typerule = rule_node->data; ckey.key1 = (intptr_t)typerule->src; ckey.key2 = (intptr_t)typerule->tgt; ckey.key3 = (intptr_t)typerule->obj; ckey.key4 = (intptr_t)typerule->rule_kind; datum.data = node; rc = cil_complex_symtab_insert(symtab, &ckey, &datum); if (rc != SEPOL_OK) { goto exit; } for (temp_node = rule_node->next; temp_node != NULL; temp_node = temp_node->next) { if (temp_node->flavor == CIL_TYPE_RULE) { typerule = temp_node->data; if ((intptr_t)typerule->src == ckey.key1 && (intptr_t)typerule->tgt == ckey.key2 && (intptr_t)typerule->obj == ckey.key3 && (intptr_t)typerule->rule_kind == ckey.key4) { cil_log(CIL_ERR, "Duplicate type rule found (line: %d)\n", node->line); rc = SEPOL_ERR; goto exit; } } } break;*/ //TODO Fix duplicate type_rule detection break; case CIL_CALL: //Fall through to check content of call break; case CIL_TUNABLEIF: //Fall through break; case CIL_NAMETYPETRANSITION: /* While type transitions with file component are not allowed in booleanif statements if they don't have "*" as the file. We can't check that here. Or at least we won't right now. */ break; default: { const char * flavor = cil_node_to_string(node); if (bif->preserved_tunable) { cil_tree_log(node, CIL_ERR, "Invalid %s statement in tunableif (treated as a booleanif due to preserve-tunables)", flavor); } else { cil_tree_log(node, CIL_ERR, "Invalid %s statement in booleanif", flavor); } goto exit; } } rc = SEPOL_OK; exit: return rc; } static int __cil_verify_booleanif(struct cil_tree_node *node, struct cil_complex_symtab *symtab) { int rc = SEPOL_ERR; struct cil_booleanif *bif = (struct cil_booleanif*)node->data; struct cil_tree_node *cond_block = node->cl_head; while (cond_block != NULL) { rc = cil_tree_walk(cond_block, __cil_verify_booleanif_helper, NULL, NULL, symtab); if (rc != SEPOL_OK) { goto exit; } cond_block = cond_block->next; } return SEPOL_OK; exit: if (bif->preserved_tunable) { cil_tree_log(node, CIL_ERR, "Invalid tunableif (treated as a booleanif due to preserve-tunables)"); } else { cil_tree_log(node, CIL_ERR, "Invalid booleanif"); } return rc; } static int __cil_verify_netifcon(struct cil_db *db, struct cil_tree_node *node) { int rc = SEPOL_ERR; struct cil_netifcon *netif = node->data; struct cil_context *if_ctx = netif->if_context; struct cil_context *pkt_ctx = netif->packet_context; /* Verify only when anonymous */ if (if_ctx->datum.name == NULL) { rc = __cil_verify_context(db, if_ctx); if (rc != SEPOL_OK) { goto exit; } } /* Verify only when anonymous */ if (pkt_ctx->datum.name == NULL) { rc = __cil_verify_context(db, pkt_ctx); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: cil_tree_log(node, CIL_ERR, "Invalid netifcon"); return rc; } static int __cil_verify_ibendportcon(struct cil_db *db, struct cil_tree_node *node) { int rc = SEPOL_ERR; struct cil_ibendportcon *ib_end_port = node->data; struct cil_context *ctx = ib_end_port->context; /* Verify only when anonymous */ if (!ctx->datum.name) { rc = __cil_verify_context(db, ctx); if (rc != SEPOL_OK) goto exit; } return SEPOL_OK; exit: cil_tree_log(node, CIL_ERR, "Invalid ibendportcon"); return rc; } static int __cil_verify_genfscon(struct cil_db *db, struct cil_tree_node *node) { int rc = SEPOL_ERR; struct cil_genfscon *genfs = node->data; struct cil_context *ctx = genfs->context; /* Verify only when anonymous */ if (ctx->datum.name == NULL) { rc = __cil_verify_context(db, ctx); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: cil_tree_log(node, CIL_ERR, "Invalid genfscon"); return rc; } static int __cil_verify_filecon(struct cil_db *db, struct cil_tree_node *node) { int rc = SEPOL_ERR; struct cil_filecon *file = node->data; struct cil_context *ctx = file->context; if (ctx == NULL) { rc = SEPOL_OK; goto exit; } /* Verify only when anonymous */ if (ctx->datum.name == NULL) { rc = __cil_verify_context(db, ctx); if (rc != SEPOL_OK) { cil_tree_log(node, CIL_ERR, "Invalid filecon"); goto exit; } } return SEPOL_OK; exit: return rc; } static int __cil_verify_nodecon(struct cil_db *db, struct cil_tree_node *node) { int rc = SEPOL_ERR; struct cil_nodecon *nodecon = node->data; struct cil_context *ctx = nodecon->context; /* Verify only when anonymous */ if (ctx->datum.name == NULL) { rc = __cil_verify_context(db, ctx); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: cil_tree_log(node, CIL_ERR, "Invalid nodecon"); return rc; } static int __cil_verify_ibpkeycon(struct cil_db *db, struct cil_tree_node *node) { int rc = SEPOL_ERR; struct cil_ibpkeycon *pkey = node->data; struct cil_context *ctx = pkey->context; /* Verify only when anonymous */ if (!ctx->datum.name) { rc = __cil_verify_context(db, ctx); if (rc != SEPOL_OK) goto exit; } return SEPOL_OK; exit: cil_tree_log(node, CIL_ERR, "Invalid ibpkeycon"); return rc; } static int __cil_verify_portcon(struct cil_db *db, struct cil_tree_node *node) { int rc = SEPOL_ERR; struct cil_portcon *port = node->data; struct cil_context *ctx = port->context; /* Verify only when anonymous */ if (ctx->datum.name == NULL) { rc = __cil_verify_context(db, ctx); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: cil_tree_log(node, CIL_ERR, "Invalid portcon"); return rc; } static int __cil_verify_pirqcon(struct cil_db *db, struct cil_tree_node *node) { int rc = SEPOL_ERR; struct cil_pirqcon *pirq = node->data; struct cil_context *ctx = pirq->context; /* Verify only when anonymous */ if (ctx->datum.name == NULL) { rc = __cil_verify_context(db, ctx); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: cil_tree_log(node, CIL_ERR, "Invalid pirqcon"); return rc; } static int __cil_verify_iomemcon(struct cil_db *db, struct cil_tree_node *node) { int rc = SEPOL_ERR; struct cil_iomemcon *iomem = node->data; struct cil_context *ctx = iomem->context; /* Verify only when anonymous */ if (ctx->datum.name == NULL) { rc = __cil_verify_context(db, ctx); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: cil_tree_log(node, CIL_ERR, "Invalid iomemcon"); return rc; } static int __cil_verify_ioportcon(struct cil_db *db, struct cil_tree_node *node) { int rc = SEPOL_ERR; struct cil_ioportcon *ioport = node->data; struct cil_context *ctx = ioport->context; /* Verify only when anonymous */ if (ctx->datum.name == NULL) { rc = __cil_verify_context(db, ctx); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: cil_tree_log(node, CIL_ERR, "Invalid ioportcon"); return rc; } static int __cil_verify_pcidevicecon(struct cil_db *db, struct cil_tree_node *node) { int rc = SEPOL_ERR; struct cil_pcidevicecon *pcidev = node->data; struct cil_context *ctx = pcidev->context; /* Verify only when anonymous */ if (ctx->datum.name == NULL) { rc = __cil_verify_context(db, ctx); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: cil_tree_log(node, CIL_ERR, "Invalid pcidevicecon"); return rc; } static int __cil_verify_devicetreecon(struct cil_db *db, struct cil_tree_node *node) { int rc = SEPOL_ERR; struct cil_devicetreecon *dt = node->data; struct cil_context *ctx = dt->context; /* Verify only when anonymous */ if (ctx->datum.name == NULL) { rc = __cil_verify_context(db, ctx); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: cil_tree_log(node, CIL_ERR, "Invalid devicetreecon"); return rc; } static int __cil_verify_fsuse(struct cil_db *db, struct cil_tree_node *node) { int rc = SEPOL_ERR; struct cil_fsuse *fsuse = node->data; struct cil_context *ctx = fsuse->context; /* Verify only when anonymous */ if (ctx->datum.name == NULL) { rc = __cil_verify_context(db, ctx); if (rc != SEPOL_OK) { goto exit; } } return SEPOL_OK; exit: cil_tree_log(node, CIL_ERR, "Invalid fsuse"); return rc; } static int __cil_verify_permissionx(struct cil_permissionx *permx, struct cil_tree_node *node) { int rc; struct cil_list *classes = NULL; struct cil_list_item *item; struct cil_class *class; struct cil_symtab_datum *perm_datum; char *kind_str; switch (permx->kind) { case CIL_PERMX_KIND_IOCTL: kind_str = CIL_KEY_IOCTL; break; case CIL_PERMX_KIND_NLMSG: kind_str = CIL_KEY_NLMSG; break; default: cil_tree_log(node, CIL_ERR, "Invalid permissionx kind (%d)", permx->kind); rc = SEPOL_ERR; goto exit; } classes = cil_expand_class(permx->obj); cil_list_for_each(item, classes) { class = item->data; rc = cil_symtab_get_datum(&class->perms, kind_str, &perm_datum); if (rc == SEPOL_ENOENT) { if (class->common != NULL) { rc = cil_symtab_get_datum(&class->common->perms, kind_str, &perm_datum); } if (rc == SEPOL_ENOENT) { cil_tree_log(node, CIL_ERR, "Invalid permissionx: %s is not a permission of class %s", kind_str, class->datum.name); rc = SEPOL_ERR; goto exit; } } } rc = SEPOL_OK; exit: if (classes != NULL) { cil_list_destroy(&classes, CIL_FALSE); } return rc; } static int __cil_verify_avrulex(struct cil_tree_node *node) { struct cil_avrule *avrulex = node->data; return __cil_verify_permissionx(avrulex->perms.x.permx, node); } static int __cil_verify_class(struct cil_tree_node *node) { int rc = SEPOL_ERR; struct cil_class *class = node->data; if (class->common != NULL) { struct cil_class *common = class->common; struct cil_tree_node *common_node = common->datum.nodes->head->data; struct cil_tree_node *curr_com_perm = NULL; for (curr_com_perm = common_node->cl_head; curr_com_perm != NULL; curr_com_perm = curr_com_perm->next) { struct cil_perm *com_perm = curr_com_perm->data; struct cil_tree_node *curr_class_perm = NULL; for (curr_class_perm = node->cl_head; curr_class_perm != NULL; curr_class_perm = curr_class_perm->next) { struct cil_perm *class_perm = curr_class_perm->data; if (com_perm->datum.name == class_perm->datum.name) { cil_log(CIL_ERR, "Duplicate permissions between %s common and class declarations\n", class_perm->datum.name); goto exit; } } } } return SEPOL_OK; exit: cil_tree_log(node, CIL_ERR, "Invalid class"); return rc; } static int __cil_verify_policycap(struct cil_tree_node *node) { int rc; struct cil_policycap *polcap = node->data; rc = sepol_polcap_getnum((const char*)polcap->datum.name); if (rc == SEPOL_ERR) { goto exit; } return SEPOL_OK; exit: cil_tree_log(node, CIL_ERR, "Invalid policycap (%s)", (const char*)polcap->datum.name); return rc; } int __cil_verify_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args) { int rc = SEPOL_ERR; int *avrule_cnt = 0; int *handleunknown; int *mls; int *nseuserdflt = 0; int *pass = 0; struct cil_args_verify *args = extra_args; struct cil_complex_symtab *csymtab = NULL; struct cil_db *db = NULL; if (node == NULL || extra_args == NULL) { goto exit; } db = args->db; avrule_cnt = args->avrule_cnt; handleunknown = args->handleunknown; mls = args->mls; nseuserdflt = args->nseuserdflt; csymtab = args->csymtab; pass = args->pass; if (node->flavor == CIL_MACRO) { *finished = CIL_TREE_SKIP_HEAD; rc = SEPOL_OK; goto exit; } else if (node->flavor == CIL_BLOCK) { struct cil_block *blk = node->data; if (blk->is_abstract == CIL_TRUE) { *finished = CIL_TREE_SKIP_HEAD; } rc = SEPOL_OK; goto exit; } switch (*pass) { case 0: { switch (node->flavor) { case CIL_USER: rc = __cil_verify_user_post_eval(db, node); break; case CIL_SELINUXUSERDEFAULT: (*nseuserdflt)++; rc = SEPOL_OK; break; case CIL_ROLE: rc = __cil_verify_role(node); break; case CIL_TYPE: rc = __cil_verify_type(node); break; case CIL_AVRULE: (*avrule_cnt)++; rc = SEPOL_OK; break; case CIL_HANDLEUNKNOWN: if (*handleunknown != -1) { cil_log(CIL_ERR, "Policy can not have more than one handleunknown\n"); rc = SEPOL_ERR; } else { *handleunknown = ((struct cil_handleunknown*)node->data)->handle_unknown; rc = SEPOL_OK; } break; case CIL_MLS: if (*mls != -1) { cil_log(CIL_ERR, "Policy can not have more than one mls\n"); rc = SEPOL_ERR; } else { *mls = ((struct cil_mls*)node->data)->value; rc = SEPOL_OK; } break; case CIL_ROLETRANSITION: rc = SEPOL_OK; //TODO __cil_verify_rule doesn't work quite right //rc = __cil_verify_rule(node, csymtab); break; case CIL_TYPE_RULE: rc = SEPOL_OK; //TODO __cil_verify_rule doesn't work quite right //rc = __cil_verify_rule(node, csymtab); break; case CIL_BOOLEANIF: rc = __cil_verify_booleanif(node, csymtab); *finished = CIL_TREE_SKIP_HEAD; break; case CIL_LEVELRANGE: rc = __cil_verify_named_levelrange(db, node); break; case CIL_CLASS: rc = __cil_verify_class(node); break; case CIL_POLICYCAP: rc = __cil_verify_policycap(node); break; default: rc = SEPOL_OK; break; } break; } case 1: { switch (node->flavor) { case CIL_CONTEXT: rc = __cil_verify_named_context(db, node); break; case CIL_NETIFCON: rc = __cil_verify_netifcon(db, node); break; case CIL_GENFSCON: rc = __cil_verify_genfscon(db, node); break; case CIL_FILECON: rc = __cil_verify_filecon(db, node); break; case CIL_NODECON: rc = __cil_verify_nodecon(db, node); break; case CIL_IBPKEYCON: rc = __cil_verify_ibpkeycon(db, node); break; case CIL_IBENDPORTCON: rc = __cil_verify_ibendportcon(db, node); break; case CIL_PORTCON: rc = __cil_verify_portcon(db, node); break; case CIL_PIRQCON: rc = __cil_verify_pirqcon(db, node); break; case CIL_IOMEMCON: rc = __cil_verify_iomemcon(db, node); break; case CIL_IOPORTCON: rc = __cil_verify_ioportcon(db, node); break; case CIL_PCIDEVICECON: rc = __cil_verify_pcidevicecon(db, node); break; case CIL_DEVICETREECON: rc = __cil_verify_devicetreecon(db, node); break; case CIL_FSUSE: rc = __cil_verify_fsuse(db, node); break; case CIL_AVRULEX: rc = __cil_verify_avrulex(node); break; case CIL_PERMISSIONX: rc = __cil_verify_permissionx(node->data, node); break; case CIL_RANGETRANSITION: rc = SEPOL_OK; break; default: rc = SEPOL_OK; break; } break; } default: rc = SEPOL_ERR; } exit: return rc; } static int __add_perm_to_list(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, void *args) { struct cil_list *perm_list = (struct cil_list *)args; cil_list_append(perm_list, CIL_DATUM, d); return SEPOL_OK; } static int __cil_verify_classperms(struct cil_list *classperms, struct cil_symtab_datum *orig, struct cil_symtab_datum *cur, unsigned steps, unsigned limit); static int __cil_verify_map_perm(struct cil_class *class, struct cil_perm *perm, struct cil_symtab_datum *orig, unsigned steps, unsigned limit) { int rc; if (!perm->classperms) { cil_tree_log(NODE(class), CIL_ERR, "No class permissions for map class %s, permission %s", DATUM(class)->name, DATUM(perm)->name); goto exit; } rc = __cil_verify_classperms(perm->classperms, orig, &perm->datum, steps, limit); if (rc != SEPOL_OK) { cil_tree_log(NODE(class), CIL_ERR, "There was an error verifying class permissions for map class %s, permission %s", DATUM(class)->name, DATUM(perm)->name); goto exit; } return SEPOL_OK; exit: return SEPOL_ERR; } static int __cil_verify_perms(struct cil_class *class, struct cil_list *perms, struct cil_symtab_datum *orig, unsigned steps, unsigned limit) { int rc = SEPOL_ERR; int count = 0; struct cil_list_item *i = NULL; if (!perms) { cil_tree_log(NODE(class), CIL_ERR, "No permissions for class %s in class permissions", DATUM(class)->name); goto exit; } cil_list_for_each(i, perms) { count++; if (i->flavor == CIL_LIST) { rc = __cil_verify_perms(class, i->data, orig, steps, limit); if (rc != SEPOL_OK) { goto exit; } } else if (i->flavor == CIL_DATUM) { struct cil_perm *perm = i->data; if (FLAVOR(perm) == CIL_MAP_PERM) { rc = __cil_verify_map_perm(class, perm, orig, steps, limit); if (rc != SEPOL_OK) { goto exit; } } } else if (i->flavor == CIL_OP) { enum cil_flavor op = (enum cil_flavor)(uintptr_t)i->data; if (op == CIL_ALL) { struct cil_list *perm_list; struct cil_list_item *j = NULL; int count2 = 0; cil_list_init(&perm_list, CIL_MAP_PERM); cil_symtab_map(&class->perms, __add_perm_to_list, perm_list); if (class->common != NULL) { cil_symtab_map(&class->common->perms, __add_perm_to_list, perm_list); } cil_list_for_each(j, perm_list) { count2++; struct cil_perm *perm = j->data; if (FLAVOR(perm) == CIL_MAP_PERM) { rc = __cil_verify_map_perm(class, perm, orig, steps, limit); if (rc != SEPOL_OK) { cil_list_destroy(&perm_list, CIL_FALSE); goto exit; } } } cil_list_destroy(&perm_list, CIL_FALSE); if (count2 == 0) { cil_tree_log(NODE(class), CIL_ERR, "Operator \"all\" used for %s which has no permissions associated with it", DATUM(class)->name); goto exit; } } } else { cil_tree_log(NODE(class), CIL_ERR, "Permission list for %s has an unexpected flavor: %d", DATUM(class)->name, i->flavor); goto exit; } } if (count == 0) { cil_tree_log(NODE(class), CIL_ERR, "Empty permissions list for class %s in class permissions", DATUM(class)->name); goto exit; } return SEPOL_OK; exit: return SEPOL_ERR; } static int __cil_verify_classperms(struct cil_list *classperms, struct cil_symtab_datum *orig, struct cil_symtab_datum *cur, unsigned steps, unsigned limit) { int rc; struct cil_list_item *i; if (classperms == NULL) { goto exit; } if (steps > 0 && orig == cur) { cil_tree_log(NODE(cur), CIL_ERR, "Found circular class permissions involving %s", cur->name); goto exit; } else { steps++; if (steps > limit) { steps = 1; limit *= 2; orig = cur; } } cil_list_for_each(i, classperms) { if (i->flavor == CIL_CLASSPERMS) { struct cil_classperms *cp = i->data; rc = __cil_verify_perms(cp->class, cp->perms, orig, steps, limit); if (rc != SEPOL_OK) { goto exit; } } else { /* SET */ struct cil_classperms_set *cp_set = i->data; struct cil_classpermission *cp = cp_set->set; if (!cp->classperms) { cil_tree_log(NODE(cur), CIL_ERR, "Classpermission %s does not have a classpermissionset", DATUM(cp)->name); } rc = __cil_verify_classperms(cp->classperms, orig, &cp->datum, steps, limit); if (rc != SEPOL_OK) { goto exit; } } } return SEPOL_OK; exit: return SEPOL_ERR; } static int __cil_verify_classpermission(struct cil_tree_node *node) { int rc; struct cil_classpermission *cp = node->data; rc = __cil_verify_classperms(cp->classperms, &cp->datum, &cp->datum, 0, 2); if (rc != SEPOL_OK) { cil_tree_log(node, CIL_ERR, "Error verifying class permissions for classpermission %s", DATUM(cp)->name); } return rc; } struct cil_verify_map_args { struct cil_class *class; struct cil_tree_node *node; int rc; }; static int __verify_map_perm_classperms(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, void *args) { struct cil_verify_map_args *map_args = args; struct cil_perm *cmp = (struct cil_perm *)d; int rc; rc = __cil_verify_classperms(cmp->classperms, &cmp->datum, &cmp->datum, 0, 2); if (rc != SEPOL_OK) { cil_tree_log(NODE(cmp), CIL_ERR, "Error verifying class permissions for map class %s, permission %s", DATUM(map_args->class)->name, DATUM(cmp)->name); map_args->rc = rc; } return SEPOL_OK; } static int __cil_verify_map_class(struct cil_tree_node *node) { struct cil_class *mc = node->data; struct cil_verify_map_args map_args; map_args.class = mc; map_args.node = node; map_args.rc = SEPOL_OK; cil_symtab_map(&mc->perms, __verify_map_perm_classperms, &map_args); if (map_args.rc != SEPOL_OK) { return SEPOL_ERR; } return SEPOL_OK; } int __cil_pre_verify_helper(struct cil_tree_node *node, uint32_t *finished, __attribute__((unused)) void *extra_args) { int rc = SEPOL_OK; switch (node->flavor) { case CIL_MACRO: { *finished = CIL_TREE_SKIP_HEAD; break; } case CIL_BLOCK: { struct cil_block *blk = node->data; if (blk->is_abstract == CIL_TRUE) { *finished = CIL_TREE_SKIP_HEAD; } break; } case CIL_USER: rc = __cil_verify_user_pre_eval(node); break; case CIL_MAP_CLASS: rc = __cil_verify_map_class(node); break; case CIL_CLASSPERMISSION: rc = __cil_verify_classpermission(node); break; case CIL_USERATTRIBUTE: case CIL_ROLEATTRIBUTE: case CIL_TYPEATTRIBUTE: case CIL_CATSET: { struct cil_stack *stack; cil_stack_init(&stack); rc = cil_verify_no_self_reference(node->flavor, node->data, stack); cil_stack_destroy(&stack); break; } default: rc = SEPOL_OK; break; } return rc; } libsepol-3.8.1/cil/src/cil_verify.h000066400000000000000000000067441476211737200172230ustar00rootroot00000000000000/* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #ifndef CIL_VERIFY_H_ #define CIL_VERIFY_H_ #include #include "cil_internal.h" #include "cil_flavor.h" #include "cil_tree.h" #include "cil_list.h" enum cil_syntax { CIL_SYN_STRING = 1 << 0, CIL_SYN_LIST = 1 << 1, CIL_SYN_EMPTY_LIST = 1 << 2, CIL_SYN_N_LISTS = 1 << 3, CIL_SYN_N_STRINGS = 1 << 4, CIL_SYN_END = 1 << 5 }; struct cil_args_verify { struct cil_db *db; struct cil_complex_symtab *csymtab; int *avrule_cnt; int *handleunknown; int *mls; int *nseuserdflt; int *pass; }; int cil_verify_name(const struct cil_db *db, const char *name, enum cil_flavor flavor); int __cil_verify_syntax(struct cil_tree_node *parse_current, enum cil_syntax s[], size_t 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_conditional_blocks(struct cil_tree_node *current); int cil_verify_decl_does_not_shadow_macro_parameter(struct cil_macro *macro, struct cil_tree_node *node, const char *name); int __cil_verify_ranges(struct cil_list *list); int cil_verify_completed_ordered_list(struct cil_list *complete, struct cil_list *ordered_lists); int __cil_verify_ordered_node_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args); int __cil_verify_ordered(struct cil_tree_node *current, enum cil_flavor flavor); int __cil_verify_initsids(struct cil_list *sids); int __cil_verify_senscat(struct cil_sens *sens, struct cil_cat *cat); int __cil_verify_helper(struct cil_tree_node *node, __attribute__((unused)) uint32_t *finished, void *extra_args); int __cil_pre_verify_helper(struct cil_tree_node *node, __attribute__((unused)) uint32_t *finished, void *extra_args); #endif libsepol-3.8.1/cil/src/cil_write_ast.c000066400000000000000000001326251476211737200177110ustar00rootroot00000000000000/* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #include #include #include #include #include "cil_internal.h" #include "cil_flavor.h" #include "cil_list.h" #include "cil_log.h" #include "cil_symtab.h" #include "cil_tree.h" #include "cil_write_ast.h" static inline const char *datum_or_str(struct cil_symtab_datum *datum, const char *str) { return datum && datum->fqn ? datum->fqn : str; } static inline const char *datum_to_str(struct cil_symtab_datum *datum) { return datum ? datum->fqn : ""; } static void write_expr(FILE *out, struct cil_list *expr) { struct cil_list_item *curr; int notfirst = 0; fprintf(out, "("); cil_list_for_each(curr, expr) { if (notfirst) fprintf(out, " "); else notfirst = 1; switch (curr->flavor) { case CIL_LIST: write_expr(out, curr->data); break; case CIL_STRING: fprintf(out, "%s", (char *)curr->data); break; case CIL_DATUM: case CIL_TYPE: case CIL_ROLE: case CIL_USER: case CIL_SENS: case CIL_CAT: case CIL_BOOL: case CIL_CLASS: case CIL_MAP_CLASS: case CIL_DECLARED_STRING: fprintf(out, "%s", datum_to_str(curr->data)); break; case CIL_OP: { const char *op_str; enum cil_flavor op_flavor = (enum cil_flavor)(uintptr_t)curr->data; switch (op_flavor) { case CIL_AND: op_str = CIL_KEY_AND; break; case CIL_OR: op_str = CIL_KEY_OR; break; case CIL_NOT: op_str = CIL_KEY_NOT; break; case CIL_ALL: op_str = CIL_KEY_ALL; break; case CIL_EQ: op_str = CIL_KEY_EQ; break; case CIL_NEQ: op_str = CIL_KEY_NEQ; break; case CIL_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: op_str = ""; break; } fprintf(out, "%s", op_str); break; } case CIL_CONS_OPERAND: { const char *operand_str; enum cil_flavor operand_flavor = (enum cil_flavor)(uintptr_t)curr->data; 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: operand_str = ""; break; } fprintf(out, "%s", operand_str); break; } default: fprintf(out, ""); break; } } fprintf(out, ")"); } static void write_node_list(FILE *out, struct cil_tree_node *current) { int notfirst = 0; fprintf(out, "("); while (current) { if (notfirst) fprintf(out, " "); else notfirst = 1; fprintf(out, "%s", datum_to_str(current->data)); current = current->next; } fprintf(out, ")"); } static void write_string_list(FILE *out, struct cil_list *list) { struct cil_list_item *curr; int notfirst = 0; if (!list) { fprintf(out, "()"); return; } fprintf(out, "("); cil_list_for_each(curr, list) { if (notfirst) fprintf(out, " "); else notfirst = 1; fprintf(out, "%s", (char*)curr->data); } fprintf(out, ")"); } static void write_datum_list(FILE *out, struct cil_list *list) { struct cil_list_item *curr; int notfirst = 0; if (!list) { fprintf(out, "()"); return; } fprintf(out, "("); cil_list_for_each(curr, list) { if (notfirst) fprintf(out, " "); else notfirst = 1; fprintf(out, "%s", datum_to_str(curr->data)); } fprintf(out, ")"); } static void write_classperms(FILE *out, struct cil_classperms *cp) { if (!cp) { fprintf(out, "()"); return; } fprintf(out, "(%s ", datum_or_str(DATUM(cp->class), cp->class_str)); if (cp->perms) write_expr(out, cp->perms); else write_expr(out, cp->perm_strs); fprintf(out, ")"); } static void write_classperms_list(FILE *out, struct cil_list *cp_list) { struct cil_list_item *curr; int notfirst = 0; int num = 0; if (!cp_list) { fprintf(out, "()"); return; } cil_list_for_each(curr, cp_list) { num++; } if (num > 1) fprintf(out, "("); cil_list_for_each(curr, cp_list) { if (notfirst) fprintf(out, " "); else notfirst = 1; if (curr->flavor == CIL_CLASSPERMS) { write_classperms(out, curr->data); } else { struct cil_classperms_set *cp_set = curr->data; struct cil_classpermission *cp = cp_set->set; if (cp) { if (cp->datum.name) fprintf(out, "%s", datum_to_str(DATUM(cp))); else write_classperms_list(out,cp->classperms); } else { fprintf(out, "%s", cp_set->set_str); } } } if (num > 1) fprintf(out, ")"); } static void write_permx(FILE *out, struct cil_permissionx *permx) { if (permx->datum.name) { fprintf(out, "%s", datum_to_str(DATUM(permx))); } else { fprintf(out, "("); if (permx->kind == CIL_PERMX_KIND_IOCTL) { fprintf(out, "ioctl "); } else if (permx->kind == CIL_PERMX_KIND_NLMSG) { fprintf(out, "nlmsg "); } else { fprintf(out, " "); } fprintf(out, "%s ", datum_or_str(DATUM(permx->obj), permx->obj_str)); write_expr(out, permx->expr_str); fprintf(out, ")"); } } static void write_cats(FILE *out, struct cil_cats *cats) { if (cats->datum_expr) { write_expr(out, cats->datum_expr); } else { write_expr(out, cats->str_expr); } } static void write_level(FILE *out, struct cil_level *level, int print_name) { if (print_name && level->datum.name) { fprintf(out, "%s", datum_to_str(DATUM(level))); } else { fprintf(out, "("); fprintf(out, "%s", datum_or_str(DATUM(level->sens), level->sens_str)); if (level->cats) { fprintf(out, " "); write_cats(out, level->cats); } fprintf(out, ")"); } } static void write_range(FILE *out, struct cil_levelrange *range, int print_name) { if (print_name && range->datum.name) { fprintf(out, "%s", datum_to_str(DATUM(range))); } else { fprintf(out, "("); if (range->low) write_level(out, range->low, CIL_TRUE); else fprintf(out, "%s", range->low_str); fprintf(out, " "); if (range->high) write_level(out, range->high, CIL_TRUE); else fprintf(out, "%s", range->high_str); fprintf(out, ")"); } } static void write_context(FILE *out, struct cil_context *context, int print_name) { if (print_name && context->datum.name) { fprintf(out, "%s", datum_to_str(DATUM(context))); } else { fprintf(out, "("); fprintf(out, "%s ", datum_or_str(DATUM(context->user), context->user_str)); fprintf(out, "%s ", datum_or_str(DATUM(context->role), context->role_str)); fprintf(out, "%s ", datum_or_str(DATUM(context->type), context->type_str)); if (context->range) write_range(out, context->range, CIL_TRUE); else fprintf(out, "%s", context->range_str); fprintf(out, ")"); } } static void write_ipaddr(FILE *out, struct cil_ipaddr *ipaddr) { if (ipaddr->datum.name) { fprintf(out, "%s", datum_to_str(DATUM(ipaddr))); } else { char buf[256]; if (inet_ntop(ipaddr->family, &ipaddr->ip, buf, 256) == NULL) strcpy(buf, ""); fprintf(out, "(%s)", buf); } } static void write_constrain(FILE *out, struct cil_constrain *cons) { write_classperms_list(out, cons->classperms); fprintf(out, " "); if (cons->datum_expr) write_expr(out, cons->datum_expr); else write_expr(out, cons->str_expr); } static void write_call_args(FILE *out, struct cil_list *args) { struct cil_list_item *item; int notfirst = 0; fprintf(out, "("); cil_list_for_each(item, args) { struct cil_args* arg = item->data; enum cil_flavor arg_flavor = arg->flavor; if (notfirst) fprintf(out, " "); else notfirst = 1; switch (arg_flavor) { case CIL_TYPE: case CIL_ROLE: case CIL_USER: case CIL_SENS: case CIL_CAT: case CIL_BOOL: case CIL_CLASS: case CIL_MAP_CLASS: { fprintf(out, "%s", datum_or_str(DATUM(arg->arg), arg->arg_str)); break; } case CIL_DECLARED_STRING: { if (arg->arg) { fprintf(out, "\"%s\" ", DATUM(arg->arg)->fqn); } else { fprintf(out, "%s ", arg->arg_str); } break; } case CIL_CATSET: { if (arg->arg) { struct cil_catset *catset = (struct cil_catset *)arg->arg; write_cats(out, catset->cats); } else { fprintf(out, "%s", arg->arg_str); } break; } case CIL_LEVEL: { if (arg->arg) { struct cil_level *level = (struct cil_level *)arg->arg; write_level(out, level, CIL_TRUE); } else { fprintf(out, "%s", arg->arg_str); } break; } case CIL_LEVELRANGE: { if (arg->arg) { struct cil_levelrange *range = (struct cil_levelrange *)arg->arg; write_range(out, range, CIL_TRUE); } else { fprintf(out, "%s", arg->arg_str); } break; } case CIL_IPADDR: { if (arg->arg) { struct cil_ipaddr *addr = (struct cil_ipaddr *)arg->arg; write_ipaddr(out, addr); } else { fprintf(out, "%s", arg->arg_str); } break; } case CIL_CLASSPERMISSION: { if (arg->arg) { struct cil_classpermission *cp = (struct cil_classpermission *)arg->arg; if (cp->datum.name) fprintf(out, "%s", datum_to_str(DATUM(cp))); else write_classperms_list(out, cp->classperms); } else { fprintf(out, "%s", arg->arg_str); } break; } default: fprintf(out, "", datum_or_str(DATUM(arg->arg), arg->arg_str)); break; } } fprintf(out, ")"); } static void write_call_args_tree(FILE *out, struct cil_tree_node *arg_node) { while (arg_node) { if (arg_node->data) { fprintf(out, "%s", (char *)arg_node->data); } else if (arg_node->cl_head) { fprintf(out, "("); write_call_args_tree(out, arg_node->cl_head); fprintf(out, ")"); } if (arg_node->next) fprintf(out, " "); arg_node = arg_node->next; } } static const char *macro_param_flavor_to_string(enum cil_flavor flavor) { const char *str; switch(flavor) { case CIL_TYPE: str = CIL_KEY_TYPE; break; case CIL_ROLE: str = CIL_KEY_ROLE; break; case CIL_USER: str = CIL_KEY_USER; break; case CIL_SENS: str = CIL_KEY_SENSITIVITY; break; case CIL_CAT: str = CIL_KEY_CATEGORY; break; case CIL_CATSET: str = CIL_KEY_CATSET; break; case CIL_LEVEL: str = CIL_KEY_LEVEL; break; case CIL_LEVELRANGE: str = CIL_KEY_LEVELRANGE; break; case CIL_CLASS: str = CIL_KEY_CLASS; break; case CIL_IPADDR: str = CIL_KEY_IPADDR; break; case CIL_MAP_CLASS: str = CIL_KEY_MAP_CLASS; break; case CIL_CLASSPERMISSION: str = CIL_KEY_CLASSPERMISSION; break; case CIL_BOOL: str = CIL_KEY_BOOL; break; case CIL_DECLARED_STRING: str = CIL_KEY_STRING; break; default: str = ""; break; } return str; } static void cil_write_src_info_node(FILE *out, struct cil_tree_node *node) { struct cil_src_info *info = node->data; if (info->kind == CIL_KEY_SRC_CIL || info->kind == CIL_KEY_SRC_HLL_LMS) { fprintf(out, ";;* lms %u %s\n", info->hll_line, info->path); } else if (info->kind == CIL_KEY_SRC_HLL_LMX) { fprintf(out, ";;* lmx %u %s\n", info->hll_line, info->path); } else { fprintf(out, ";;* %u %s\n", info->hll_line, info->path); } } void cil_write_ast_node(FILE *out, struct cil_tree_node *node) { if (!node->data) { return; } switch(node->flavor) { case CIL_NODE: { fprintf(out, "%s\n", (char *)node->data); break; } case CIL_BLOCK: { struct cil_block *block = node->data; fprintf(out, "(block %s", datum_to_str(DATUM(block))); if (!node->cl_head) fprintf(out, ")"); fprintf(out, "\n"); break; } case CIL_BLOCKINHERIT: { struct cil_blockinherit *inherit = node->data; fprintf(out, "(blockinherit %s)\n", datum_or_str(DATUM(inherit->block), inherit->block_str)); break; } case CIL_IN: { struct cil_in *in = node->data; fprintf(out, "(in %s", datum_or_str(DATUM(in->block), in->block_str)); if (!node->cl_head) fprintf(out, ")"); fprintf(out, "\n"); break; } case CIL_OPTIONAL: { struct cil_optional *optional = node->data; fprintf(out, "(optional %s", datum_to_str(DATUM(optional))); if (!node->cl_head) fprintf(out, ")"); fprintf(out, "\n"); break; } case CIL_BOOLEANIF: { struct cil_booleanif *bif = node->data; fprintf(out, "(booleanif "); if (bif->datum_expr) write_expr(out, bif->datum_expr); else write_expr(out, bif->str_expr); if (!node->cl_head) fprintf(out, ")"); fprintf(out, "\n"); break; } case CIL_TUNABLEIF: { struct cil_tunableif *tif = node->data; fprintf(out, "(tunableif "); if (tif->datum_expr) write_expr(out, tif->datum_expr); else write_expr(out, tif->str_expr); if (!node->cl_head) fprintf(out, ")"); fprintf(out, "\n"); break; } case CIL_CONDBLOCK: { struct cil_condblock *cb = node->data; fprintf(out, "(%s", cb->flavor == CIL_CONDTRUE ? "true" : "false"); if (!node->cl_head) fprintf(out, ")"); fprintf(out, "\n"); break; } case CIL_MACRO: { struct cil_macro *macro = node->data; struct cil_list_item *curr; fprintf(out, "(macro %s (", datum_to_str(DATUM(macro))); if (macro->params) { cil_list_for_each(curr, macro->params) { struct cil_param *param = curr->data; fprintf(out, "(%s %s)", macro_param_flavor_to_string(param->flavor), param->str); } } fprintf(out, ")"); if (!node->cl_head) fprintf(out, ")"); fprintf(out, "\n"); break; } case CIL_CALL: { struct cil_call *call = node->data; fprintf(out, "(call %s", datum_or_str(DATUM(call->macro), call->macro_str)); if (call->args) { fprintf(out, " "); write_call_args(out, call->args); } else if (call->args_tree) { fprintf(out, " "); write_call_args_tree(out, call->args_tree->root); } if (!node->cl_head) fprintf(out, ")"); fprintf(out, "\n"); break; } case CIL_BLOCKABSTRACT: { struct cil_blockabstract *abstract = node->data; fprintf(out, "(blockabstract %s)\n", datum_or_str(DATUM(abstract->block), abstract->block_str)); break; } case CIL_MLS: { struct cil_mls *mls = node->data; fprintf(out, "(mls %s)\n", mls->value ? "true" : "false"); break; } case CIL_HANDLEUNKNOWN: { struct cil_handleunknown *unknown = node->data; fprintf(out, "(handleunknown "); if (unknown->handle_unknown == SEPOL_ALLOW_UNKNOWN) fprintf(out, "%s", CIL_KEY_HANDLEUNKNOWN_ALLOW); else if (unknown->handle_unknown == SEPOL_DENY_UNKNOWN) fprintf(out, "%s", CIL_KEY_HANDLEUNKNOWN_DENY); else if (unknown->handle_unknown == SEPOL_REJECT_UNKNOWN) fprintf(out, "%s", CIL_KEY_HANDLEUNKNOWN_REJECT); else fprintf(out, ""); fprintf(out, ")\n"); break; } case CIL_DEFAULTUSER: { struct cil_default *def = node->data; fprintf(out, "(defaultuser "); if (def->class_datums) write_datum_list(out, def->class_datums); else write_string_list(out, def->class_strs); if (def->object == CIL_DEFAULT_SOURCE) fprintf(out, " source"); else if (def->object == CIL_DEFAULT_TARGET) fprintf(out, " target"); else fprintf(out, " "); fprintf(out, ")\n"); break; } case CIL_DEFAULTROLE: { struct cil_default *def = node->data; fprintf(out, "(defaultrole "); if (def->class_datums) write_datum_list(out, def->class_datums); else write_string_list(out, def->class_strs); if (def->object == CIL_DEFAULT_SOURCE) fprintf(out, " source"); else if (def->object == CIL_DEFAULT_TARGET) fprintf(out, " target"); else fprintf(out, " "); fprintf(out, ")\n"); break; } case CIL_DEFAULTTYPE: { struct cil_default *def = node->data; fprintf(out, "(defaulttype "); if (def->class_datums) write_datum_list(out, def->class_datums); else write_string_list(out, def->class_strs); if (def->object == CIL_DEFAULT_SOURCE) fprintf(out, " source"); else if (def->object == CIL_DEFAULT_TARGET) fprintf(out, " target"); else fprintf(out, " "); fprintf(out, ")\n"); break; } case CIL_DEFAULTRANGE: { struct cil_defaultrange *def = node->data; fprintf(out, "(defaultrange "); if (def->class_datums) write_datum_list(out, def->class_datums); else write_string_list(out, def->class_strs); if (def->object_range == CIL_DEFAULT_SOURCE_LOW) fprintf(out, " source low"); else if (def->object_range == CIL_DEFAULT_SOURCE_HIGH) fprintf(out, " source high"); else if (def->object_range == CIL_DEFAULT_SOURCE_LOW_HIGH) fprintf(out, " source low-high"); else if (def->object_range == CIL_DEFAULT_TARGET_LOW) fprintf(out, " target low"); else if (def->object_range == CIL_DEFAULT_TARGET_HIGH) fprintf(out, " target high"); else if (def->object_range == CIL_DEFAULT_TARGET_LOW_HIGH) fprintf(out, " target low-high"); else fprintf(out, " "); fprintf(out, ")\n"); break; } case CIL_CLASS: { struct cil_class *class = node->data; fprintf(out, "(class %s ", datum_to_str(DATUM(class))); write_node_list(out, node->cl_head); fprintf(out, ")\n"); break; } case CIL_CLASSORDER: { struct cil_ordered *ordered = node->data; fprintf(out, "(classorder "); if (ordered->datums) { write_datum_list(out, ordered->datums); } else { write_string_list(out, ordered->strs); } fprintf(out, ")\n"); break; } case CIL_COMMON: { struct cil_class *common = node->data; fprintf(out, "(common %s ", datum_to_str(DATUM(common))); write_node_list(out, node->cl_head); fprintf(out, ")\n"); break; } case CIL_CLASSCOMMON: { struct cil_classcommon *cc = node->data; fprintf(out, "(classcommon %s ", datum_or_str(DATUM(cc->class), cc->class_str)); fprintf(out, "%s", datum_or_str(DATUM(cc->common), cc->common_str)); fprintf(out, ")\n"); break; } case CIL_CLASSPERMISSION: { struct cil_classpermission *cp = node->data; fprintf(out, "(classpermission %s)\n", datum_to_str(DATUM(cp))); break; } case CIL_CLASSPERMISSIONSET: { struct cil_classpermissionset *cps = node->data; fprintf(out, "(classpermissionset %s ", datum_or_str(DATUM(cps->set), cps->set_str)); write_classperms_list(out, cps->classperms); fprintf(out, ")\n"); break; } case CIL_MAP_CLASS: { struct cil_class *map = node->data; fprintf(out, "(classmap %s ", datum_to_str(DATUM(map))); write_node_list(out, node->cl_head); fprintf(out, ")\n"); break; } case CIL_CLASSMAPPING: { struct cil_classmapping *mapping = node->data; fprintf(out, "(classmapping %s ", datum_or_str(DATUM(mapping->map_class), mapping->map_class_str)); fprintf(out, "%s ", datum_or_str(DATUM(mapping->map_perm), mapping->map_perm_str)); write_classperms_list(out, mapping->classperms); fprintf(out, ")\n"); break; } case CIL_PERMISSIONX: { struct cil_permissionx *permx = node->data; fprintf(out, "(permissionx %s (", datum_to_str(DATUM(permx))); if (permx->kind == CIL_PERMX_KIND_IOCTL) { fprintf(out, "ioctl "); } else if (permx->kind == CIL_PERMX_KIND_NLMSG) { fprintf(out, "nlmsg "); } else { fprintf(out, " "); } fprintf(out, "%s ", datum_or_str(DATUM(permx->obj), permx->obj_str)); write_expr(out, permx->expr_str); fprintf(out, "))\n"); break; } case CIL_SID: { struct cil_sid *sid = node->data; fprintf(out, "(sid %s)\n", datum_to_str(DATUM(sid))); break; } case CIL_SIDCONTEXT: { struct cil_sidcontext *sidcon = node->data; fprintf(out, "(sidcontext %s ", datum_or_str(DATUM(sidcon->sid), sidcon->sid_str)); if (sidcon->context) write_context(out, sidcon->context, CIL_TRUE); else fprintf(out, "%s", sidcon->context_str); fprintf(out, ")\n"); break; } case CIL_SIDORDER: { struct cil_ordered *ordered = node->data; fprintf(out, "(sidorder "); if (ordered->datums) { write_datum_list(out, ordered->datums); } else { write_string_list(out, ordered->strs); } fprintf(out, ")\n"); break; } case CIL_BOOL: { struct cil_bool *boolean = node->data; fprintf(out, "(boolean %s %s)\n", datum_to_str(DATUM(boolean)), boolean->value ? "true" : "false"); break; } case CIL_TUNABLE: { struct cil_tunable *tunable = node->data; fprintf(out, "(tunable %s %s)\n", datum_to_str(DATUM(tunable)), tunable->value ? "true" : "false"); break; } case CIL_SENS: { struct cil_sens *sens = node->data; fprintf(out, "(sensitivity %s)\n", datum_to_str(DATUM(sens))); break; } case CIL_SENSALIAS: { struct cil_alias *alias = node->data; fprintf(out, "(sensitivityalias %s)\n", datum_to_str(DATUM(alias))); break; } case CIL_SENSALIASACTUAL: { struct cil_aliasactual *aliasactual = node->data; fprintf(out, "(sensitivityaliasactual %s ", datum_or_str(DATUM(aliasactual->alias), aliasactual->alias_str)); fprintf(out, "%s", datum_or_str(DATUM(aliasactual->actual), aliasactual->actual_str)); fprintf(out, ")\n"); break; } case CIL_CAT: { struct cil_cat *cat = node->data; fprintf(out, "(category %s)\n", datum_to_str(DATUM(cat))); break; } case CIL_CATALIAS: { struct cil_alias *alias = node->data; fprintf(out, "(categoryalias %s)\n", datum_to_str(DATUM(alias))); break; } case CIL_CATALIASACTUAL: { struct cil_aliasactual *aliasactual = node->data; fprintf(out, "(categoryaliasactual %s ", datum_or_str(DATUM(aliasactual->alias), aliasactual->alias_str)); fprintf(out, "%s", datum_or_str(DATUM(aliasactual->actual), aliasactual->actual_str)); fprintf(out, ")\n"); break; } case CIL_CATSET: { struct cil_catset *catset = node->data; fprintf(out, "(categoryset %s ", datum_to_str(DATUM(catset))); write_cats(out, catset->cats); fprintf(out, ")\n"); break; } case CIL_CATORDER: { struct cil_ordered *ordered = node->data; fprintf(out, "(categoryorder "); if (ordered->datums) { write_datum_list(out, ordered->datums); } else { write_string_list(out, ordered->strs); } fprintf(out, ")\n"); break; } case CIL_SENSCAT: { struct cil_senscat *senscat = node->data; fprintf(out, "(sensitivitycategory "); fprintf(out, "%s ", datum_or_str(DATUM(senscat->sens), senscat->sens_str)); write_cats(out, senscat->cats); fprintf(out, ")\n"); break; } case CIL_SENSITIVITYORDER: { struct cil_ordered *ordered = node->data; fprintf(out, "(sensitivityorder "); if (ordered->datums) { write_datum_list(out, ordered->datums); } else { write_string_list(out, ordered->strs); } fprintf(out, ")\n"); break; } case CIL_LEVEL: { struct cil_level *level = node->data; fprintf(out, "(level %s ", datum_to_str(&level->datum)); write_level(out, level, CIL_FALSE); fprintf(out, ")\n"); break; } case CIL_LEVELRANGE: { struct cil_levelrange *lvlrange = node->data; fprintf(out, "(levelrange %s ", datum_to_str(DATUM(lvlrange))); write_range(out, lvlrange, CIL_FALSE); fprintf(out, ")\n"); break; } case CIL_USER: { struct cil_user *user = node->data; fprintf(out, "(user %s)\n", datum_to_str(DATUM(user))); break; } case CIL_USERATTRIBUTE: { struct cil_userattribute *attr = node->data; fprintf(out, "(userattribute %s)\n", datum_to_str(DATUM(attr))); break; } case CIL_USERATTRIBUTESET: { struct cil_userattributeset *attr = node->data; fprintf(out, "(userattributeset %s ", datum_or_str(DATUM(attr->attr), attr->attr_str)); if (attr->datum_expr) write_expr(out, attr->datum_expr); else write_expr(out, attr->str_expr); fprintf(out, ")\n"); break; } case CIL_USERROLE: { struct cil_userrole *userrole = node->data; fprintf(out, "(userrole "); fprintf(out, "%s ", datum_or_str(DATUM(userrole->user), userrole->user_str)); fprintf(out, "%s", datum_or_str(DATUM(userrole->role), userrole->role_str)); fprintf(out, ")\n"); break; } case CIL_USERLEVEL: { struct cil_userlevel *userlevel = node->data; fprintf(out, "(userlevel %s ", datum_or_str(DATUM(userlevel->user), userlevel->user_str)); if (userlevel->level) write_level(out, userlevel->level, CIL_TRUE); else fprintf(out, "%s", userlevel->level_str); fprintf(out, ")\n"); break; } case CIL_USERRANGE: { struct cil_userrange *userrange = node->data; fprintf(out, "(userrange %s ", datum_or_str(DATUM(userrange->user), userrange->user_str)); if (userrange->range) write_range(out, userrange->range, CIL_TRUE); else fprintf(out, "%s", userrange->range_str); fprintf(out, ")\n"); break; } case CIL_USERBOUNDS: { struct cil_bounds *bounds = node->data; fprintf(out, "(userbounds "); fprintf(out, "%s ", datum_or_str(DATUM(bounds->parent), bounds->parent_str)); fprintf(out, "%s)\n", datum_or_str(DATUM(bounds->child), bounds->child_str)); break; } case CIL_USERPREFIX: { struct cil_userprefix *prefix = node->data; fprintf(out, "(userprefix "); fprintf(out, "%s ", datum_or_str(DATUM(prefix->user), prefix->user_str)); fprintf(out, "%s)\n", prefix->prefix_str); break; } case CIL_SELINUXUSER: { struct cil_selinuxuser *selinuxuser = node->data; fprintf(out, "(selinuxuser %s ", selinuxuser->name_str); fprintf(out, "%s ", datum_or_str(DATUM(selinuxuser->user), selinuxuser->user_str)); if (selinuxuser->range) write_range(out, selinuxuser->range, CIL_TRUE); else fprintf(out, "%s", selinuxuser->range_str); fprintf(out, ")\n"); break; } case CIL_SELINUXUSERDEFAULT: { struct cil_selinuxuser *selinuxuser = node->data; fprintf(out, "(selinuxuserdefault "); fprintf(out, "%s ", datum_or_str(DATUM(selinuxuser->user), selinuxuser->user_str)); if (selinuxuser->range) write_range(out, selinuxuser->range, CIL_TRUE); else fprintf(out, "%s", selinuxuser->range_str); fprintf(out, ")\n"); break; } case CIL_ROLE: { fprintf(out, "(role %s)\n", datum_to_str(node->data)); break; } case CIL_ROLEATTRIBUTE: { fprintf(out, "(roleattribute %s)\n", datum_to_str(node->data)); break; } case CIL_ROLEATTRIBUTESET: { struct cil_roleattributeset *attr = node->data; fprintf(out, "(roleattributeset %s ", datum_or_str(DATUM(attr->attr), attr->attr_str)); if (attr->datum_expr) write_expr(out, attr->datum_expr); else write_expr(out, attr->str_expr); fprintf(out, ")\n"); break; } case CIL_ROLETYPE: { struct cil_roletype *roletype = node->data; fprintf(out, "(roletype "); fprintf(out, "%s ", datum_or_str(DATUM(roletype->role), roletype->role_str)); fprintf(out, "%s", datum_or_str(DATUM(roletype->type), roletype->type_str)); fprintf(out, ")\n"); break; } case CIL_ROLEBOUNDS: { struct cil_bounds *bounds = node->data; fprintf(out, "(rolebounds "); fprintf(out, "%s ", datum_or_str(DATUM(bounds->parent), bounds->parent_str)); fprintf(out, "%s)\n", datum_or_str(DATUM(bounds->child), bounds->child_str)); break; } case CIL_TYPE: { fprintf(out, "(type %s)\n", datum_to_str(node->data)); break; } case CIL_TYPEALIAS: { fprintf(out, "(typealias %s)\n", datum_to_str(node->data)); break; } case CIL_TYPEALIASACTUAL: { struct cil_aliasactual *aliasactual = node->data; fprintf(out, "(typealiasactual %s ", datum_or_str(DATUM(aliasactual->alias), aliasactual->alias_str)); fprintf(out, "%s", datum_or_str(DATUM(aliasactual->actual), aliasactual->actual_str)); fprintf(out, ")\n"); break; } case CIL_TYPEATTRIBUTE: { fprintf(out, "(typeattribute %s)\n", datum_to_str(node->data)); break; } case CIL_TYPEATTRIBUTESET: { struct cil_typeattributeset *attr = node->data; fprintf(out, "(typeattributeset %s ", datum_or_str(DATUM(attr->attr), attr->attr_str)); if (attr->datum_expr) write_expr(out, attr->datum_expr); else write_expr(out, attr->str_expr); fprintf(out, ")\n"); break; } case CIL_EXPANDTYPEATTRIBUTE: { struct cil_expandtypeattribute *attr = node->data; fprintf(out, "(expandtypeattribute "); if (attr->attr_datums) write_expr(out, attr->attr_datums); else write_expr(out, attr->attr_strs); fprintf(out, " %s)\n", attr->expand ? "true" : "false"); break; } case CIL_TYPEPERMISSIVE: { struct cil_typepermissive *tp = node->data; fprintf(out, "(typepermissive "); fprintf(out, "%s", datum_or_str(DATUM(tp->type), tp->type_str)); fprintf(out, ")\n"); break; } case CIL_TYPEBOUNDS: { struct cil_bounds *bounds = node->data; fprintf(out, "(typebounds "); fprintf(out, "%s ", datum_or_str(DATUM(bounds->parent), bounds->parent_str)); fprintf(out, "%s)\n", datum_or_str(DATUM(bounds->child), bounds->child_str)); break; } case CIL_ROLEALLOW: { struct cil_roleallow *roleallow = node->data; fprintf(out, "(roleallow "); fprintf(out, "%s ", datum_or_str(DATUM(roleallow->src), roleallow->src_str)); fprintf(out, "%s", datum_or_str(DATUM(roleallow->tgt), roleallow->tgt_str)); fprintf(out, ")\n"); break; } case CIL_ROLETRANSITION: { struct cil_roletransition *roletrans = node->data; fprintf(out, "(roletransition "); fprintf(out, "%s ", datum_or_str(DATUM(roletrans->src), roletrans->src_str)); fprintf(out, "%s ", datum_or_str(DATUM(roletrans->tgt), roletrans->tgt_str)); fprintf(out, "%s ", datum_or_str(DATUM(roletrans->obj), roletrans->obj_str)); fprintf(out, "%s", datum_or_str(DATUM(roletrans->result), roletrans->result_str)); fprintf(out, ")\n"); break; } case CIL_AVRULE: { struct cil_avrule *rule = node->data; if (rule->rule_kind == AVRULE_ALLOWED) fprintf(out, "(allow "); else if (rule->rule_kind == AVRULE_AUDITALLOW) fprintf(out, "(auditallow "); else if (rule->rule_kind == AVRULE_DONTAUDIT) fprintf(out, "(dontaudit "); else if (rule->rule_kind == AVRULE_NEVERALLOW) fprintf(out, "(neverallow "); else fprintf(out, "( "); fprintf(out, "%s ", datum_or_str(DATUM(rule->src), rule->src_str)); fprintf(out, "%s ", datum_or_str(DATUM(rule->tgt), rule->tgt_str)); write_classperms_list(out, rule->perms.classperms); fprintf(out, ")\n"); break; } case CIL_AVRULEX: { struct cil_avrule *rule = node->data; if (rule->rule_kind == AVRULE_ALLOWED) fprintf(out, "(allowx "); else if (rule->rule_kind == AVRULE_AUDITALLOW) fprintf(out, "(auditallowx "); else if (rule->rule_kind == AVRULE_DONTAUDIT) fprintf(out, "(dontauditx "); else if (rule->rule_kind == AVRULE_NEVERALLOW) fprintf(out, "(neverallowx "); else fprintf(out, "( "); fprintf(out, "%s ", datum_or_str(DATUM(rule->src), rule->src_str)); fprintf(out, "%s ", datum_or_str(DATUM(rule->tgt), rule->tgt_str)); if (rule->perms.x.permx_str) { fprintf(out, "%s",rule->perms.x.permx_str); } else { write_permx(out, rule->perms.x.permx); } fprintf(out, ")\n"); break; } case CIL_DENY_RULE: { struct cil_deny_rule *rule = node->data; fprintf(out, "(deny "); fprintf(out, "%s ", datum_or_str(DATUM(rule->src), rule->src_str)); fprintf(out, "%s ", datum_or_str(DATUM(rule->tgt), rule->tgt_str)); write_classperms_list(out, rule->classperms); fprintf(out, ")\n"); break; } case CIL_TYPE_RULE: { struct cil_type_rule *rule = node->data; if (rule->rule_kind == AVRULE_TRANSITION) fprintf(out, "(typetransition "); else if (rule->rule_kind == AVRULE_MEMBER) fprintf(out, "(typemember "); else if (rule->rule_kind == AVRULE_CHANGE) fprintf(out, "(typechange "); else fprintf(out, "( "); fprintf(out, "%s ", datum_or_str(DATUM(rule->src), rule->src_str)); fprintf(out, "%s ", datum_or_str(DATUM(rule->tgt), rule->tgt_str)); fprintf(out, "%s ", datum_or_str(DATUM(rule->obj), rule->obj_str)); fprintf(out, "%s", datum_or_str(DATUM(rule->result), rule->result_str)); fprintf(out, ")\n"); break; } case CIL_NAMETYPETRANSITION: { struct cil_nametypetransition *rule = node->data; fprintf(out, "(typetransition "); fprintf(out, "%s ", datum_or_str(DATUM(rule->src), rule->src_str)); fprintf(out, "%s ", datum_or_str(DATUM(rule->tgt), rule->tgt_str)); fprintf(out, "%s ", datum_or_str(DATUM(rule->obj), rule->obj_str)); if (rule->name) { fprintf(out, "\"%s\" ", DATUM(rule->name)->fqn); } else { fprintf(out, "%s ", rule->name_str); } fprintf(out, "%s", datum_or_str(DATUM(rule->result), rule->result_str)); fprintf(out, ")\n"); break; } case CIL_RANGETRANSITION: { struct cil_rangetransition *rule = node->data; fprintf(out, "(rangetransition "); fprintf(out, "%s ", datum_or_str(DATUM(rule->src), rule->src_str)); fprintf(out, "%s ", datum_or_str(DATUM(rule->exec), rule->exec_str)); fprintf(out, "%s ", datum_or_str(DATUM(rule->obj), rule->obj_str)); if (rule->range) write_range(out, rule->range, CIL_TRUE); else fprintf(out, "%s", rule->range_str); fprintf(out, ")\n"); break; } case CIL_CONSTRAIN: { struct cil_constrain *cons = node->data; fprintf(out, "(constrain "); write_constrain(out, cons); fprintf(out, ")\n"); break; } case CIL_MLSCONSTRAIN: { struct cil_constrain *cons = node->data; fprintf(out, "(mlsconstrain "); write_constrain(out, cons); fprintf(out, ")\n"); break; } case CIL_VALIDATETRANS: { struct cil_validatetrans *vt = node->data; fprintf(out, "(validatetrans "); fprintf(out, "%s ", datum_or_str(DATUM(vt->class), vt->class_str)); if (vt->datum_expr) write_expr(out, vt->datum_expr); else write_expr(out, vt->str_expr); fprintf(out, ")\n"); break; } case CIL_MLSVALIDATETRANS: { struct cil_validatetrans *vt = node->data; fprintf(out, "(mlsvalidatetrans "); fprintf(out, "%s ", datum_or_str(DATUM(vt->class), vt->class_str)); if (vt->datum_expr) write_expr(out, vt->datum_expr); else write_expr(out, vt->str_expr); fprintf(out, ")\n"); break; } case CIL_CONTEXT: { struct cil_context *context = node->data; fprintf(out, "(context %s ", datum_to_str(DATUM(context))); write_context(out, context, CIL_FALSE); fprintf(out, ")\n"); break; } case CIL_FILECON: { struct cil_filecon *filecon = node->data; fprintf(out, "(filecon "); if (filecon->path) { fprintf(out, "\"%s\" ", DATUM(filecon->path)->fqn); } else { fprintf(out, "%s ", filecon->path_str); } switch (filecon->type) { case CIL_FILECON_ANY: fprintf(out, "%s ", CIL_KEY_ANY); break; case CIL_FILECON_FILE: fprintf(out, "%s ", CIL_KEY_FILE); break; case CIL_FILECON_DIR: fprintf(out, "%s ", CIL_KEY_DIR); break; case CIL_FILECON_CHAR: fprintf(out, "%s ", CIL_KEY_CHAR); break; case CIL_FILECON_BLOCK: fprintf(out, "%s ", CIL_KEY_BLOCK); break; case CIL_FILECON_SOCKET: fprintf(out, "%s ", CIL_KEY_SOCKET); break; case CIL_FILECON_PIPE: fprintf(out, "%s ", CIL_KEY_PIPE); break; case CIL_FILECON_SYMLINK: fprintf(out, "%s ", CIL_KEY_SYMLINK); break; default: fprintf(out, " "); } if (filecon->context) write_context(out, filecon->context, CIL_TRUE); else if (filecon->context_str) fprintf(out, "%s", filecon->context_str); else fprintf(out, "()"); fprintf(out, ")\n"); break; } case CIL_IBPKEYCON: { struct cil_ibpkeycon *ibpkeycon = node->data; fprintf(out, "(ibpkeycon %s ", ibpkeycon->subnet_prefix_str); fprintf(out, "(%d %d) ", ibpkeycon->pkey_low, ibpkeycon->pkey_high); if (ibpkeycon->context) write_context(out, ibpkeycon->context, CIL_TRUE); else if (ibpkeycon->context_str) fprintf(out, "%s", ibpkeycon->context_str); fprintf(out, ")\n"); break; } case CIL_PORTCON: { struct cil_portcon *portcon = node->data; fprintf(out, "(portcon "); if (portcon->proto == CIL_PROTOCOL_UDP) fprintf(out, " udp "); else if (portcon->proto == CIL_PROTOCOL_TCP) fprintf(out, " tcp "); else if (portcon->proto == CIL_PROTOCOL_DCCP) fprintf(out, "dccp "); else if (portcon->proto == CIL_PROTOCOL_SCTP) fprintf(out, "sctp "); else fprintf(out, " "); if (portcon->port_low == portcon->port_high) fprintf(out, "%d ", portcon->port_low); else fprintf(out, "(%d %d) ", portcon->port_low, portcon->port_high); if (portcon->context) write_context(out, portcon->context, CIL_TRUE); else fprintf(out, "%s", portcon->context_str); fprintf(out, ")\n"); break; } case CIL_NODECON: { struct cil_nodecon *nodecon = node->data; fprintf(out, "(nodecon "); if (nodecon->addr) write_ipaddr(out, nodecon->addr); else fprintf(out, "%s ", nodecon->addr_str); fprintf(out, " "); if (nodecon->mask) write_ipaddr(out, nodecon->mask); else fprintf(out, "%s ", nodecon->mask_str); fprintf(out, " "); if (nodecon->context) write_context(out, nodecon->context, CIL_TRUE); else fprintf(out, "%s", nodecon->context_str); fprintf(out, ")\n"); break; } case CIL_GENFSCON: { struct cil_genfscon *genfscon = node->data; fprintf(out, "(genfscon "); fprintf(out, "%s \"%s\" ", genfscon->fs_str, genfscon->path_str); if (genfscon->file_type != CIL_FILECON_ANY) { switch (genfscon->file_type) { case CIL_FILECON_FILE: fprintf(out, "%s ", CIL_KEY_FILE); break; case CIL_FILECON_DIR: fprintf(out, "%s ", CIL_KEY_DIR); break; case CIL_FILECON_CHAR: fprintf(out, "%s ", CIL_KEY_CHAR); break; case CIL_FILECON_BLOCK: fprintf(out, "%s ", CIL_KEY_BLOCK); break; case CIL_FILECON_SOCKET: fprintf(out, "%s ", CIL_KEY_SOCKET); break; case CIL_FILECON_PIPE: fprintf(out, "%s ", CIL_KEY_PIPE); break; case CIL_FILECON_SYMLINK: fprintf(out, "%s ", CIL_KEY_SYMLINK); break; default: fprintf(out, " "); } } if (genfscon->context) write_context(out, genfscon->context, CIL_TRUE); else fprintf(out, "%s", genfscon->context_str); fprintf(out, ")\n"); break; } case CIL_NETIFCON: { struct cil_netifcon *netifcon = node->data; fprintf(out, "(netifcon %s ", netifcon->interface_str); if (netifcon->if_context) write_context(out, netifcon->if_context, CIL_TRUE); else fprintf(out, "%s", netifcon->if_context_str); fprintf(out, " "); if (netifcon->packet_context) write_context(out, netifcon->packet_context, CIL_TRUE); else fprintf(out, "%s", netifcon->packet_context_str); fprintf(out, ")\n"); break; } case CIL_IBENDPORTCON: { struct cil_ibendportcon *ibendportcon = node->data; fprintf(out, "(ibendportcon %s %u ", ibendportcon->dev_name_str, ibendportcon->port); if (ibendportcon->context) write_context(out, ibendportcon->context, CIL_TRUE); else fprintf(out, "%s", ibendportcon->context_str); fprintf(out, ")\n"); break; } case CIL_PIRQCON: { struct cil_pirqcon *pirqcon = node->data; fprintf(out, "(pirqcon %d ", pirqcon->pirq); if (pirqcon->context) write_context(out, pirqcon->context, CIL_TRUE); else fprintf(out, "%s", pirqcon->context_str); fprintf(out, ")\n"); break; } case CIL_IOMEMCON: { struct cil_iomemcon *iomemcon = node->data; fprintf(out, "(iomemcon (%"PRId64" %"PRId64") ", iomemcon->iomem_low, iomemcon->iomem_high); if (iomemcon->context) write_context(out, iomemcon->context, CIL_TRUE); else fprintf(out, "%s", iomemcon->context_str); fprintf(out, ")\n"); break; } case CIL_IOPORTCON: { struct cil_ioportcon *ioportcon = node->data; fprintf(out, "(ioportcon "); if (ioportcon->ioport_low == ioportcon->ioport_high) fprintf(out, "%d ", ioportcon->ioport_low); else fprintf(out, "(%d %d) ", ioportcon->ioport_low, ioportcon->ioport_high); if (ioportcon->context) write_context(out, ioportcon->context, CIL_TRUE); else fprintf(out, "%s", ioportcon->context_str); fprintf(out, ")\n"); break; } case CIL_PCIDEVICECON: { struct cil_pcidevicecon *pcidevicecon = node->data; fprintf(out, "(pcidevicecon %d ", pcidevicecon->dev); if (pcidevicecon->context) write_context(out, pcidevicecon->context, CIL_TRUE); else fprintf(out, "%s", pcidevicecon->context_str); fprintf(out, ")\n"); break; } case CIL_DEVICETREECON: { struct cil_devicetreecon *devicetreecon = node->data; fprintf(out, "(devicetreecon \"%s\" ", devicetreecon->path); if (devicetreecon->context) write_context(out, devicetreecon->context, CIL_TRUE); else fprintf(out, "%s", devicetreecon->context_str); fprintf(out, ")\n"); break; } case CIL_FSUSE: { struct cil_fsuse *fsuse = node->data; fprintf(out, "(fsuse "); if (fsuse->type == CIL_FSUSE_XATTR) fprintf(out, "xattr "); else if (fsuse->type == CIL_FSUSE_TASK) fprintf(out, "task "); else if (fsuse->type == CIL_FSUSE_TRANS) fprintf(out, "trans "); else fprintf(out, " "); fprintf(out, "%s ", fsuse->fs_str); if (fsuse->context) write_context(out, fsuse->context, CIL_TRUE); else fprintf(out, "%s", fsuse->context_str); fprintf(out, ")\n"); break; } case CIL_POLICYCAP: { struct cil_policycap *polcap = node->data; fprintf(out, "(policycap %s)\n", polcap->datum.name); break; } case CIL_IPADDR: { struct cil_ipaddr *ipaddr = node->data; char buf[256]; if (inet_ntop(ipaddr->family, &ipaddr->ip, buf, 256) == NULL) strcpy(buf, ""); fprintf(out, "(ipaddr %s %s)\n", datum_to_str(&ipaddr->datum), buf); break; } default : fprintf(out, "()\n", cil_node_to_string(node)); break; } } /* * Tree walk data and helper functions for writing the AST of the various phases */ struct cil_write_ast_args { FILE *out; int depth; }; /* * Helper functions for writing the parse AST */ static int __write_parse_ast_node_helper(struct cil_tree_node *node, __attribute__((unused)) uint32_t *finished, void *extra_args) { struct cil_write_ast_args *args = extra_args; fprintf(args->out, "%*s", args->depth*4, ""); if (!node->data) { if (node->cl_head) fprintf(args->out, "(\n"); else fprintf(args->out, "()\n"); } else { char *str = (char *)node->data; size_t len = strlen(str); size_t i; for (i = 0; i < len; i++) { if (isspace(str[i])) { fprintf(args->out, "\"%s\"\n", str); return SEPOL_OK; } } fprintf(args->out, "%s\n", (char *)node->data); } return SEPOL_OK; } static int __write_parse_ast_first_child_helper(struct cil_tree_node *node, void *extra_args) { struct cil_write_ast_args *args = extra_args; struct cil_tree_node *parent = node->parent; if (parent->flavor != CIL_ROOT) { args->depth++; } return SEPOL_OK; } static int __write_parse_ast_last_child_helper(struct cil_tree_node *node, void *extra_args) { struct cil_write_ast_args *args = extra_args; struct cil_tree_node *parent = node->parent; if (parent->flavor == CIL_ROOT) { return SEPOL_OK; } args->depth--; fprintf(args->out, "%*s", args->depth*4, ""); fprintf(args->out, ")\n"); return SEPOL_OK; } /* * Helper functions for writing the CIL AST for the build and resolve phases */ static int __write_cil_ast_node_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args) { struct cil_write_ast_args *args = extra_args; if (node->flavor == CIL_SRC_INFO) { cil_write_src_info_node(args->out, node); return SEPOL_OK; } fprintf(args->out, "%*s", args->depth*4, ""); cil_write_ast_node(args->out, node); if (node->flavor == CIL_CLASS || node->flavor == CIL_COMMON || node->flavor == CIL_MAP_CLASS) { *finished = CIL_TREE_SKIP_HEAD; } return SEPOL_OK; } static int __write_cil_ast_first_child_helper(struct cil_tree_node *node, void *extra_args) { struct cil_write_ast_args *args = extra_args; struct cil_tree_node *parent = node->parent; if (parent->flavor != CIL_SRC_INFO && parent->flavor != CIL_ROOT) { args->depth++; } return SEPOL_OK; } static int __write_cil_ast_last_child_helper(struct cil_tree_node *node, void *extra_args) { struct cil_write_ast_args *args = extra_args; struct cil_tree_node *parent = node->parent; if (parent->flavor == CIL_ROOT) { return SEPOL_OK; } else if (parent->flavor == CIL_SRC_INFO) { fprintf(args->out, ";;* lme\n"); return SEPOL_OK; } args->depth--; fprintf(args->out, "%*s", args->depth*4, ""); fprintf(args->out, ")\n"); return SEPOL_OK; } int cil_write_ast(FILE *out, enum cil_write_ast_phase phase, struct cil_tree_node *node) { struct cil_write_ast_args extra_args; int rc; extra_args.out = out; extra_args.depth = 0; if (phase == CIL_WRITE_AST_PHASE_PARSE) { rc = cil_tree_walk(node, __write_parse_ast_node_helper, __write_parse_ast_first_child_helper, __write_parse_ast_last_child_helper, &extra_args); } else { rc = cil_tree_walk(node, __write_cil_ast_node_helper, __write_cil_ast_first_child_helper, __write_cil_ast_last_child_helper, &extra_args); } if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Failed to write AST\n"); return SEPOL_ERR; } return SEPOL_OK; } libsepol-3.8.1/cil/src/cil_write_ast.h000066400000000000000000000037621476211737200177150ustar00rootroot00000000000000/* * 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_WRITE_AST_H_ #define CIL_WRITE_AST_H_ #include #include "cil_tree.h" enum cil_write_ast_phase { CIL_WRITE_AST_PHASE_PARSE = 0, CIL_WRITE_AST_PHASE_BUILD, CIL_WRITE_AST_PHASE_RESOLVE, CIL_WRITE_AST_PHASE_POST, }; void cil_write_ast_node(FILE *out, struct cil_tree_node *node); int cil_write_ast(FILE *out, enum cil_write_ast_phase phase, struct cil_tree_node *node); #endif /* CIL_WRITE_AST_H_ */ libsepol-3.8.1/cil/test/000077500000000000000000000000001476211737200150745ustar00rootroot00000000000000libsepol-3.8.1/cil/test/integration_testing/000077500000000000000000000000001476211737200211545ustar00rootroot00000000000000libsepol-3.8.1/cil/test/integration_testing/mls_policy.cil000066400000000000000000000047111476211737200240220ustar00rootroot00000000000000(class testing (read open close write exec)) (class fooclass (read open close write exec)) (category c0) (category c1) (category c2) (category c3) (category c4) (categoryalias c0 cat) (categoryorder (c0 c1 c2 c3 c4)) (categoryset catset (c0 c2 c3)) (sensitivity s0) (sensitivity s1) (sensitivity s2) (sensitivity s3) (sensitivityalias s3 sens) (dominance (s0 s1 s2 s3)) (sensitivitycategory s0 (c0 c2 c3)) (sensitivitycategory s0 (cat)) ; the following causes a segfault ;(sensitivitycategory sens (c2)) (type foo_t) (type typea_t) (type typeb_t) (type typec_t) (role foo_r) (role rolea_r) (role roleb_r) (user foo_u) (user user_u) (userrole foo_u foo_r) (level low (s0 catset)) (level high (s0 (c0))) (level test_l (s0 (cat))) (sid test_sid) (sidcontext test_sid (foo_u foo_r foo_t (s0 (c0)) (s0 (c0)))) (sid test_sid_anon_l) (sidcontext test_sid_anon_l (foo_u foo_r foo_t low high)) (context con (foo_u foo_r foo_t low high)) (context con_anon_l (foo_u foo_r foo_t (s0 (c0)) high)) (fsuse xattr ext3 con) (fsuse xattr ext3 con_anon_l) (netifcon eth0 con con_anon_l) (ipaddr ip_v4 192.25.35.200) (ipaddr netmask 192.168.1.1) (ipaddr ip_v6 2001:0DB8:AC10:FE01::) (ipaddr netmask_v6 2001:0DE0:DA88:2222::) ; will need anon levels (nodecon ip_v4 netmask con) (nodecon ip_v6 netmask_v6 con_anon_l) ;needs anon levels (portcon type 25 con) (filecon root path file con) (genfscon type path con) (netifcon eth0 con con_anon_l) (typemember typea_t typeb_t testing typec_t) (typechange typea_t typeb_t testing typec_t) (typetransition typea_t typeb_t testing typec_t) (permissionset permset (open close)) (allow typea_t typeb_t testing (write)) (allow typea_t typeb_t testing permset) (roleallow rolea_r roleb_r) (rolebounds rolea_r roleb_r) (roletransition foo_r foo_t testing rolea_r) (level l2 (s0 (c0))) (level h2 (s0 (c0))) (mlsconstrain (fooclass testing)(open close)(eq l2 h2)) (common fooclass (open)) (classcommon fooclass fooclass) (rangetransition typea_t typeb_t fooclass low high) (nametypetransition string typea_t typeb_t fooclass foo_t) (typepermissive foo_t) (typebounds typea_t typeb_t) (block test_b (typealias .test_b.test typea_t) (type test)) (attribute attrs) (attributetypes attrs (foo_t)) (roletype foo_r foo_t) (userbounds user_u foo_u) (userrole user_u foo_r) (bool foo_b true) (bool baz_b false) (booleanif (&& foo_b baz_b) (allow typea_t typeb_t fooclass(read))) ;(class baz (read)) ;(booleanif (&& foo_b baz_b) ; (allow foo_b baz_b fooclass (read))) libsepol-3.8.1/cil/test/integration_testing/nonmls.cil000066400000000000000000000032761476211737200231630ustar00rootroot00000000000000(class testing (read open close write exec)) (class fooclass (read open close write exec)) (type foo_t) (type typea_t) (type typeb_t) (type typec_t) (role foo_r) (role rolea_r) (role roleb_r) (user foo_u) (user user_u) (userrole foo_u foo_r) (sid test_sid) ;(sidcontext test_sid (foo_u foo_r foo_t (s0 (c0)) (s0 (c0)))) ;(sid test_sid_anon_l) ;(fsuse xattr ext3 con) ;(fsuse xattr ext3 con_anon_l) ;(netifcon eth0 con con_anon_l) (ipaddr ip_v4 192.25.35.200) (ipaddr netmask 192.168.1.1) (ipaddr ip_v6 2001:0DB8:AC10:FE01::) (ipaddr netmask_v6 2001:0DE0:DA88:2222::) ; will need anon levels ;(nodecon ip_v4 netmask con) ;(nodecon ip_v6 netmask_v6 con_anon_l) ;needs anon levels ;(portcon type 25 con) ;(filecon root path file con) ;(genfscon type path con) ;(netifcon eth0 con con_anon_l) (typemember typea_t typeb_t testing typec_t) (typechange typea_t typeb_t testing typec_t) (typetransition typea_t typeb_t testing typec_t) (permissionset permset (open close)) (allow typea_t typeb_t testing (write)) (allow typea_t typeb_t testing permset) (roleallow rolea_r roleb_r) (rolebounds rolea_r roleb_r) (roletransition foo_r foo_t testing rolea_r) (common fooclass (open)) (classcommon fooclass fooclass) (nametypetransition string typea_t typeb_t fooclass foo_t) (typepermissive foo_t) (typebounds typea_t typeb_t) (block test_b (typealias .test_b.test typea_t) (type test)) (attribute attrs) (attributetypes attrs (foo_t)) (roletype foo_r foo_t) (userbounds user_u foo_u) (userrole user_u foo_r) ;(bool foo_b true) ;(bool baz_b false) ;(booleanif (&& foo_b baz_b) ; (allow typea_t typeb_t fooclass(read))) ;(class baz (read)) ;(booleanif (&& foo_b baz_b) ; (allow foo_b baz_b fooclass (read))) libsepol-3.8.1/cil/test/integration_testing/nonmls.conf000066400000000000000000000013701476211737200233320ustar00rootroot00000000000000 class testing class fooclass sid test_sid #end #sid decl sid security class testing { read open close write exec } class fooclass { read open close write exec } #end #attribs attribute attrs; #end type foo_t, attrs; type typea_t; type typeb_t; type typec_t; #end bool foo_b true; bool baz_b false; #end role foo_r types foo_t; role rolea_r; role roleb_r; #end #role decl allow typea_t typeb_t : testing write; allow typea_t typeb_t : testing {open close}; type_transition typea_t typeb_t : testing typec_t; #end #audit rules #dontaudit {kernel} unknown : dir search; allow rolea_r roleb_r; #end #rbac stuff #allow system {guest local_user}; #allow local_user guest; user foo_u roles foo_r; #end sid test_sid foo_u:foo_r:foo_t libsepol-3.8.1/cil/test/integration_testing/ordered_lists_bad1.cil000066400000000000000000000013051476211737200253750ustar00rootroot00000000000000; Minimum policy ; **************************** (class foo (read)) (type bar) (allow bar self (foo (read))) ; **************************** (sensitivity s0) (sensitivity s1) (sensitivity s2) (sensitivity s3) (sensitivity s4) (sensitivity s5) (sensitivity s6) (sensitivity s7) (sensitivity s8) (sensitivity s9) (dominance (s2 s3 s4)) (dominance (s1 s2 s4 s5)) (dominance (s5 s6 s8)) (dominance (s6 s7 s8 s9)) (category c0) (category c1) (category c2) (category c3) (category c4) (category c5) (category c6) (category c7) (category c8) (category c9) (categoryorder (c1 c3)) (categoryorder (c1 c2 c3)) (categoryorder (c5 c6 c7)) (categoryorder (c3 c4 c5)) (categoryorder (c7 c8 c9)) (categoryorder (c0 c1)) libsepol-3.8.1/cil/test/integration_testing/ordered_lists_bad2.cil000066400000000000000000000013021476211737200253730ustar00rootroot00000000000000; Minimum policy ; **************************** (class foo (read)) (type bar) (allow bar self (foo (read))) ; **************************** (sensitivity s0) (sensitivity s1) (sensitivity s2) (sensitivity s3) (sensitivity s4) (sensitivity s5) (sensitivity s6) (sensitivity s7) (sensitivity s8) (sensitivity s9) (dominance (s2 s3 s4)) (dominance (s1 s2 s4 s5)) (dominance (s5 s6 s8)) (dominance (s6 s7 s8 s9)) (dominance (s0 s1)) (category c0) (category c1) (category c2) (category c3) (category c4) (category c5) (category c6) (category c7) (category c8) (category c9) (categoryorder (c1 c3)) (categoryorder (c1 c2 c3)) (categoryorder (c5 c6 c7)) (categoryorder (c3 c4 c5)) (categoryorder (c7 c8 c9)) libsepol-3.8.1/cil/test/integration_testing/ordered_lists_bad3.cil000066400000000000000000000013261476211737200254020ustar00rootroot00000000000000; Minimum policy ; **************************** (class foo (read)) (type bar) (allow bar self (foo (read))) ; **************************** (sensitivity s0) (sensitivity s1) (sensitivity s2) (sensitivity s3) (sensitivity s4) (sensitivity s5) (sensitivity s6) (sensitivity s7) (sensitivity s8) (sensitivity s9) (dominance (s2 s3 s4)) (dominance (s1 s2 s5)) (dominance (s5 s6 s8)) (dominance (s6 s7 s8 s9)) (dominance (s0 s1)) (category c0) (category c1) (category c2) (category c3) (category c4) (category c5) (category c6) (category c7) (category c8) (category c9) (categoryorder (c1 c3)) (categoryorder (c1 c2 c3)) (categoryorder (c5 c6 c7)) (categoryorder (c3 c4 c5)) (categoryorder (c7 c8 c9)) (categoryorder (c0 c1)) libsepol-3.8.1/cil/test/integration_testing/ordered_lists_easy.cil000066400000000000000000000011461476211737200255320ustar00rootroot00000000000000; Minimum policy ; **************************** (class foo (read)) (type bar) (allow bar self (foo (read))) ; **************************** (sensitivity s0) (sensitivity s1) (sensitivity s2) (sensitivity s3) (sensitivity s4) (sensitivity s5) (sensitivity s6) (sensitivity s7) (sensitivity s8) (sensitivity s9) (dominance (s0 s1 s2 s3 s4 s5 s6 s7 s8 s9)) (category c0) (category c1) (category c2) (category c3) (category c4) (category c5) (category c6) (category c7) (category c8) (category c9) (categoryorder (c2 c3 c4 c5)) (categoryorder (c0 c1 c2 c3)) (categoryorder (c5 c6 c7)) (categoryorder (c7 c8 c9)) libsepol-3.8.1/cil/test/integration_testing/ordered_lists_hard.cil000066400000000000000000000013311476211737200255030ustar00rootroot00000000000000; Minimum policy ; **************************** (class foo (read)) (type bar) (allow bar self (foo (read))) ; **************************** (sensitivity s0) (sensitivity s1) (sensitivity s2) (sensitivity s3) (sensitivity s4) (sensitivity s5) (sensitivity s6) (sensitivity s7) (sensitivity s8) (sensitivity s9) (dominance (s2 s3 s4)) (dominance (s1 s2 s4 s5)) (dominance (s5 s6 s8)) (dominance (s6 s7 s8 s9)) (dominance (s0 s1)) (category c0) (category c1) (category c2) (category c3) (category c4) (category c5) (category c6) (category c7) (category c8) (category c9) (categoryorder (c1 c3)) (categoryorder (c1 c2 c3)) (categoryorder (c5 c6 c7)) (categoryorder (c3 c4 c5)) (categoryorder (c7 c8 c9)) (categoryorder (c0 c1)) libsepol-3.8.1/cil/test/integration_testing/small.cil000066400000000000000000000000761476211737200227600ustar00rootroot00000000000000(class foo (read)) (type bar) (allow bar self (foo (read))) libsepol-3.8.1/cil/test/unit/000077500000000000000000000000001476211737200160535ustar00rootroot00000000000000libsepol-3.8.1/cil/test/unit/AllTests.c000066400000000000000000000055731476211737200177640ustar00rootroot00000000000000/* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #include #include "CuTest.h" #include "../../src/cil_log.h" CuSuite* CilTreeGetSuite(void); CuSuite* CilTreeGetResolveSuite(void); CuSuite* CilTreeGetBuildSuite(void); CuSuite* CilTestFullCil(void); void RunAllTests(void) { /* disable cil log output */ cil_set_log_level(0); CuString *output = CuStringNew(); CuSuite* suite = CuSuiteNew(); CuSuite* suiteResolve = CuSuiteNew(); CuSuite* suiteBuild = CuSuiteNew(); CuSuite* suiteIntegration = CuSuiteNew(); CuSuiteAddSuite(suite, CilTreeGetSuite()); CuSuiteAddSuite(suiteResolve, CilTreeGetResolveSuite()); CuSuiteAddSuite(suiteBuild, CilTreeGetBuildSuite()); CuSuiteAddSuite(suiteIntegration, CilTestFullCil()); CuSuiteRun(suite); CuSuiteDetails(suite, output); CuSuiteSummary(suite, output); CuSuiteRun(suiteResolve); CuSuiteDetails(suiteResolve, output); CuSuiteSummary(suiteResolve, output); CuSuiteRun(suiteBuild); CuSuiteDetails(suiteBuild, output); CuSuiteSummary(suiteBuild, output); CuSuiteRun(suiteIntegration); CuSuiteDetails(suiteIntegration, output); CuSuiteSummary(suiteIntegration, output); printf("\n%s\n", output->buffer); } int main(__attribute__((unused)) int argc, __attribute__((unused)) char *argv[]) { RunAllTests(); return 0; } libsepol-3.8.1/cil/test/unit/CilTest.c000066400000000000000000003150531476211737200175750ustar00rootroot00000000000000/* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #include #include #include #include #include #include #include "CuTest.h" #include "CilTest.h" #include "../../src/cil_internal.h" #include "test_cil.h" #include "test_cil_tree.h" #include "test_cil_list.h" #include "test_cil_symtab.h" #include "test_cil_parser.h" #include "test_cil_lexer.h" #include "test_cil_build_ast.h" #include "test_cil_resolve_ast.h" #include "test_cil_fqn.h" #include "test_cil_copy_ast.h" #include "test_cil_post.h" #include "test_integration.h" void set_cil_file_data(struct cil_file_data **data) { struct cil_file_data *new_data = malloc(sizeof(*new_data)); FILE *file; struct stat filedata; uint32_t file_size; char *buffer; file = fopen("test/policy.cil", "r"); if (!file) { fprintf(stderr, "Could not open file\n"); exit(1); } if (stat("test/policy.cil", &filedata) == -1) { printf("Could not stat file\n"); exit(1); } file_size = filedata.st_size; buffer = malloc(file_size + 2); if(fread(buffer, file_size, 1, file) < 1) { exit(1); } memset(buffer+file_size, 0, 2); fclose(file); new_data->buffer = buffer; new_data->file_size = file_size; *data = new_data; } void gen_test_tree(struct cil_tree **test_root, char *line[]) { struct cil_tree *new_tree = malloc(sizeof(*new_tree)); struct cil_tree_node *node, *item, *current; cil_tree_init(&new_tree); new_tree->root->flavor = CIL_ROOT; current = new_tree->root; char **i = line; do { if (*i[0] == '(') { cil_tree_node_init(&node); node->parent = current; node->flavor = CIL_PARSE_NODE; node->line = 0; if (current->cl_head == NULL) current->cl_head = node; else current->cl_tail->next = node; current->cl_tail = node; current = node; } else if (*i[0] == ')') current = current->parent; else { cil_tree_node_init(&item); item->parent = current; item->data = cil_strdup(*i); item->flavor = CIL_PARSE_NODE; item->line = 0; if (current->cl_head == NULL) { current->cl_head = item; } else { current->cl_tail->next = item; } current->cl_tail = item; } i++; } while(*i != NULL); *test_root = new_tree; } void test_symtab_init(CuTest *tc) { struct cil_db *test_new_db; test_new_db = malloc(sizeof(*test_new_db)); uint32_t rc = 0, i =0; for (i = 0; i < CIL_SYM_NUM; i++) { rc = symtab_init(&test_new_db->symtab[i], cil_sym_sizes[CIL_SYM_ARRAY_ROOT][i]); CuAssertIntEquals(tc, 0, rc); // TODO CDS add checks to make sure the symtab looks correct } free(test_new_db); } void test_symtab_init_no_table_neg(CuTest *tc) { struct cil_db *test_new_db; test_new_db = malloc(sizeof(*test_new_db)); int rc = symtab_init(&test_new_db->symtab[0], (uint32_t)SIZE_MAX); CuAssertIntEquals(tc, -1, rc); free(test_new_db); } CuSuite* CilTreeGetResolveSuite(void) { CuSuite* suite = CuSuiteNew(); /* test_cil_resolve_ast.c */ SUITE_ADD_TEST(suite, test_cil_resolve_ast_curr_null_neg); SUITE_ADD_TEST(suite, test_cil_gen_perm_nodes_inval_perm_neg); SUITE_ADD_TEST(suite, test_cil_resolve_name); SUITE_ADD_TEST(suite, test_cil_resolve_name_invalid_type_neg); SUITE_ADD_TEST(suite, test_cil_resolve_typeattributeset_type_in_multiple_attrs); SUITE_ADD_TEST(suite, test_cil_resolve_typeattributeset_multiple_excludes_with_not); SUITE_ADD_TEST(suite, test_cil_resolve_typeattributeset_multiple_types_with_and); SUITE_ADD_TEST(suite, test_cil_resolve_typeattributeset_using_attr); SUITE_ADD_TEST(suite, test_cil_resolve_typeattributeset_name_neg); SUITE_ADD_TEST(suite, test_cil_resolve_typeattributeset_undef_type_neg); SUITE_ADD_TEST(suite, test_cil_resolve_typeattributeset_not); SUITE_ADD_TEST(suite, test_cil_resolve_typeattributeset_undef_type_not_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_typeattributeset); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_typeattributeset_undef_type_neg); SUITE_ADD_TEST(suite, test_cil_resolve_typealias); SUITE_ADD_TEST(suite, test_cil_resolve_typealias_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_typealias); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_typealias_notype_neg); SUITE_ADD_TEST(suite, test_cil_resolve_typebounds); SUITE_ADD_TEST(suite, test_cil_resolve_typebounds_repeatbind_neg); SUITE_ADD_TEST(suite, test_cil_resolve_typebounds_type1_neg); SUITE_ADD_TEST(suite, test_cil_resolve_typebounds_type2_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_typebounds); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_typebounds_neg); SUITE_ADD_TEST(suite, test_cil_resolve_typepermissive); SUITE_ADD_TEST(suite, test_cil_resolve_typepermissive_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_typepermissive); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_typepermissive_neg); SUITE_ADD_TEST(suite, test_cil_resolve_nametypetransition); SUITE_ADD_TEST(suite, test_cil_resolve_nametypetransition_src_neg); SUITE_ADD_TEST(suite, test_cil_resolve_nametypetransition_tgt_neg); SUITE_ADD_TEST(suite, test_cil_resolve_nametypetransition_class_neg); SUITE_ADD_TEST(suite, test_cil_resolve_nametypetransition_dest_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_nametypetransition); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_nametypetransition_neg); SUITE_ADD_TEST(suite, test_cil_resolve_rangetransition); SUITE_ADD_TEST(suite, test_cil_resolve_rangetransition_namedrange); SUITE_ADD_TEST(suite, test_cil_resolve_rangetransition_namedrange_anon); SUITE_ADD_TEST(suite, test_cil_resolve_rangetransition_namedrange_anon_neg); SUITE_ADD_TEST(suite, test_cil_resolve_rangetransition_namedrange_neg); SUITE_ADD_TEST(suite, test_cil_resolve_rangetransition_type1_neg); SUITE_ADD_TEST(suite, test_cil_resolve_rangetransition_type2_neg); SUITE_ADD_TEST(suite, test_cil_resolve_rangetransition_class_neg); SUITE_ADD_TEST(suite, test_cil_resolve_rangetransition_call_level_l_anon); SUITE_ADD_TEST(suite, test_cil_resolve_rangetransition_call_level_l_anon_neg); SUITE_ADD_TEST(suite, test_cil_resolve_rangetransition_call_level_h_anon); SUITE_ADD_TEST(suite, test_cil_resolve_rangetransition_call_level_h_anon_neg); SUITE_ADD_TEST(suite, test_cil_resolve_rangetransition_level_l_neg); SUITE_ADD_TEST(suite, test_cil_resolve_rangetransition_level_h_neg); SUITE_ADD_TEST(suite, test_cil_resolve_rangetransition_anon_level_l); SUITE_ADD_TEST(suite, test_cil_resolve_rangetransition_anon_level_l_neg); SUITE_ADD_TEST(suite, test_cil_resolve_rangetransition_anon_level_h); SUITE_ADD_TEST(suite, test_cil_resolve_rangetransition_anon_level_h_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_rangetransition); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_rangetransition_neg); SUITE_ADD_TEST(suite, test_cil_resolve_classcommon); SUITE_ADD_TEST(suite, test_cil_resolve_classcommon_no_class_neg); SUITE_ADD_TEST(suite, test_cil_resolve_classcommon_no_common_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_classcommon); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_classcommon_neg); SUITE_ADD_TEST(suite, test_cil_resolve_classmapping_named); SUITE_ADD_TEST(suite, test_cil_resolve_classmapping_anon); SUITE_ADD_TEST(suite, test_cil_resolve_classmapping_anon_inmacro); SUITE_ADD_TEST(suite, test_cil_resolve_classmapping_anon_inmacro_neg); SUITE_ADD_TEST(suite, test_cil_resolve_classmapping_named_classmapname_neg); SUITE_ADD_TEST(suite, test_cil_resolve_classmapping_anon_classmapname_neg); SUITE_ADD_TEST(suite, test_cil_resolve_classmapping_anon_permset_neg); SUITE_ADD_TEST(suite, test_cil_resolve_rolebounds); SUITE_ADD_TEST(suite, test_cil_resolve_rolebounds_exists_neg); SUITE_ADD_TEST(suite, test_cil_resolve_rolebounds_role1_neg); SUITE_ADD_TEST(suite, test_cil_resolve_rolebounds_role2_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_rolebounds); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_rolebounds_neg); SUITE_ADD_TEST(suite, test_cil_resolve_sensalias); SUITE_ADD_TEST(suite, test_cil_resolve_sensalias_sensdecl_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_sensalias); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_sensalias_neg); SUITE_ADD_TEST(suite, test_cil_resolve_catalias); SUITE_ADD_TEST(suite, test_cil_resolve_catalias_catdecl_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_catalias); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_catalias_neg); SUITE_ADD_TEST(suite, test_cil_resolve_catorder); SUITE_ADD_TEST(suite, test_cil_resolve_catorder_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_catorder); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_catorder_neg); SUITE_ADD_TEST(suite, test_cil_resolve_dominance); SUITE_ADD_TEST(suite, test_cil_resolve_dominance_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_dominance); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_dominance_neg); //TODO: test for __cil_set_order SUITE_ADD_TEST(suite, test_cil_resolve_catset); SUITE_ADD_TEST(suite, test_cil_resolve_catset_catlist_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_catset); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_catset_catlist_neg); SUITE_ADD_TEST(suite, test_cil_resolve_catrange); SUITE_ADD_TEST(suite, test_cil_resolve_catrange_catloworder_neg); SUITE_ADD_TEST(suite, test_cil_resolve_catrange_cathighorder_neg); SUITE_ADD_TEST(suite, test_cil_resolve_catrange_cat1_neg); SUITE_ADD_TEST(suite, test_cil_resolve_catrange_cat2_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_catrange); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_catrange_neg); SUITE_ADD_TEST(suite, test_cil_resolve_senscat); SUITE_ADD_TEST(suite, test_cil_resolve_senscat_catrange_neg); SUITE_ADD_TEST(suite, test_cil_resolve_senscat_catsetname); SUITE_ADD_TEST(suite, test_cil_resolve_senscat_catsetname_neg); SUITE_ADD_TEST(suite, test_cil_resolve_senscat_sublist); SUITE_ADD_TEST(suite, test_cil_resolve_senscat_missingsens_neg); SUITE_ADD_TEST(suite, test_cil_resolve_senscat_category_neg); SUITE_ADD_TEST(suite, test_cil_resolve_senscat_currrangecat); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_senscat); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_senscat_neg); SUITE_ADD_TEST(suite, test_cil_resolve_level); SUITE_ADD_TEST(suite, test_cil_resolve_level_catlist); SUITE_ADD_TEST(suite, test_cil_resolve_level_catset); SUITE_ADD_TEST(suite, test_cil_resolve_level_catset_name_neg); SUITE_ADD_TEST(suite, test_cil_resolve_level_sens_neg); SUITE_ADD_TEST(suite, test_cil_resolve_level_cat_neg); SUITE_ADD_TEST(suite, test_cil_resolve_level_senscat_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_level); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_level_neg); SUITE_ADD_TEST(suite, test_cil_resolve_levelrange_namedlvl); SUITE_ADD_TEST(suite, test_cil_resolve_levelrange_namedlvl_low_neg); SUITE_ADD_TEST(suite, test_cil_resolve_levelrange_namedlvl_high_neg); SUITE_ADD_TEST(suite, test_cil_resolve_levelrange_anonlvl); SUITE_ADD_TEST(suite, test_cil_resolve_levelrange_anonlvl_low_neg); SUITE_ADD_TEST(suite, test_cil_resolve_levelrange_anonlvl_high_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_levelrange); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_levelrange_neg); SUITE_ADD_TEST(suite, test_cil_resolve_constrain); SUITE_ADD_TEST(suite, test_cil_resolve_constrain_class_neg); SUITE_ADD_TEST(suite, test_cil_resolve_constrain_perm_neg); SUITE_ADD_TEST(suite, test_cil_resolve_constrain_perm_resolve_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_constrain); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_constrain_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_mlsconstrain); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_mlsconstrain_neg); SUITE_ADD_TEST(suite, test_cil_resolve_context); SUITE_ADD_TEST(suite, test_cil_resolve_context_macro); SUITE_ADD_TEST(suite, test_cil_resolve_context_macro_neg); SUITE_ADD_TEST(suite, test_cil_resolve_context_namedrange); SUITE_ADD_TEST(suite, test_cil_resolve_context_namedrange_neg); SUITE_ADD_TEST(suite, test_cil_resolve_context_user_neg); SUITE_ADD_TEST(suite, test_cil_resolve_context_role_neg); SUITE_ADD_TEST(suite, test_cil_resolve_context_type_neg); SUITE_ADD_TEST(suite, test_cil_resolve_context_anon_level_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_context); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_context_neg); SUITE_ADD_TEST(suite, test_cil_resolve_roletransition); SUITE_ADD_TEST(suite, test_cil_resolve_roletransition_srcdecl_neg); SUITE_ADD_TEST(suite, test_cil_resolve_roletransition_tgtdecl_neg); SUITE_ADD_TEST(suite, test_cil_resolve_roletransition_resultdecl_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_roletransition); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_roletransition_srcdecl_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_roletransition_tgtdecl_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_roletransition_resultdecl_neg); SUITE_ADD_TEST(suite, test_cil_resolve_roleallow); SUITE_ADD_TEST(suite, test_cil_resolve_roleallow_srcdecl_neg); SUITE_ADD_TEST(suite, test_cil_resolve_roleallow_tgtdecl_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_roleallow); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_roleallow_neg); SUITE_ADD_TEST(suite, test_cil_resolve_classpermset_named); SUITE_ADD_TEST(suite, test_cil_resolve_classpermset_named_namedpermlist); SUITE_ADD_TEST(suite, test_cil_resolve_classpermset_named_permlist_neg); SUITE_ADD_TEST(suite, test_cil_resolve_classpermset_named_unnamedcps_neg); SUITE_ADD_TEST(suite, test_cil_resolve_classpermset_anon); SUITE_ADD_TEST(suite, test_cil_resolve_classpermset_anon_namedpermlist); SUITE_ADD_TEST(suite, test_cil_resolve_classpermset_anon_permlist_neg); SUITE_ADD_TEST(suite, test_cil_resolve_avrule); SUITE_ADD_TEST(suite, test_cil_resolve_avrule_permset); SUITE_ADD_TEST(suite, test_cil_resolve_avrule_permset_neg); SUITE_ADD_TEST(suite, test_cil_resolve_avrule_permset_permdne_neg); SUITE_ADD_TEST(suite, test_cil_resolve_avrule_firsttype_neg); SUITE_ADD_TEST(suite, test_cil_resolve_avrule_secondtype_neg); SUITE_ADD_TEST(suite, test_cil_resolve_avrule_class_neg); SUITE_ADD_TEST(suite, test_cil_resolve_avrule_perm_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_avrule); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_avrule_src_nores_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_avrule_tgt_nores_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_avrule_class_nores_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_avrule_datum_null_neg); SUITE_ADD_TEST(suite, test_cil_resolve_type_rule_transition); SUITE_ADD_TEST(suite, test_cil_resolve_type_rule_transition_srcdecl_neg); SUITE_ADD_TEST(suite, test_cil_resolve_type_rule_transition_tgtdecl_neg); SUITE_ADD_TEST(suite, test_cil_resolve_type_rule_transition_objdecl_neg); SUITE_ADD_TEST(suite, test_cil_resolve_type_rule_transition_resultdecl_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_type_rule_transition); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_type_rule_transition_neg); SUITE_ADD_TEST(suite, test_cil_resolve_type_rule_change); SUITE_ADD_TEST(suite, test_cil_resolve_type_rule_change_srcdecl_neg); SUITE_ADD_TEST(suite, test_cil_resolve_type_rule_change_tgtdecl_neg); SUITE_ADD_TEST(suite, test_cil_resolve_type_rule_change_objdecl_neg); SUITE_ADD_TEST(suite, test_cil_resolve_type_rule_change_resultdecl_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_type_rule_change); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_type_rule_change_neg); SUITE_ADD_TEST(suite, test_cil_resolve_type_rule_member); SUITE_ADD_TEST(suite, test_cil_resolve_type_rule_member_srcdecl_neg); SUITE_ADD_TEST(suite, test_cil_resolve_type_rule_member_tgtdecl_neg); SUITE_ADD_TEST(suite, test_cil_resolve_type_rule_member_objdecl_neg); SUITE_ADD_TEST(suite, test_cil_resolve_type_rule_member_resultdecl_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_type_rule_member); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_type_rule_member_neg); SUITE_ADD_TEST(suite, test_cil_resolve_filecon); SUITE_ADD_TEST(suite, test_cil_resolve_filecon_neg); SUITE_ADD_TEST(suite, test_cil_resolve_filecon_anon_context); SUITE_ADD_TEST(suite, test_cil_resolve_filecon_anon_context_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_filecon); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_filecon_neg); SUITE_ADD_TEST(suite, test_cil_resolve_portcon); SUITE_ADD_TEST(suite, test_cil_resolve_portcon_neg); SUITE_ADD_TEST(suite, test_cil_resolve_portcon_anon_context); SUITE_ADD_TEST(suite, test_cil_resolve_portcon_anon_context_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_portcon); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_portcon_neg); SUITE_ADD_TEST(suite, test_cil_resolve_genfscon); SUITE_ADD_TEST(suite, test_cil_resolve_genfscon_neg); SUITE_ADD_TEST(suite, test_cil_resolve_genfscon_anon_context); SUITE_ADD_TEST(suite, test_cil_resolve_genfscon_anon_context_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_genfscon); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_genfscon_neg); SUITE_ADD_TEST(suite, test_cil_resolve_nodecon_ipv4); SUITE_ADD_TEST(suite, test_cil_resolve_nodecon_ipv6); SUITE_ADD_TEST(suite, test_cil_resolve_nodecon_anonipaddr_ipv4); SUITE_ADD_TEST(suite, test_cil_resolve_nodecon_anonnetmask_ipv4); SUITE_ADD_TEST(suite, test_cil_resolve_nodecon_anonipaddr_ipv6); SUITE_ADD_TEST(suite, test_cil_resolve_nodecon_anonnetmask_ipv6); SUITE_ADD_TEST(suite, test_cil_resolve_nodecon_diffipfam_neg); SUITE_ADD_TEST(suite, test_cil_resolve_nodecon_context_neg); SUITE_ADD_TEST(suite, test_cil_resolve_nodecon_ipaddr_neg); SUITE_ADD_TEST(suite, test_cil_resolve_nodecon_netmask_neg); SUITE_ADD_TEST(suite, test_cil_resolve_nodecon_anon_context); SUITE_ADD_TEST(suite, test_cil_resolve_nodecon_anon_context_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_nodecon); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_nodecon_ipaddr_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_nodecon_netmask_neg); SUITE_ADD_TEST(suite, test_cil_resolve_netifcon); SUITE_ADD_TEST(suite, test_cil_resolve_netifcon_otf_neg); SUITE_ADD_TEST(suite, test_cil_resolve_netifcon_interface_neg); SUITE_ADD_TEST(suite, test_cil_resolve_netifcon_unnamed); SUITE_ADD_TEST(suite, test_cil_resolve_netifcon_unnamed_packet_neg); SUITE_ADD_TEST(suite, test_cil_resolve_netifcon_unnamed_otf_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_netifcon); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_netifcon_neg); SUITE_ADD_TEST(suite, test_cil_resolve_pirqcon); SUITE_ADD_TEST(suite, test_cil_resolve_pirqcon_context_neg); SUITE_ADD_TEST(suite, test_cil_resolve_pirqcon_anon_context); SUITE_ADD_TEST(suite, test_cil_resolve_pirqcon_anon_context_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_pirqcon); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_pirqcon_neg); SUITE_ADD_TEST(suite, test_cil_resolve_iomemcon); SUITE_ADD_TEST(suite, test_cil_resolve_iomemcon_context_neg); SUITE_ADD_TEST(suite, test_cil_resolve_iomemcon_anon_context); SUITE_ADD_TEST(suite, test_cil_resolve_iomemcon_anon_context_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_iomemcon); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_iomemcon_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ioportcon); SUITE_ADD_TEST(suite, test_cil_resolve_ioportcon_context_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ioportcon_anon_context); SUITE_ADD_TEST(suite, test_cil_resolve_ioportcon_anon_context_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_ioportcon); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_ioportcon_neg); SUITE_ADD_TEST(suite, test_cil_resolve_pcidevicecon); SUITE_ADD_TEST(suite, test_cil_resolve_pcidevicecon_context_neg); SUITE_ADD_TEST(suite, test_cil_resolve_pcidevicecon_anon_context); SUITE_ADD_TEST(suite, test_cil_resolve_pcidevicecon_anon_context_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_pcidevicecon); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_pcidevicecon_neg); SUITE_ADD_TEST(suite, test_cil_resolve_fsuse); SUITE_ADD_TEST(suite, test_cil_resolve_fsuse_neg); SUITE_ADD_TEST(suite, test_cil_resolve_fsuse_anon); SUITE_ADD_TEST(suite, test_cil_resolve_fsuse_anon_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_fsuse); //SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_fsuse_neg); SUITE_ADD_TEST(suite, test_cil_resolve_sidcontext); SUITE_ADD_TEST(suite, test_cil_resolve_sidcontext_named_levels); SUITE_ADD_TEST(suite, test_cil_resolve_sidcontext_named_context); SUITE_ADD_TEST(suite, test_cil_resolve_sidcontext_named_context_wrongname_neg); SUITE_ADD_TEST(suite, test_cil_resolve_sidcontext_named_context_invaliduser_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_sidcontext); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_sidcontext_neg); SUITE_ADD_TEST(suite, test_cil_resolve_blockinherit); SUITE_ADD_TEST(suite, test_cil_resolve_blockinherit_blockstrdne_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_blockinherit); SUITE_ADD_TEST(suite, test_cil_resolve_in_block); SUITE_ADD_TEST(suite, test_cil_resolve_in_blockstrdne_neg); SUITE_ADD_TEST(suite, test_cil_resolve_in_macro); SUITE_ADD_TEST(suite, test_cil_resolve_in_optional); //SUITE_ADD_TEST(suite, test_cil_resolve_call1_noparam); SUITE_ADD_TEST(suite, test_cil_resolve_call1_type); SUITE_ADD_TEST(suite, test_cil_resolve_call1_role); SUITE_ADD_TEST(suite, test_cil_resolve_call1_user); SUITE_ADD_TEST(suite, test_cil_resolve_call1_sens); SUITE_ADD_TEST(suite, test_cil_resolve_call1_cat); SUITE_ADD_TEST(suite, test_cil_resolve_call1_catset); SUITE_ADD_TEST(suite, test_cil_resolve_call1_catset_anon); SUITE_ADD_TEST(suite, test_cil_resolve_call1_catset_anon_neg); SUITE_ADD_TEST(suite, test_cil_resolve_call1_class); SUITE_ADD_TEST(suite, test_cil_resolve_call1_classmap); SUITE_ADD_TEST(suite, test_cil_resolve_call1_permset); SUITE_ADD_TEST(suite, test_cil_resolve_call1_permset_anon); SUITE_ADD_TEST(suite, test_cil_resolve_call1_classpermset_named); SUITE_ADD_TEST(suite, test_cil_resolve_call1_classpermset_anon); SUITE_ADD_TEST(suite, test_cil_resolve_call1_classpermset_anon_neg); SUITE_ADD_TEST(suite, test_cil_resolve_call1_level); SUITE_ADD_TEST(suite, test_cil_resolve_call1_level_anon); SUITE_ADD_TEST(suite, test_cil_resolve_call1_level_anon_neg); SUITE_ADD_TEST(suite, test_cil_resolve_call1_ipaddr); SUITE_ADD_TEST(suite, test_cil_resolve_call1_ipaddr_anon); SUITE_ADD_TEST(suite, test_cil_resolve_call1_ipaddr_anon_neg); SUITE_ADD_TEST(suite, test_cil_resolve_call1_unknown_neg); SUITE_ADD_TEST(suite, test_cil_resolve_call1_unknowncall_neg); SUITE_ADD_TEST(suite, test_cil_resolve_call1_extraargs_neg); SUITE_ADD_TEST(suite, test_cil_resolve_call1_copy_dup); SUITE_ADD_TEST(suite, test_cil_resolve_call1_missing_arg_neg); SUITE_ADD_TEST(suite, test_cil_resolve_call1_paramsflavor_neg); SUITE_ADD_TEST(suite, test_cil_resolve_call1_unknownflavor_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_call1); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_call1_neg); SUITE_ADD_TEST(suite, test_cil_resolve_call2_type); SUITE_ADD_TEST(suite, test_cil_resolve_call2_role); SUITE_ADD_TEST(suite, test_cil_resolve_call2_user); SUITE_ADD_TEST(suite, test_cil_resolve_call2_sens); SUITE_ADD_TEST(suite, test_cil_resolve_call2_cat); SUITE_ADD_TEST(suite, test_cil_resolve_call2_catset); SUITE_ADD_TEST(suite, test_cil_resolve_call2_catset_anon); SUITE_ADD_TEST(suite, test_cil_resolve_call2_permset); SUITE_ADD_TEST(suite, test_cil_resolve_call2_permset_anon); SUITE_ADD_TEST(suite, test_cil_resolve_call2_classpermset_named); SUITE_ADD_TEST(suite, test_cil_resolve_call2_classpermset_anon); SUITE_ADD_TEST(suite, test_cil_resolve_call2_class); SUITE_ADD_TEST(suite, test_cil_resolve_call2_classmap); SUITE_ADD_TEST(suite, test_cil_resolve_call2_level); SUITE_ADD_TEST(suite, test_cil_resolve_call2_level_anon); SUITE_ADD_TEST(suite, test_cil_resolve_call2_ipaddr); SUITE_ADD_TEST(suite, test_cil_resolve_call2_ipaddr_anon); SUITE_ADD_TEST(suite, test_cil_resolve_call2_unknown_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_call2); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_call2_neg); SUITE_ADD_TEST(suite, test_cil_resolve_name_call_args); SUITE_ADD_TEST(suite, test_cil_resolve_name_call_args_multipleparams); SUITE_ADD_TEST(suite, test_cil_resolve_name_call_args_diffflavor); SUITE_ADD_TEST(suite, test_cil_resolve_name_call_args_callnull_neg); SUITE_ADD_TEST(suite, test_cil_resolve_name_call_args_namenull_neg); //SUITE_ADD_TEST(suite, test_cil_resolve_name_call_args_callargsnull_neg); SUITE_ADD_TEST(suite, test_cil_resolve_name_call_args_name_neg); // SUITE_ADD_TEST(suite, test_cil_resolve_expr_stack_bools); // SUITE_ADD_TEST(suite, test_cil_resolve_expr_stack_tunables); // SUITE_ADD_TEST(suite, test_cil_resolve_expr_stack_type); // SUITE_ADD_TEST(suite, test_cil_resolve_expr_stack_role); // SUITE_ADD_TEST(suite, test_cil_resolve_expr_stack_user); // SUITE_ADD_TEST(suite, test_cil_resolve_expr_stack_neg); // SUITE_ADD_TEST(suite, test_cil_resolve_expr_stack_emptystr_neg); SUITE_ADD_TEST(suite, test_cil_resolve_boolif); SUITE_ADD_TEST(suite, test_cil_resolve_boolif_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_boolif); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_boolif_neg); SUITE_ADD_TEST(suite, test_cil_evaluate_expr_stack_and); SUITE_ADD_TEST(suite, test_cil_evaluate_expr_stack_not); SUITE_ADD_TEST(suite, test_cil_evaluate_expr_stack_or); SUITE_ADD_TEST(suite, test_cil_evaluate_expr_stack_xor); SUITE_ADD_TEST(suite, test_cil_evaluate_expr_stack_eq); SUITE_ADD_TEST(suite, test_cil_evaluate_expr_stack_neq); SUITE_ADD_TEST(suite, test_cil_evaluate_expr_stack_oper1); SUITE_ADD_TEST(suite, test_cil_evaluate_expr_stack_oper2); //SUITE_ADD_TEST(suite, test_cil_evaluate_expr_stack_neg); SUITE_ADD_TEST(suite, test_cil_resolve_tunif_false); SUITE_ADD_TEST(suite, test_cil_resolve_tunif_true); SUITE_ADD_TEST(suite, test_cil_resolve_tunif_resolveexpr_neg); //SUITE_ADD_TEST(suite, test_cil_resolve_tunif_evaluateexpr_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_tunif); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_tunif_neg); SUITE_ADD_TEST(suite, test_cil_resolve_userbounds); SUITE_ADD_TEST(suite, test_cil_resolve_userbounds_exists_neg); SUITE_ADD_TEST(suite, test_cil_resolve_userbounds_user1_neg); SUITE_ADD_TEST(suite, test_cil_resolve_userbounds_user2_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_userbounds); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_userbounds_neg); SUITE_ADD_TEST(suite, test_cil_resolve_roletype); SUITE_ADD_TEST(suite, test_cil_resolve_roletype_type_neg); SUITE_ADD_TEST(suite, test_cil_resolve_roletype_role_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_roletype); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_roletype_role_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_roletype_type_neg); SUITE_ADD_TEST(suite, test_cil_resolve_userrole); SUITE_ADD_TEST(suite, test_cil_resolve_userrole_user_neg); SUITE_ADD_TEST(suite, test_cil_resolve_userrole_role_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_userrole); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_userrole_user_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_userrole_role_neg); SUITE_ADD_TEST(suite, test_cil_resolve_userlevel); SUITE_ADD_TEST(suite, test_cil_resolve_userlevel_macro); SUITE_ADD_TEST(suite, test_cil_resolve_userlevel_macro_neg); SUITE_ADD_TEST(suite, test_cil_resolve_userlevel_level_anon); SUITE_ADD_TEST(suite, test_cil_resolve_userlevel_level_anon_neg); SUITE_ADD_TEST(suite, test_cil_resolve_userlevel_user_neg); SUITE_ADD_TEST(suite, test_cil_resolve_userlevel_level_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_userlevel); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_userlevel_neg); SUITE_ADD_TEST(suite, test_cil_resolve_userrange); SUITE_ADD_TEST(suite, test_cil_resolve_userrange_macro); SUITE_ADD_TEST(suite, test_cil_resolve_userrange_macro_neg); SUITE_ADD_TEST(suite, test_cil_resolve_userrange_range_anon); SUITE_ADD_TEST(suite, test_cil_resolve_userrange_range_anon_neg); SUITE_ADD_TEST(suite, test_cil_resolve_userrange_user_neg); SUITE_ADD_TEST(suite, test_cil_resolve_userrange_range_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_userrange); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_userrange_neg); SUITE_ADD_TEST(suite, test_cil_disable_children_helper_optional_enabled); SUITE_ADD_TEST(suite, test_cil_disable_children_helper_optional_disabled); SUITE_ADD_TEST(suite, test_cil_disable_children_helper_block); SUITE_ADD_TEST(suite, test_cil_disable_children_helper_user); SUITE_ADD_TEST(suite, test_cil_disable_children_helper_role); SUITE_ADD_TEST(suite, test_cil_disable_children_helper_type); SUITE_ADD_TEST(suite, test_cil_disable_children_helper_typealias); SUITE_ADD_TEST(suite, test_cil_disable_children_helper_common); SUITE_ADD_TEST(suite, test_cil_disable_children_helper_class); SUITE_ADD_TEST(suite, test_cil_disable_children_helper_bool); SUITE_ADD_TEST(suite, test_cil_disable_children_helper_sens); SUITE_ADD_TEST(suite, test_cil_disable_children_helper_cat); SUITE_ADD_TEST(suite, test_cil_disable_children_helper_catset); SUITE_ADD_TEST(suite, test_cil_disable_children_helper_sid); SUITE_ADD_TEST(suite, test_cil_disable_children_helper_macro); SUITE_ADD_TEST(suite, test_cil_disable_children_helper_context); SUITE_ADD_TEST(suite, test_cil_disable_children_helper_level); SUITE_ADD_TEST(suite, test_cil_disable_children_helper_policycap); SUITE_ADD_TEST(suite, test_cil_disable_children_helper_perm); SUITE_ADD_TEST(suite, test_cil_disable_children_helper_catalias); SUITE_ADD_TEST(suite, test_cil_disable_children_helper_sensalias); SUITE_ADD_TEST(suite, test_cil_disable_children_helper_tunable); SUITE_ADD_TEST(suite, test_cil_disable_children_helper_unknown); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_callstack); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_call); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_optional); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_macro); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_optstack); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_optstack_tunable_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_optstack_macro_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_nodenull_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_extraargsnull_neg); SUITE_ADD_TEST(suite, test_cil_resolve_ast_node_helper_optfailedtoresolve); return suite; } CuSuite* CilTreeGetBuildSuite(void) { CuSuite* suite = CuSuiteNew(); /* test_cil_build_ast.c */ SUITE_ADD_TEST(suite, test_cil_build_ast); SUITE_ADD_TEST(suite, test_cil_build_ast_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_astnull_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_treenull_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_suberr_neg); SUITE_ADD_TEST(suite, test_cil_parse_to_list); SUITE_ADD_TEST(suite, test_cil_parse_to_list_currnull_neg); SUITE_ADD_TEST(suite, test_cil_parse_to_list_listnull_neg); SUITE_ADD_TEST(suite, test_cil_set_to_list); SUITE_ADD_TEST(suite, test_cil_set_to_list_listnull_neg); SUITE_ADD_TEST(suite, test_cil_set_to_list_tree_node_null_neg); SUITE_ADD_TEST(suite, test_cil_set_to_list_cl_head_null_neg); SUITE_ADD_TEST(suite, test_cil_gen_block); SUITE_ADD_TEST(suite, test_cil_gen_block_justblock_neg); SUITE_ADD_TEST(suite, test_cil_gen_block_noname_neg); SUITE_ADD_TEST(suite, test_cil_gen_block_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_block_treenull_neg); SUITE_ADD_TEST(suite, test_cil_gen_block_nodenull_neg); SUITE_ADD_TEST(suite, test_cil_gen_block_nodeparentnull_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_block); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_block_neg); SUITE_ADD_TEST(suite, test_cil_gen_blockinherit); SUITE_ADD_TEST(suite, test_cil_gen_blockinherit_namelist_neg); SUITE_ADD_TEST(suite, test_cil_gen_blockinherit_namenull_neg); SUITE_ADD_TEST(suite, test_cil_gen_blockinherit_extra_neg); SUITE_ADD_TEST(suite, test_cil_gen_blockinherit_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_blockinherit_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_blockinherit_astnull_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_blockinherit); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_blockinherit_neg); SUITE_ADD_TEST(suite, test_cil_gen_perm); SUITE_ADD_TEST(suite, test_cil_gen_perm_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_perm_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_perm_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_perm_nodenull_neg); SUITE_ADD_TEST(suite, test_cil_gen_permset); SUITE_ADD_TEST(suite, test_cil_gen_permset_noname_neg); SUITE_ADD_TEST(suite, test_cil_gen_permset_nameinparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_permset_noperms_neg); SUITE_ADD_TEST(suite, test_cil_gen_permset_emptyperms_neg); SUITE_ADD_TEST(suite, test_cil_gen_permset_extra_neg); SUITE_ADD_TEST(suite, test_cil_gen_permset_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_permset_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_permset_astnull_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_permset); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_permset_neg); SUITE_ADD_TEST(suite, test_cil_gen_perm_nodes); SUITE_ADD_TEST(suite, test_cil_gen_perm_nodes_failgen_neg); SUITE_ADD_TEST(suite, test_cil_fill_permset); SUITE_ADD_TEST(suite, test_cil_fill_permset_sublist_neg); SUITE_ADD_TEST(suite, test_cil_fill_permset_startpermnull_neg); SUITE_ADD_TEST(suite, test_cil_fill_permset_permsetnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_in); SUITE_ADD_TEST(suite, test_cil_gen_in_blockstrnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_in_extra_neg); SUITE_ADD_TEST(suite, test_cil_gen_in_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_in_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_in_astnull_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_in); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_in_neg); SUITE_ADD_TEST(suite, test_cil_gen_class); SUITE_ADD_TEST(suite, test_cil_gen_class_noname_neg); SUITE_ADD_TEST(suite, test_cil_gen_class_nodenull_neg); SUITE_ADD_TEST(suite, test_cil_gen_class_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_class_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_class_noclassname_neg); SUITE_ADD_TEST(suite, test_cil_gen_class_namesublist_neg); SUITE_ADD_TEST(suite, test_cil_gen_class_noperms); SUITE_ADD_TEST(suite, test_cil_gen_class_permsnotinlist_neg); SUITE_ADD_TEST(suite, test_cil_gen_class_extrapermlist_neg); SUITE_ADD_TEST(suite, test_cil_gen_class_listinlist_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_class); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_class_neg); SUITE_ADD_TEST(suite, test_cil_fill_classpermset_anonperms); SUITE_ADD_TEST(suite, test_cil_fill_classpermset_anonperms_neg); SUITE_ADD_TEST(suite, test_cil_fill_classpermset_namedperms); SUITE_ADD_TEST(suite, test_cil_fill_classpermset_extra_neg); SUITE_ADD_TEST(suite, test_cil_fill_classpermset_emptypermslist_neg); SUITE_ADD_TEST(suite, test_cil_fill_classpermset_noperms_neg); SUITE_ADD_TEST(suite, test_cil_fill_classpermset_noclass_neg); SUITE_ADD_TEST(suite, test_cil_fill_classpermset_classnodenull_neg); SUITE_ADD_TEST(suite, test_cil_fill_classpermset_cpsnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_classpermset); SUITE_ADD_TEST(suite, test_cil_gen_classpermset_noname_neg); SUITE_ADD_TEST(suite, test_cil_gen_classpermset_nameinparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_classpermset_noclass_neg); SUITE_ADD_TEST(suite, test_cil_gen_classpermset_noperms_neg); SUITE_ADD_TEST(suite, test_cil_gen_classpermset_emptyperms_neg); SUITE_ADD_TEST(suite, test_cil_gen_classpermset_extra_neg); SUITE_ADD_TEST(suite, test_cil_gen_classpermset_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_classpermset_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_classpermset_astnull_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_classpermset); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_classpermset_neg); SUITE_ADD_TEST(suite, test_cil_gen_classmap_perm); SUITE_ADD_TEST(suite, test_cil_gen_classmap_perm_dupeperm_neg); SUITE_ADD_TEST(suite, test_cil_gen_classmap_perm_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_classmap_perm_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_classmap_perm_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_classmap); SUITE_ADD_TEST(suite, test_cil_gen_classmap_extra_neg); SUITE_ADD_TEST(suite, test_cil_gen_classmap_noname_neg); SUITE_ADD_TEST(suite, test_cil_gen_classmap_emptyperms_neg); SUITE_ADD_TEST(suite, test_cil_gen_classmap_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_classmap_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_classmap_astnull_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_classmap); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_classmap_neg); SUITE_ADD_TEST(suite, test_cil_gen_classmapping_anonpermset); SUITE_ADD_TEST(suite, test_cil_gen_classmapping_anonpermset_neg); SUITE_ADD_TEST(suite, test_cil_gen_classmapping_namedpermset); SUITE_ADD_TEST(suite, test_cil_gen_classmapping_noclassmapname_neg); SUITE_ADD_TEST(suite, test_cil_gen_classmapping_noclassmapperm_neg); SUITE_ADD_TEST(suite, test_cil_gen_classmapping_nopermissionsets_neg); SUITE_ADD_TEST(suite, test_cil_gen_classmapping_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_classmapping_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_classmapping_astnull_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_classmapping); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_classmapping_neg); SUITE_ADD_TEST(suite, test_cil_gen_common); SUITE_ADD_TEST(suite, test_cil_gen_common_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_common_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_common_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_common_noname_neg); SUITE_ADD_TEST(suite, test_cil_gen_common_twoperms_neg); SUITE_ADD_TEST(suite, test_cil_gen_common_permsublist_neg); SUITE_ADD_TEST(suite, test_cil_gen_common_noperms_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_common); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_common_neg); SUITE_ADD_TEST(suite, test_cil_gen_sid); SUITE_ADD_TEST(suite, test_cil_gen_sid_noname_neg); SUITE_ADD_TEST(suite, test_cil_gen_sid_nameinparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_sid_extra_neg); SUITE_ADD_TEST(suite, test_cil_gen_sid_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_sid_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_sid_astnull_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_sid); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_sid_neg); SUITE_ADD_TEST(suite, test_cil_gen_sidcontext); SUITE_ADD_TEST(suite, test_cil_gen_sidcontext_namedcontext); // SUITE_ADD_TEST(suite, test_cil_gen_sidcontext_halfcontext_neg); SUITE_ADD_TEST(suite, test_cil_gen_sidcontext_noname_neg); SUITE_ADD_TEST(suite, test_cil_gen_sidcontext_empty_neg); SUITE_ADD_TEST(suite, test_cil_gen_sidcontext_nocontext_neg); SUITE_ADD_TEST(suite, test_cil_gen_sidcontext_dblname_neg); SUITE_ADD_TEST(suite, test_cil_gen_sidcontext_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_sidcontext_pcurrnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_sidcontext_astnodenull_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_sidcontext); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_sidcontext_neg); SUITE_ADD_TEST(suite, test_cil_gen_type); SUITE_ADD_TEST(suite, test_cil_gen_type_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_type_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_type_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_type_extra_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_type); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_type_neg); SUITE_ADD_TEST(suite, test_cil_gen_typeattribute); SUITE_ADD_TEST(suite, test_cil_gen_typeattribute_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_typeattribute_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_typeattribute_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_typeattribute_extra_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_typeattribute); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_typeattribute_neg); SUITE_ADD_TEST(suite, test_cil_gen_typebounds); SUITE_ADD_TEST(suite, test_cil_gen_typebounds_notype1_neg); SUITE_ADD_TEST(suite, test_cil_gen_typebounds_type1inparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_typebounds_notype2_neg); SUITE_ADD_TEST(suite, test_cil_gen_typebounds_type2inparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_typebounds_extra_neg); SUITE_ADD_TEST(suite, test_cil_gen_typebounds_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_typebounds_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_typebounds_astnull_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_typebounds); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_typebounds_neg); SUITE_ADD_TEST(suite, test_cil_gen_typepermissive); SUITE_ADD_TEST(suite, test_cil_gen_typepermissive_noname_neg); SUITE_ADD_TEST(suite, test_cil_gen_typepermissive_typeinparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_typepermissive_extra_neg); SUITE_ADD_TEST(suite, test_cil_gen_typepermissive_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_typepermissive_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_typepermissive_astnull_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_typepermissive); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_typepermissive_neg); SUITE_ADD_TEST(suite, test_cil_gen_nametypetransition); SUITE_ADD_TEST(suite, test_cil_gen_nametypetransition_nostr_neg); SUITE_ADD_TEST(suite, test_cil_gen_nametypetransition_strinparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_nametypetransition_nosrc_neg); SUITE_ADD_TEST(suite, test_cil_gen_nametypetransition_srcinparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_nametypetransition_notgt_neg); SUITE_ADD_TEST(suite, test_cil_gen_nametypetransition_tgtinparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_nametypetransition_noclass_neg); SUITE_ADD_TEST(suite, test_cil_gen_nametypetransition_classinparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_nametypetransition_nodest_neg); SUITE_ADD_TEST(suite, test_cil_gen_nametypetransition_destinparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_nametypetransition_extra_neg); SUITE_ADD_TEST(suite, test_cil_gen_nametypetransition_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_nametypetransition_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_nametypetransition_astnull_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_nametypetransition); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_nametypetransition_neg); SUITE_ADD_TEST(suite, test_cil_gen_rangetransition); SUITE_ADD_TEST(suite, test_cil_gen_rangetransition_namedtransition); SUITE_ADD_TEST(suite, test_cil_gen_rangetransition_anon_low_l); SUITE_ADD_TEST(suite, test_cil_gen_rangetransition_anon_low_l_neg); SUITE_ADD_TEST(suite, test_cil_gen_rangetransition_anon_high_l); SUITE_ADD_TEST(suite, test_cil_gen_rangetransition_anon_high_l_neg); SUITE_ADD_TEST(suite, test_cil_gen_rangetransition_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_rangetransition_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_rangetransition_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_rangetransition_nofirsttype_neg); SUITE_ADD_TEST(suite, test_cil_gen_rangetransition_firsttype_inparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_rangetransition_nosecondtype_neg); SUITE_ADD_TEST(suite, test_cil_gen_rangetransition_secondtype_inparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_rangetransition_noclass_neg); SUITE_ADD_TEST(suite, test_cil_gen_rangetransition_class_inparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_rangetransition_nolevel_l_neg); SUITE_ADD_TEST(suite, test_cil_gen_rangetransition_nolevel_h_neg); SUITE_ADD_TEST(suite, test_cil_gen_rangetransition_extra_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_rangetransition); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_rangetransition_neg); SUITE_ADD_TEST(suite, test_cil_gen_expr_stack_and); SUITE_ADD_TEST(suite, test_cil_gen_expr_stack_or); SUITE_ADD_TEST(suite, test_cil_gen_expr_stack_xor); SUITE_ADD_TEST(suite, test_cil_gen_expr_stack_not); SUITE_ADD_TEST(suite, test_cil_gen_expr_stack_not_noexpr_neg); SUITE_ADD_TEST(suite, test_cil_gen_expr_stack_not_extraexpr_neg); SUITE_ADD_TEST(suite, test_cil_gen_expr_stack_eq); SUITE_ADD_TEST(suite, test_cil_gen_expr_stack_neq); SUITE_ADD_TEST(suite, test_cil_gen_expr_stack_nested); SUITE_ADD_TEST(suite, test_cil_gen_expr_stack_nested_neg); SUITE_ADD_TEST(suite, test_cil_gen_expr_stack_nested_emptyargs_neg); SUITE_ADD_TEST(suite, test_cil_gen_expr_stack_nested_missingoperator_neg); SUITE_ADD_TEST(suite, test_cil_gen_expr_stack_arg1null_neg); SUITE_ADD_TEST(suite, test_cil_gen_expr_stack_arg2null_neg); SUITE_ADD_TEST(suite, test_cil_gen_expr_stack_extraarg_neg); SUITE_ADD_TEST(suite, test_cil_gen_expr_stack_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_expr_stack_stacknull_neg); SUITE_ADD_TEST(suite, test_cil_gen_boolif_multiplebools_true); SUITE_ADD_TEST(suite, test_cil_gen_boolif_multiplebools_false); SUITE_ADD_TEST(suite, test_cil_gen_boolif_multiplebools_unknowncond_neg); SUITE_ADD_TEST(suite, test_cil_gen_boolif_true); SUITE_ADD_TEST(suite, test_cil_gen_boolif_false); SUITE_ADD_TEST(suite, test_cil_gen_boolif_unknowncond_neg); SUITE_ADD_TEST(suite, test_cil_gen_boolif_nested); SUITE_ADD_TEST(suite, test_cil_gen_boolif_nested_neg); SUITE_ADD_TEST(suite, test_cil_gen_boolif_extra_neg); SUITE_ADD_TEST(suite, test_cil_gen_boolif_extra_parens_neg); SUITE_ADD_TEST(suite, test_cil_gen_boolif_nocond); SUITE_ADD_TEST(suite, test_cil_gen_boolif_neg); SUITE_ADD_TEST(suite, test_cil_gen_boolif_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_boolif_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_boolif_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_boolif_nocond_neg); SUITE_ADD_TEST(suite, test_cil_gen_boolif_notruelist_neg); SUITE_ADD_TEST(suite, test_cil_gen_boolif_empty_cond_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_boolif); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_boolif_neg); SUITE_ADD_TEST(suite, test_cil_gen_tunif_multiplebools_true); SUITE_ADD_TEST(suite, test_cil_gen_tunif_multiplebools_false); SUITE_ADD_TEST(suite, test_cil_gen_tunif_multiplebools_unknowncond_neg); SUITE_ADD_TEST(suite, test_cil_gen_tunif_true); SUITE_ADD_TEST(suite, test_cil_gen_tunif_false); SUITE_ADD_TEST(suite, test_cil_gen_tunif_unknowncond_neg); SUITE_ADD_TEST(suite, test_cil_gen_tunif_nocond); SUITE_ADD_TEST(suite, test_cil_gen_tunif_nested); SUITE_ADD_TEST(suite, test_cil_gen_tunif_nested_neg); SUITE_ADD_TEST(suite, test_cil_gen_tunif_extra_neg); SUITE_ADD_TEST(suite, test_cil_gen_tunif_extra_parens_neg); SUITE_ADD_TEST(suite, test_cil_gen_tunif_neg); SUITE_ADD_TEST(suite, test_cil_gen_tunif_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_tunif_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_tunif_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_tunif_nocond_neg); SUITE_ADD_TEST(suite, test_cil_gen_tunif_notruelist_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_tunif); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_tunif_neg); SUITE_ADD_TEST(suite, test_cil_gen_condblock_true); SUITE_ADD_TEST(suite, test_cil_gen_condblock_false); SUITE_ADD_TEST(suite, test_cil_gen_condblock_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_condblock_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_condblock_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_condblock_nocond_neg); SUITE_ADD_TEST(suite, test_cil_gen_condblock_extra_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_condblock_true); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_condblock_true_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_condblock_false); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_condblock_false_neg); SUITE_ADD_TEST(suite, test_cil_gen_typealias); SUITE_ADD_TEST(suite, test_cil_gen_typealias_incomplete_neg); SUITE_ADD_TEST(suite, test_cil_gen_typealias_incomplete_neg2); SUITE_ADD_TEST(suite, test_cil_gen_typealias_extratype_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_typealias); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_typealias_notype_neg); SUITE_ADD_TEST(suite, test_cil_gen_typealias_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_typealias_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_typealias_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_typeattributeset); SUITE_ADD_TEST(suite, test_cil_gen_typeattributeset_and_two_types); SUITE_ADD_TEST(suite, test_cil_gen_typeattributeset_not); SUITE_ADD_TEST(suite, test_cil_gen_typeattributeset_exclude_attr); SUITE_ADD_TEST(suite, test_cil_gen_typeattributeset_exclude_neg); SUITE_ADD_TEST(suite, test_cil_gen_typeattributeset_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_typeattributeset_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_typeattributeset_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_typeattributeset_noname_neg); SUITE_ADD_TEST(suite, test_cil_gen_typeattributeset_nameinparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_typeattributeset_emptylists_neg); SUITE_ADD_TEST(suite, test_cil_gen_typeattributeset_listinparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_typeattributeset_extra_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_typeattributeset); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_typeattributeset_neg); SUITE_ADD_TEST(suite, test_cil_gen_userbounds); SUITE_ADD_TEST(suite, test_cil_gen_userbounds_notype1_neg); SUITE_ADD_TEST(suite, test_cil_gen_userbounds_type1_inparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_userbounds_notype2_neg); SUITE_ADD_TEST(suite, test_cil_gen_userbounds_type2_inparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_userbounds_extra_neg); SUITE_ADD_TEST(suite, test_cil_gen_userbounds_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_userbounds_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_userbounds_astnull_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_userbounds); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_userbounds_neg); SUITE_ADD_TEST(suite, test_cil_gen_role); SUITE_ADD_TEST(suite, test_cil_gen_role_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_role_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_role_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_role_extrarole_neg); SUITE_ADD_TEST(suite, test_cil_gen_role_noname_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_role); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_role_neg); SUITE_ADD_TEST(suite, test_cil_gen_roletransition); SUITE_ADD_TEST(suite, test_cil_gen_roletransition_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_roletransition_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_roletransition_srcnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_roletransition_tgtnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_roletransition_resultnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_roletransition_extra_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_roletransition); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_roletransition_neg); SUITE_ADD_TEST(suite, test_cil_gen_bool_true); SUITE_ADD_TEST(suite, test_cil_gen_bool_tunable_true); SUITE_ADD_TEST(suite, test_cil_gen_bool_false); SUITE_ADD_TEST(suite, test_cil_gen_bool_tunable_false); SUITE_ADD_TEST(suite, test_cil_gen_bool_none_neg); SUITE_ADD_TEST(suite, test_cil_gen_bool_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_bool_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_bool_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_bool_notbool_neg); SUITE_ADD_TEST(suite, test_cil_gen_bool_boolname_neg); SUITE_ADD_TEST(suite, test_cil_gen_bool_extraname_false_neg); SUITE_ADD_TEST(suite, test_cil_gen_bool_extraname_true_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_bool); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_bool_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_bool_tunable); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_bool_tunable_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq2_t1type); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq2_t1t1_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq2_t2type); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq2_t2t2_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq2_r1role); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq2_r1r1_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq2_r2role); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq2_r2r2_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq2_t1t2); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq_r1r2); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq2_r1r2); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq2_u1u2); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq2_u1user); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq2_u1u1_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq2_u2user); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq2_u2u2_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq_l2h2); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq_l2_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq_l1l2); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq_l1h1); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq_l1h2); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq_h1l2); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq_h1h2); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq_h1_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq_l1l1_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq2_l1l2_constrain_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq_l1l2_constrain_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq_leftkeyword_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq_noexpr1_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq_expr1inparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq_noexpr2_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq_expr2inparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq_extraexpr_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq2); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq2_noexpr1_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq2_expr1inparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq2_noexpr2_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq2_expr2inparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_eq2_extraexpr_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_noteq); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_noteq_noexpr1_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_noteq_expr1inparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_noteq_noexpr2_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_noteq_expr2inparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_noteq_extraexpr_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_not); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_not_noexpr_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_not_emptyparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_not_extraparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_or); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_or_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_or_noexpr_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_or_emptyfirstparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_or_missingsecondexpr_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_or_emptysecondparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_or_extraexpr_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_and); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_and_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_and_noexpr_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_and_emptyfirstparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_and_missingsecondexpr_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_and_emptysecondparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_and_extraexpr_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_dom); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_dom_noexpr1_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_dom_expr1inparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_dom_noexpr2_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_dom_expr2inparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_dom_extraexpr_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_domby); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_domby_noexpr1_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_domby_expr1inparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_domby_noexpr2_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_domby_expr2inparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_domby_extraexpr_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_incomp); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_incomp_noexpr1_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_incomp_expr1inparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_incomp_noexpr2_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_incomp_expr2inparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_incomp_extraexpr_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_stacknull_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_operatorinparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expr_stack_incorrectcall_neg); SUITE_ADD_TEST(suite, test_cil_gen_roleallow); SUITE_ADD_TEST(suite, test_cil_gen_roleallow_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_roleallow_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_roleallow_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_roleallow_srcnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_roleallow_tgtnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_roleallow_extra_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_roleallow); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_roleallow_neg); SUITE_ADD_TEST(suite, test_cil_gen_rolebounds); SUITE_ADD_TEST(suite, test_cil_gen_rolebounds_norole1_neg); SUITE_ADD_TEST(suite, test_cil_gen_rolebounds_role1_inparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_rolebounds_norole2_neg); SUITE_ADD_TEST(suite, test_cil_gen_rolebounds_role2_inparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_rolebounds_extra_neg); SUITE_ADD_TEST(suite, test_cil_gen_rolebounds_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_rolebounds_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_rolebounds_astnull_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_rolebounds); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_rolebounds_neg); SUITE_ADD_TEST(suite, test_cil_gen_avrule); SUITE_ADD_TEST(suite, test_cil_gen_avrule_permset); SUITE_ADD_TEST(suite, test_cil_gen_avrule_permset_anon); SUITE_ADD_TEST(suite, test_cil_gen_avrule_extra_neg); SUITE_ADD_TEST(suite, test_cil_gen_avrule_sourceparens); SUITE_ADD_TEST(suite, test_cil_gen_avrule_sourceemptyparen_neg); SUITE_ADD_TEST(suite, test_cil_gen_avrule_targetparens); SUITE_ADD_TEST(suite, test_cil_gen_avrule_targetemptyparen_neg); SUITE_ADD_TEST(suite, test_cil_gen_avrule_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_avrule_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_avrule_sourcedomainnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_avrule_targetdomainnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_avrule_objectclassnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_avrule_permsnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_avrule_twolists_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_avrule_allow); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_avrule_allow_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_avrule_auditallow); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_avrule_auditallow_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_avrule_dontaudit); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_avrule_dontaudit_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_avrule_neverallow); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_avrule_neverallow_neg); SUITE_ADD_TEST(suite, test_cil_gen_type_rule_transition); SUITE_ADD_TEST(suite, test_cil_gen_type_rule_transition_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_type_rule_transition_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_type_rule_transition_srcnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_type_rule_transition_tgtnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_type_rule_transition_objnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_type_rule_transition_resultnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_type_rule_transition_extra_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_type_rule_transition); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_type_rule_transition_neg); SUITE_ADD_TEST(suite, test_cil_gen_type_rule_change); SUITE_ADD_TEST(suite, test_cil_gen_type_rule_change_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_type_rule_change_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_type_rule_change_srcnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_type_rule_change_tgtnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_type_rule_change_objnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_type_rule_change_resultnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_type_rule_change_extra_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_type_rule_change); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_type_rule_change_neg); SUITE_ADD_TEST(suite, test_cil_gen_type_rule_member); SUITE_ADD_TEST(suite, test_cil_gen_type_rule_member_extra_neg); SUITE_ADD_TEST(suite, test_cil_gen_type_rule_member_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_type_rule_member_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_type_rule_member_srcnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_type_rule_member_tgtnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_type_rule_member_objnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_type_rule_member_resultnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_type_rule_member_extra_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_type_rule_member); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_type_rule_member_neg); SUITE_ADD_TEST(suite, test_cil_gen_user); SUITE_ADD_TEST(suite, test_cil_gen_user_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_user_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_user_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_user_nouser_neg); SUITE_ADD_TEST(suite, test_cil_gen_user_xsinfo_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_user); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_user_neg); SUITE_ADD_TEST(suite, test_cil_gen_userlevel); SUITE_ADD_TEST(suite, test_cil_gen_userlevel_anon_level); SUITE_ADD_TEST(suite, test_cil_gen_userlevel_anon_level_neg); SUITE_ADD_TEST(suite, test_cil_gen_userlevel_usernull_neg); SUITE_ADD_TEST(suite, test_cil_gen_userlevel_userrange_neg); SUITE_ADD_TEST(suite, test_cil_gen_userlevel_levelnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_userlevel_levelrangeempty_neg); SUITE_ADD_TEST(suite, test_cil_gen_userlevel_extra_neg); SUITE_ADD_TEST(suite, test_cil_gen_userlevel_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_userlevel_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_userlevel_astnull_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_userlevel); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_userlevel_neg); SUITE_ADD_TEST(suite, test_cil_gen_userrange_named); SUITE_ADD_TEST(suite, test_cil_gen_userrange_anon); SUITE_ADD_TEST(suite, test_cil_gen_userrange_usernull_neg); SUITE_ADD_TEST(suite, test_cil_gen_userrange_anonuser_neg); SUITE_ADD_TEST(suite, test_cil_gen_userrange_rangenamenull_neg); SUITE_ADD_TEST(suite, test_cil_gen_userrange_anonrangeinvalid_neg); SUITE_ADD_TEST(suite, test_cil_gen_userrange_anonrangeempty_neg); SUITE_ADD_TEST(suite, test_cil_gen_userrange_extra_neg); SUITE_ADD_TEST(suite, test_cil_gen_userrange_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_userrange_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_userrange_astnull_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_userrange); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_userrange_neg); SUITE_ADD_TEST(suite, test_cil_gen_sensitivity); SUITE_ADD_TEST(suite, test_cil_gen_sensitivity_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_sensitivity_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_sensitivity_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_sensitivity_sensnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_sensitivity_senslist_neg); SUITE_ADD_TEST(suite, test_cil_gen_sensitivity_extra_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_sensitivity); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_sensitivity_neg); SUITE_ADD_TEST(suite, test_cil_gen_sensalias); SUITE_ADD_TEST(suite, test_cil_gen_sensalias_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_sensalias_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_sensalias_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_sensalias_sensnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_sensalias_senslist_neg); SUITE_ADD_TEST(suite, test_cil_gen_sensalias_aliasnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_sensalias_aliaslist_neg); SUITE_ADD_TEST(suite, test_cil_gen_sensalias_extra_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_sensalias); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_sensalias_neg); SUITE_ADD_TEST(suite, test_cil_gen_category); SUITE_ADD_TEST(suite, test_cil_gen_category_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_category_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_category_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_category_catnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_category_catlist_neg); SUITE_ADD_TEST(suite, test_cil_gen_category_extra_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_category); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_category_neg); SUITE_ADD_TEST(suite, test_cil_gen_catset); SUITE_ADD_TEST(suite, test_cil_gen_catset_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_catset_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_catset_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_catset_namenull_neg); SUITE_ADD_TEST(suite, test_cil_gen_catset_setnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_catset_namelist_neg); SUITE_ADD_TEST(suite, test_cil_gen_catset_extra_neg); SUITE_ADD_TEST(suite, test_cil_gen_catset_nodefail_neg); SUITE_ADD_TEST(suite, test_cil_gen_catset_notset_neg); SUITE_ADD_TEST(suite, test_cil_gen_catset_settolistfail_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_catset); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_catset_neg); SUITE_ADD_TEST(suite, test_cil_gen_catalias); SUITE_ADD_TEST(suite, test_cil_gen_catalias_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_catalias_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_catalias_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_catalias_catnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_catalias_aliasnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_catalias_extra_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_catalias); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_catalias_neg); SUITE_ADD_TEST(suite, test_cil_gen_catrange); SUITE_ADD_TEST(suite, test_cil_gen_catrange_noname_neg); SUITE_ADD_TEST(suite, test_cil_gen_catrange_norange_neg); SUITE_ADD_TEST(suite, test_cil_gen_catrange_emptyrange_neg); SUITE_ADD_TEST(suite, test_cil_gen_catrange_extrarange_neg); SUITE_ADD_TEST(suite, test_cil_gen_catrange_extra_neg); SUITE_ADD_TEST(suite, test_cil_gen_catrange_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_catrange_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_catrange_astnull_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_catrange); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_catrange_neg); SUITE_ADD_TEST(suite, test_cil_gen_roletype); SUITE_ADD_TEST(suite, test_cil_gen_roletype_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_roletype_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_roletype_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_roletype_empty_neg); SUITE_ADD_TEST(suite, test_cil_gen_roletype_rolelist_neg); SUITE_ADD_TEST(suite, test_cil_gen_roletype_roletype_sublist_neg); SUITE_ADD_TEST(suite, test_cil_gen_roletype_typelist_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_roletype); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_roletype_neg); SUITE_ADD_TEST(suite, test_cil_gen_userrole); SUITE_ADD_TEST(suite, test_cil_gen_userrole_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_userrole_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_userrole_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_userrole_empty_neg); SUITE_ADD_TEST(suite, test_cil_gen_userrole_userlist_neg); SUITE_ADD_TEST(suite, test_cil_gen_userrole_userrole_sublist_neg); SUITE_ADD_TEST(suite, test_cil_gen_userrole_rolelist_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_userrole); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_userrole_neg); SUITE_ADD_TEST(suite, test_cil_gen_classcommon); SUITE_ADD_TEST(suite, test_cil_gen_classcommon_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_classcommon_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_classcommon_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_classcommon_missingclassname_neg); SUITE_ADD_TEST(suite, test_cil_gen_classcommon_noperms_neg); SUITE_ADD_TEST(suite, test_cil_gen_classcommon_extraperms_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_classcommon); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_classcommon_neg); SUITE_ADD_TEST(suite, test_cil_gen_catorder); SUITE_ADD_TEST(suite, test_cil_gen_catorder_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_catorder_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_catorder_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_catorder_missingcats_neg); SUITE_ADD_TEST(suite, test_cil_gen_catorder_nosublist_neg); SUITE_ADD_TEST(suite, test_cil_gen_catorder_nestedcat_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_catorder); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_catorder_neg); SUITE_ADD_TEST(suite, test_cil_gen_dominance); SUITE_ADD_TEST(suite, test_cil_gen_dominance_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_dominance_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_dominance_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_dominance_nosensitivities_neg); SUITE_ADD_TEST(suite, test_cil_gen_dominance_nosublist_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_dominance); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_dominance_neg); SUITE_ADD_TEST(suite, test_cil_gen_senscat); SUITE_ADD_TEST(suite, test_cil_gen_senscat_nosublist); SUITE_ADD_TEST(suite, test_cil_gen_senscat_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_senscat_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_senscat_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_senscat_nosensitivities_neg); SUITE_ADD_TEST(suite, test_cil_gen_senscat_sublist_neg); SUITE_ADD_TEST(suite, test_cil_gen_senscat_nocat_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_senscat); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_senscat_neg); SUITE_ADD_TEST(suite, test_cil_fill_level); SUITE_ADD_TEST(suite, test_cil_fill_level_sensnull_neg); SUITE_ADD_TEST(suite, test_cil_fill_level_levelnull_neg); SUITE_ADD_TEST(suite, test_cil_fill_level_nocat); SUITE_ADD_TEST(suite, test_cil_fill_level_emptycat_neg); SUITE_ADD_TEST(suite, test_cil_gen_level); SUITE_ADD_TEST(suite, test_cil_gen_level_nameinparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_level_emptysensparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_level_extra_neg); SUITE_ADD_TEST(suite, test_cil_gen_level_emptycat_neg); SUITE_ADD_TEST(suite, test_cil_gen_level_noname_neg); SUITE_ADD_TEST(suite, test_cil_gen_level_nosens_neg); SUITE_ADD_TEST(suite, test_cil_gen_level_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_level_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_level_astnull_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_level); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_level_neg); SUITE_ADD_TEST(suite, test_cil_gen_levelrange); SUITE_ADD_TEST(suite, test_cil_gen_levelrange_rangeinvalid_neg); SUITE_ADD_TEST(suite, test_cil_gen_levelrange_namenull_neg); SUITE_ADD_TEST(suite, test_cil_gen_levelrange_rangenull_neg); SUITE_ADD_TEST(suite, test_cil_gen_levelrange_rangeempty_neg); SUITE_ADD_TEST(suite, test_cil_gen_levelrange_extra_neg); SUITE_ADD_TEST(suite, test_cil_gen_levelrange_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_levelrange_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_levelrange_astnull_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_levelrange); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_levelrange_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain); SUITE_ADD_TEST(suite, test_cil_gen_constrain_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_classset_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_classset_noperm_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_classset_noclass_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_permset_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_permset_noclass_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_permset_noperm_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_expression_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_constrain_astnull_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_constrain); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_constrain_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_mlsconstrain); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_mlsconstrain_neg); SUITE_ADD_TEST(suite, test_cil_fill_context); SUITE_ADD_TEST(suite, test_cil_fill_context_unnamedlvl); SUITE_ADD_TEST(suite, test_cil_fill_context_nocontext_neg); SUITE_ADD_TEST(suite, test_cil_fill_context_nouser_neg); SUITE_ADD_TEST(suite, test_cil_fill_context_norole_neg); SUITE_ADD_TEST(suite, test_cil_fill_context_notype_neg); SUITE_ADD_TEST(suite, test_cil_fill_context_nolowlvl_neg); SUITE_ADD_TEST(suite, test_cil_fill_context_nohighlvl_neg); SUITE_ADD_TEST(suite, test_cil_fill_context_unnamedlvl_nocontextlow_neg); SUITE_ADD_TEST(suite, test_cil_fill_context_unnamedlvl_nocontexthigh_neg); SUITE_ADD_TEST(suite, test_cil_gen_context); SUITE_ADD_TEST(suite, test_cil_gen_context_notinparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_context_extralevel_neg); SUITE_ADD_TEST(suite, test_cil_gen_context_emptycontext_neg); SUITE_ADD_TEST(suite, test_cil_gen_context_extra_neg); SUITE_ADD_TEST(suite, test_cil_gen_context_doubleparen_neg); SUITE_ADD_TEST(suite, test_cil_gen_context_norole_neg); SUITE_ADD_TEST(suite, test_cil_gen_context_roleinparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_context_notype_neg); SUITE_ADD_TEST(suite, test_cil_gen_context_typeinparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_context_nolevels_neg); // SUITE_ADD_TEST(suite, test_cil_gen_context_nosecondlevel_neg); SUITE_ADD_TEST(suite, test_cil_gen_context_noname_neg); SUITE_ADD_TEST(suite, test_cil_gen_context_nouser_neg); SUITE_ADD_TEST(suite, test_cil_gen_context_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_context_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_context_astnull_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_context); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_context_neg); SUITE_ADD_TEST(suite, test_cil_gen_filecon_file); SUITE_ADD_TEST(suite, test_cil_gen_filecon_dir); SUITE_ADD_TEST(suite, test_cil_gen_filecon_char); SUITE_ADD_TEST(suite, test_cil_gen_filecon_block); SUITE_ADD_TEST(suite, test_cil_gen_filecon_socket); SUITE_ADD_TEST(suite, test_cil_gen_filecon_pipe); SUITE_ADD_TEST(suite, test_cil_gen_filecon_symlink); SUITE_ADD_TEST(suite, test_cil_gen_filecon_any); SUITE_ADD_TEST(suite, test_cil_gen_filecon_neg); SUITE_ADD_TEST(suite, test_cil_gen_filecon_anon_context); SUITE_ADD_TEST(suite, test_cil_gen_filecon_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_filecon_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_filecon_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_filecon_str1null_neg); SUITE_ADD_TEST(suite, test_cil_gen_filecon_str1_inparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_filecon_str2null_neg); SUITE_ADD_TEST(suite, test_cil_gen_filecon_str2_inparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_filecon_classnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_filecon_class_inparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_filecon_contextnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_filecon_context_neg); SUITE_ADD_TEST(suite, test_cil_gen_filecon_extra_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_filecon); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_filecon_neg); SUITE_ADD_TEST(suite, test_cil_gen_portcon_udp); SUITE_ADD_TEST(suite, test_cil_gen_portcon_tcp); SUITE_ADD_TEST(suite, test_cil_gen_portcon_unknownprotocol_neg); SUITE_ADD_TEST(suite, test_cil_gen_portcon_anon_context); SUITE_ADD_TEST(suite, test_cil_gen_portcon_portrange); SUITE_ADD_TEST(suite, test_cil_gen_portcon_portrange_one_neg); SUITE_ADD_TEST(suite, test_cil_gen_portcon_portrange_morethanone_neg); SUITE_ADD_TEST(suite, test_cil_gen_portcon_singleport_neg); SUITE_ADD_TEST(suite, test_cil_gen_portcon_lowport_neg); SUITE_ADD_TEST(suite, test_cil_gen_portcon_highport_neg); SUITE_ADD_TEST(suite, test_cil_gen_portcon_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_portcon_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_portcon_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_portcon_str1null_neg); SUITE_ADD_TEST(suite, test_cil_gen_portcon_str1parens_neg); SUITE_ADD_TEST(suite, test_cil_gen_portcon_portnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_portcon_contextnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_portcon_context_neg); SUITE_ADD_TEST(suite, test_cil_gen_portcon_extra_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_portcon); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_portcon_neg); SUITE_ADD_TEST(suite, test_cil_fill_ipaddr); SUITE_ADD_TEST(suite, test_cil_fill_ipaddr_addrnodenull_neg); SUITE_ADD_TEST(suite, test_cil_fill_ipaddr_addrnull_neg); SUITE_ADD_TEST(suite, test_cil_fill_ipaddr_addrinparens_neg); SUITE_ADD_TEST(suite, test_cil_fill_ipaddr_extra_neg); SUITE_ADD_TEST(suite, test_cil_gen_nodecon); SUITE_ADD_TEST(suite, test_cil_gen_nodecon_anon_context); SUITE_ADD_TEST(suite, test_cil_gen_nodecon_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_nodecon_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_nodecon_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_nodecon_ipnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_nodecon_ipanon); SUITE_ADD_TEST(suite, test_cil_gen_nodecon_ipanon_neg); SUITE_ADD_TEST(suite, test_cil_gen_nodecon_netmasknull_neg); SUITE_ADD_TEST(suite, test_cil_gen_nodecon_netmaskanon); SUITE_ADD_TEST(suite, test_cil_gen_nodecon_netmaskanon_neg); SUITE_ADD_TEST(suite, test_cil_gen_nodecon_contextnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_nodecon_context_neg); SUITE_ADD_TEST(suite, test_cil_gen_nodecon_extra_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_nodecon); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_nodecon_neg); SUITE_ADD_TEST(suite, test_cil_gen_genfscon); SUITE_ADD_TEST(suite, test_cil_gen_genfscon_anon_context); SUITE_ADD_TEST(suite, test_cil_gen_genfscon_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_genfscon_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_genfscon_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_genfscon_typenull_neg); SUITE_ADD_TEST(suite, test_cil_gen_genfscon_typeparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_genfscon_pathnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_genfscon_pathparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_genfscon_contextnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_genfscon_context_neg); SUITE_ADD_TEST(suite, test_cil_gen_genfscon_extra_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_genfscon); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_genfscon_neg); SUITE_ADD_TEST(suite, test_cil_gen_netifcon); SUITE_ADD_TEST(suite, test_cil_gen_netifcon_nested); SUITE_ADD_TEST(suite, test_cil_gen_netifcon_nested_neg); SUITE_ADD_TEST(suite, test_cil_gen_netifcon_nested_emptysecondlist_neg); SUITE_ADD_TEST(suite, test_cil_gen_netifcon_extra_nested_secondlist_neg); SUITE_ADD_TEST(suite, test_cil_gen_netifcon_nested_missingobjects_neg); SUITE_ADD_TEST(suite, test_cil_gen_netifcon_nested_secondnested_missingobjects_neg); SUITE_ADD_TEST(suite, test_cil_gen_netifcon_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_netifcon_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_netifcon_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_netifcon_ethmissing_neg); SUITE_ADD_TEST(suite, test_cil_gen_netifcon_interfacemissing_neg); SUITE_ADD_TEST(suite, test_cil_gen_netifcon_packetmissing_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_netifcon); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_netifcon_neg); SUITE_ADD_TEST(suite, test_cil_gen_pirqcon); SUITE_ADD_TEST(suite, test_cil_gen_pirqcon_pirqnotint_neg); SUITE_ADD_TEST(suite, test_cil_gen_pirqcon_nopirq_neg); SUITE_ADD_TEST(suite, test_cil_gen_pirqcon_pirqrange_neg); SUITE_ADD_TEST(suite, test_cil_gen_pirqcon_nocontext_neg); SUITE_ADD_TEST(suite, test_cil_gen_pirqcon_anoncontext_neg); SUITE_ADD_TEST(suite, test_cil_gen_pirqcon_extra_neg); SUITE_ADD_TEST(suite, test_cil_gen_pirqcon_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_pirqcon_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_pirqcon_astnull_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_pirqcon); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_pirqcon_neg); SUITE_ADD_TEST(suite, test_cil_gen_iomemcon); SUITE_ADD_TEST(suite, test_cil_gen_iomemcon_iomemrange); SUITE_ADD_TEST(suite, test_cil_gen_iomemcon_iomemrange_firstnotint_neg); SUITE_ADD_TEST(suite, test_cil_gen_iomemcon_iomemrange_secondnotint_neg); SUITE_ADD_TEST(suite, test_cil_gen_iomemcon_iomemrange_empty_neg); SUITE_ADD_TEST(suite, test_cil_gen_iomemcon_iomemrange_singleiomem_neg); SUITE_ADD_TEST(suite, test_cil_gen_iomemcon_iomemrange_morethantwoiomem_neg); SUITE_ADD_TEST(suite, test_cil_gen_iomemcon_iomemnotint_neg); SUITE_ADD_TEST(suite, test_cil_gen_iomemcon_noiomem_neg); SUITE_ADD_TEST(suite, test_cil_gen_iomemcon_nocontext_neg); SUITE_ADD_TEST(suite, test_cil_gen_iomemcon_anoncontext_neg); SUITE_ADD_TEST(suite, test_cil_gen_iomemcon_extra_neg); SUITE_ADD_TEST(suite, test_cil_gen_iomemcon_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_iomemcon_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_iomemcon_astnull_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_iomemcon); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_iomemcon_neg); SUITE_ADD_TEST(suite, test_cil_gen_ioportcon); SUITE_ADD_TEST(suite, test_cil_gen_ioportcon_ioportrange); SUITE_ADD_TEST(suite, test_cil_gen_ioportcon_ioportrange_firstnotint_neg); SUITE_ADD_TEST(suite, test_cil_gen_ioportcon_ioportrange_secondnotint_neg); SUITE_ADD_TEST(suite, test_cil_gen_ioportcon_ioportrange_empty_neg); SUITE_ADD_TEST(suite, test_cil_gen_ioportcon_ioportrange_singleioport_neg); SUITE_ADD_TEST(suite, test_cil_gen_ioportcon_ioportrange_morethantwoioport_neg); SUITE_ADD_TEST(suite, test_cil_gen_ioportcon_ioportnotint_neg); SUITE_ADD_TEST(suite, test_cil_gen_ioportcon_noioport_neg); SUITE_ADD_TEST(suite, test_cil_gen_ioportcon_nocontext_neg); SUITE_ADD_TEST(suite, test_cil_gen_ioportcon_anoncontext_neg); SUITE_ADD_TEST(suite, test_cil_gen_ioportcon_extra_neg); SUITE_ADD_TEST(suite, test_cil_gen_ioportcon_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_ioportcon_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_ioportcon_astnull_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_ioportcon); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_ioportcon_neg); SUITE_ADD_TEST(suite, test_cil_gen_pcidevicecon); SUITE_ADD_TEST(suite, test_cil_gen_pcidevicecon_pcidevicenotint_neg); SUITE_ADD_TEST(suite, test_cil_gen_pcidevicecon_nopcidevice_neg); SUITE_ADD_TEST(suite, test_cil_gen_pcidevicecon_pcidevicerange_neg); SUITE_ADD_TEST(suite, test_cil_gen_pcidevicecon_nocontext_neg); SUITE_ADD_TEST(suite, test_cil_gen_pcidevicecon_anoncontext_neg); SUITE_ADD_TEST(suite, test_cil_gen_pcidevicecon_extra_neg); SUITE_ADD_TEST(suite, test_cil_gen_pcidevicecon_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_pcidevicecon_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_pcidevicecon_astnull_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_pcidevicecon); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_pcidevicecon_neg); SUITE_ADD_TEST(suite, test_cil_gen_fsuse_anoncontext); SUITE_ADD_TEST(suite, test_cil_gen_fsuse_anoncontext_neg); SUITE_ADD_TEST(suite, test_cil_gen_fsuse_xattr); SUITE_ADD_TEST(suite, test_cil_gen_fsuse_task); SUITE_ADD_TEST(suite, test_cil_gen_fsuse_transition); SUITE_ADD_TEST(suite, test_cil_gen_fsuse_invalidtype_neg); SUITE_ADD_TEST(suite, test_cil_gen_fsuse_notype_neg); SUITE_ADD_TEST(suite, test_cil_gen_fsuse_typeinparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_fsuse_nofilesystem_neg); SUITE_ADD_TEST(suite, test_cil_gen_fsuse_filesysteminparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_fsuse_nocontext_neg); SUITE_ADD_TEST(suite, test_cil_gen_fsuse_emptyconparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_fsuse_extra_neg); SUITE_ADD_TEST(suite, test_cil_gen_fsuse_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_fsuse_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_fsuse_astnull_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_fsuse); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_fsuse_neg); SUITE_ADD_TEST(suite, test_cil_gen_macro_noparams); SUITE_ADD_TEST(suite, test_cil_gen_macro_type); SUITE_ADD_TEST(suite, test_cil_gen_macro_role); SUITE_ADD_TEST(suite, test_cil_gen_macro_user); SUITE_ADD_TEST(suite, test_cil_gen_macro_sensitivity); SUITE_ADD_TEST(suite, test_cil_gen_macro_category); SUITE_ADD_TEST(suite, test_cil_gen_macro_catset); SUITE_ADD_TEST(suite, test_cil_gen_macro_level); SUITE_ADD_TEST(suite, test_cil_gen_macro_class); SUITE_ADD_TEST(suite, test_cil_gen_macro_classmap); SUITE_ADD_TEST(suite, test_cil_gen_macro_permset); SUITE_ADD_TEST(suite, test_cil_gen_macro_duplicate); SUITE_ADD_TEST(suite, test_cil_gen_macro_duplicate_neg); SUITE_ADD_TEST(suite, test_cil_gen_macro_unknown_neg); SUITE_ADD_TEST(suite, test_cil_gen_macro_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_macro_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_macro_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_macro_unnamed_neg); SUITE_ADD_TEST(suite, test_cil_gen_macro_noparam_neg); SUITE_ADD_TEST(suite, test_cil_gen_macro_nosecondparam_neg); SUITE_ADD_TEST(suite, test_cil_gen_macro_noparam_name_neg); SUITE_ADD_TEST(suite, test_cil_gen_macro_emptyparam_neg); SUITE_ADD_TEST(suite, test_cil_gen_macro_paramcontainsperiod_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_macro); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_macro_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_macro_nested_macro_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_macro_nested_tunif_neg); SUITE_ADD_TEST(suite, test_cil_gen_call); SUITE_ADD_TEST(suite, test_cil_gen_call_noargs); SUITE_ADD_TEST(suite, test_cil_gen_call_anon); SUITE_ADD_TEST(suite, test_cil_gen_call_empty_call_neg); SUITE_ADD_TEST(suite, test_cil_gen_call_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_call_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_call_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_call_name_inparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_call_noname_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_call); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_call_neg); SUITE_ADD_TEST(suite, test_cil_gen_optional); SUITE_ADD_TEST(suite, test_cil_gen_optional_emptyoptional); SUITE_ADD_TEST(suite, test_cil_gen_optional_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_optional_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_optional_astnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_optional_unnamed_neg); SUITE_ADD_TEST(suite, test_cil_gen_optional_extra_neg); SUITE_ADD_TEST(suite, test_cil_gen_optional_nameinparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_optional_norule_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_optional); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_optional_neg); SUITE_ADD_TEST(suite, test_cil_gen_policycap); SUITE_ADD_TEST(suite, test_cil_gen_policycap_noname_neg); SUITE_ADD_TEST(suite, test_cil_gen_policycap_nameinparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_policycap_extra_neg); SUITE_ADD_TEST(suite, test_cil_gen_policycap_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_policycap_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_policycap_astnull_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_policycap); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_policycap_neg); SUITE_ADD_TEST(suite, test_cil_gen_ipaddr_ipv4); SUITE_ADD_TEST(suite, test_cil_gen_ipaddr_ipv4_neg); SUITE_ADD_TEST(suite, test_cil_gen_ipaddr_ipv6); SUITE_ADD_TEST(suite, test_cil_gen_ipaddr_ipv6_neg); SUITE_ADD_TEST(suite, test_cil_gen_ipaddr_noname_neg); SUITE_ADD_TEST(suite, test_cil_gen_ipaddr_nameinparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_ipaddr_noip_neg); SUITE_ADD_TEST(suite, test_cil_gen_ipaddr_ipinparens_neg); SUITE_ADD_TEST(suite, test_cil_gen_ipaddr_extra_neg); SUITE_ADD_TEST(suite, test_cil_gen_ipaddr_dbnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_ipaddr_currnull_neg); SUITE_ADD_TEST(suite, test_cil_gen_ipaddr_astnull_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_ipaddr); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_gen_ipaddr_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_node_helper_extraargsnull_neg); SUITE_ADD_TEST(suite, test_cil_build_ast_last_child_helper); SUITE_ADD_TEST(suite, test_cil_build_ast_last_child_helper_extraargsnull_neg); return suite; } CuSuite* CilTreeGetSuite(void) { CuSuite* suite = CuSuiteNew(); /* CilTest.c */ SUITE_ADD_TEST(suite, test_symtab_init); SUITE_ADD_TEST(suite, test_symtab_init_no_table_neg); /* test_cil.c */ SUITE_ADD_TEST(suite, test_cil_symtab_array_init); SUITE_ADD_TEST(suite, test_cil_db_init); SUITE_ADD_TEST(suite, test_cil_get_symtab_block); SUITE_ADD_TEST(suite, test_cil_get_symtab_class); SUITE_ADD_TEST(suite, test_cil_get_symtab_root); SUITE_ADD_TEST(suite, test_cil_get_symtab_flavor_neg); SUITE_ADD_TEST(suite, test_cil_get_symtab_null_neg); SUITE_ADD_TEST(suite, test_cil_get_symtab_node_null_neg); SUITE_ADD_TEST(suite, test_cil_get_symtab_parent_null_neg); /* test_cil_list.c */ SUITE_ADD_TEST(suite, test_cil_list_append_item); SUITE_ADD_TEST(suite, test_cil_list_append_item_append); SUITE_ADD_TEST(suite, test_cil_list_append_item_append_extra); SUITE_ADD_TEST(suite, test_cil_list_append_item_listnull_neg); SUITE_ADD_TEST(suite, test_cil_list_append_item_itemnull_neg); SUITE_ADD_TEST(suite, test_cil_list_prepend_item_prepend); SUITE_ADD_TEST(suite, test_cil_list_prepend_item_prepend_neg); SUITE_ADD_TEST(suite, test_cil_list_prepend_item_listnull_neg); SUITE_ADD_TEST(suite, test_cil_list_prepend_item_itemnull_neg); /* test_cil_symtab.c */ SUITE_ADD_TEST(suite, test_cil_symtab_insert); /* test_cil_tree.c */ SUITE_ADD_TEST(suite, test_cil_tree_init); SUITE_ADD_TEST(suite, test_cil_tree_node_init); /* test_cil_lexer.c */ SUITE_ADD_TEST(suite, test_cil_lexer_setup); SUITE_ADD_TEST(suite, test_cil_lexer_next); /* test_cil_parser.c */ SUITE_ADD_TEST(suite, test_cil_parser); /* test_cil_fqn.c */ SUITE_ADD_TEST(suite, test_cil_qualify_name); SUITE_ADD_TEST(suite, test_cil_qualify_name_cil_flavor); /* test cil_copy_ast.c */ SUITE_ADD_TEST(suite, test_cil_copy_list); SUITE_ADD_TEST(suite, test_cil_copy_list_sublist); SUITE_ADD_TEST(suite, test_cil_copy_list_sublist_extra); SUITE_ADD_TEST(suite, test_cil_copy_list_orignull_neg); SUITE_ADD_TEST(suite, test_cil_copy_block); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_block); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_block_merge); SUITE_ADD_TEST(suite, test_cil_copy_perm); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_perm); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_perm_neg); SUITE_ADD_TEST(suite, test_cil_copy_class); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_class); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_class_dup_neg); SUITE_ADD_TEST(suite, test_cil_copy_common); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_common); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_common_dup_neg); SUITE_ADD_TEST(suite, test_cil_copy_classcommon); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_classcommon); SUITE_ADD_TEST(suite, test_cil_copy_sid); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_sid); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_sid_merge); SUITE_ADD_TEST(suite, test_cil_copy_sidcontext); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_sidcontext); SUITE_ADD_TEST(suite, test_cil_copy_user); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_user); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_user_merge); SUITE_ADD_TEST(suite, test_cil_copy_role); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_role); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_role_merge); SUITE_ADD_TEST(suite, test_cil_copy_userrole); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_userrole); SUITE_ADD_TEST(suite, test_cil_copy_type); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_type); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_type_merge); SUITE_ADD_TEST(suite, test_cil_copy_typeattribute); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_typeattribute); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_typeattribute_merge); SUITE_ADD_TEST(suite, test_cil_copy_typealias); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_typealias); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_typealias_dup_neg); SUITE_ADD_TEST(suite, test_cil_copy_bool); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_bool); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_bool_dup_neg); SUITE_ADD_TEST(suite, test_cil_copy_avrule); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_avrule); SUITE_ADD_TEST(suite, test_cil_copy_type_rule); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_type_rule); SUITE_ADD_TEST(suite, test_cil_copy_sens); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_sens); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_sens_merge); SUITE_ADD_TEST(suite, test_cil_copy_sensalias); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_sensalias); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_sensalias_dup_neg); SUITE_ADD_TEST(suite, test_cil_copy_cat); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_cat); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_cat_merge); SUITE_ADD_TEST(suite, test_cil_copy_catalias); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_catalias); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_catalias_dup_neg); SUITE_ADD_TEST(suite, test_cil_copy_senscat); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_senscat); SUITE_ADD_TEST(suite, test_cil_copy_catorder); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_catorder); SUITE_ADD_TEST(suite, test_cil_copy_dominance); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_dominance); SUITE_ADD_TEST(suite, test_cil_copy_level); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_level); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_level_dup_neg); SUITE_ADD_TEST(suite, test_cil_copy_fill_level); SUITE_ADD_TEST(suite, test_cil_copy_context); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_context); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_context_dup_neg); SUITE_ADD_TEST(suite, test_cil_copy_netifcon); SUITE_ADD_TEST(suite, test_cil_copy_netifcon_nested); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_netifcon); SUITE_ADD_TEST(suite, test_cil_copy_fill_context); SUITE_ADD_TEST(suite, test_cil_copy_fill_context_anonrange); SUITE_ADD_TEST(suite, test_cil_copy_call); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_call); SUITE_ADD_TEST(suite, test_cil_copy_optional); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_optional); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_optional_merge); SUITE_ADD_TEST(suite, test_cil_copy_nodecon); SUITE_ADD_TEST(suite, test_cil_copy_nodecon_anon); SUITE_ADD_TEST(suite, test_cil_copy_fill_ipaddr); SUITE_ADD_TEST(suite, test_cil_copy_ipaddr); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_ipaddr); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_ipaddr_dup_neg); SUITE_ADD_TEST(suite, test_cil_copy_conditional); SUITE_ADD_TEST(suite, test_cil_copy_boolif); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_boolif); SUITE_ADD_TEST(suite, test_cil_copy_constrain); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_mlsconstrain); //SUITE_ADD_TEST(suite, test_cil_copy_ast); //SUITE_ADD_TEST(suite, test_cil_copy_ast_neg); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_orignull_neg); SUITE_ADD_TEST(suite, test_cil_copy_node_helper_extraargsnull_neg); /* test_post.c */ SUITE_ADD_TEST(suite, test_cil_post_filecon_compare_meta_a_not_b); SUITE_ADD_TEST(suite, test_cil_post_filecon_compare_meta_b_not_a); SUITE_ADD_TEST(suite, test_cil_post_filecon_compare_meta_a_and_b_strlen_a_greater_b); SUITE_ADD_TEST(suite, test_cil_post_filecon_compare_meta_a_and_b_strlen_b_greater_a); SUITE_ADD_TEST(suite, test_cil_post_filecon_compare_type_atype_greater_btype); SUITE_ADD_TEST(suite, test_cil_post_filecon_compare_type_btype_greater_atype); SUITE_ADD_TEST(suite, test_cil_post_filecon_compare_stemlen_a_greater_b); SUITE_ADD_TEST(suite, test_cil_post_filecon_compare_stemlen_b_greater_a); SUITE_ADD_TEST(suite, test_cil_post_filecon_compare_equal); SUITE_ADD_TEST(suite, test_cil_post_genfscon_compare_atypestr_greater_btypestr); SUITE_ADD_TEST(suite, test_cil_post_genfscon_compare_btypestr_greater_atypestr); SUITE_ADD_TEST(suite, test_cil_post_genfscon_compare_apathstr_greater_bpathstr); SUITE_ADD_TEST(suite, test_cil_post_genfscon_compare_bpathstr_greater_apathstr); SUITE_ADD_TEST(suite, test_cil_post_genfscon_compare_equal); SUITE_ADD_TEST(suite, test_cil_post_netifcon_compare_a_greater_b); SUITE_ADD_TEST(suite, test_cil_post_netifcon_compare_b_greater_a); SUITE_ADD_TEST(suite, test_cil_post_netifcon_compare_equal); SUITE_ADD_TEST(suite, test_cil_post_nodecon_compare_aipv4_bipv6); SUITE_ADD_TEST(suite, test_cil_post_nodecon_compare_aipv6_bipv4); SUITE_ADD_TEST(suite, test_cil_post_nodecon_compare_aipv4_greaterthan_bipv4); SUITE_ADD_TEST(suite, test_cil_post_nodecon_compare_aipv4_lessthan_bipv4); SUITE_ADD_TEST(suite, test_cil_post_nodecon_compare_amaskipv4_greaterthan_bmaskipv4); SUITE_ADD_TEST(suite, test_cil_post_nodecon_compare_amaskipv4_lessthan_bmaskipv4); SUITE_ADD_TEST(suite, test_cil_post_nodecon_compare_aipv6_greaterthan_bipv6); SUITE_ADD_TEST(suite, test_cil_post_nodecon_compare_aipv6_lessthan_bipv6); SUITE_ADD_TEST(suite, test_cil_post_nodecon_compare_amaskipv6_greaterthan_bmaskipv6); SUITE_ADD_TEST(suite, test_cil_post_nodecon_compare_amaskipv6_lessthan_bmaskipv6); SUITE_ADD_TEST(suite, test_cil_post_fsuse_compare_type_a_greater_b); SUITE_ADD_TEST(suite, test_cil_post_fsuse_compare_type_b_greater_a); SUITE_ADD_TEST(suite, test_cil_post_fsuse_compare_fsstr_a_greater_b); SUITE_ADD_TEST(suite, test_cil_post_fsuse_compare_fsstr_b_greater_a); SUITE_ADD_TEST(suite, test_cil_post_fsuse_compare_equal); return suite; } CuSuite* CilTestFullCil(void) { CuSuite* suite = CuSuiteNew(); SUITE_ADD_TEST(suite, test_min_policy); SUITE_ADD_TEST(suite, test_integration); return suite; } libsepol-3.8.1/cil/test/unit/CilTest.h000066400000000000000000000035501476211737200175760ustar00rootroot00000000000000/* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #ifndef CILTEST_H_ #define CILTEST_H_ #include "../../src/cil_tree.h" // TODO Check more in the data structures struct cil_file_data { char *buffer; uint32_t file_size; }; void set_cil_file_data(struct cil_file_data **); void gen_test_tree(struct cil_tree **, char **); #endif libsepol-3.8.1/cil/test/unit/CuTest.c000066400000000000000000000215131476211737200174300ustar00rootroot00000000000000/* * Copyright (c) 2003 Asim Jalis * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages * arising from the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software in * a product, an acknowledgment in the product documentation would be * appreciated but is not required. * * 2. Altered source versions must be plainly marked as such, and must not * be misrepresented as being the original software. * * 3. This notice may not be removed or altered from any source * distribution. */ #include #include #include #include #include #include #include "CuTest.h" /*-------------------------------------------------------------------------* * CuStr *-------------------------------------------------------------------------*/ char* CuStrAlloc(int size) { char* newStr = (char*) malloc( sizeof(char) * (size) ); return newStr; } char* CuStrCopy(const char* old) { int len = strlen(old); char* newStr = CuStrAlloc(len + 1); strcpy(newStr, old); return newStr; } /*-------------------------------------------------------------------------* * CuString *-------------------------------------------------------------------------*/ void CuStringInit(CuString* str) { str->length = 0; str->size = STRING_MAX; str->buffer = (char*) malloc(sizeof(char) * str->size); str->buffer[0] = '\0'; } CuString* CuStringNew(void) { CuString* str = (CuString*) malloc(sizeof(CuString)); str->length = 0; str->size = STRING_MAX; str->buffer = (char*) malloc(sizeof(char) * str->size); str->buffer[0] = '\0'; return str; } void CuStringDelete(CuString *str) { if (!str) return; free(str->buffer); free(str); } void CuStringResize(CuString* str, int newSize) { str->buffer = (char*) realloc(str->buffer, sizeof(char) * newSize); str->size = newSize; } void CuStringAppend(CuString* str, const char* text) { int length; if (text == NULL) { text = "NULL"; } length = strlen(text); if (str->length + length + 1 >= str->size) CuStringResize(str, str->length + length + 1 + STRING_INC); str->length += length; strcat(str->buffer, text); } void CuStringAppendChar(CuString* str, char ch) { char text[2]; text[0] = ch; text[1] = '\0'; CuStringAppend(str, text); } __attribute__ ((format (printf, 2, 3))) void CuStringAppendFormat(CuString* str, const char* format, ...) { va_list argp; char buf[HUGE_STRING_LEN]; va_start(argp, format); vsprintf(buf, format, argp); va_end(argp); CuStringAppend(str, buf); } void CuStringInsert(CuString* str, const char* text, int pos) { int length = strlen(text); if (pos > str->length) pos = str->length; if (str->length + length + 1 >= str->size) CuStringResize(str, str->length + length + 1 + STRING_INC); memmove(str->buffer + pos + length, str->buffer + pos, (str->length - pos) + 1); str->length += length; memcpy(str->buffer + pos, text, length); } /*-------------------------------------------------------------------------* * CuTest *-------------------------------------------------------------------------*/ void CuTestInit(CuTest* t, const char* name, TestFunction function) { t->name = CuStrCopy(name); t->failed = 0; t->ran = 0; t->message = NULL; t->function = function; t->jumpBuf = NULL; } CuTest* CuTestNew(const char* name, TestFunction function) { CuTest* tc = CU_ALLOC(CuTest); CuTestInit(tc, name, function); return tc; } void CuTestDelete(CuTest *t) { if (!t) return; free(t->name); free(t); } void CuTestRun(CuTest* tc) { jmp_buf buf; tc->jumpBuf = &buf; if (setjmp(buf) == 0) { tc->ran = 1; (tc->function)(tc); } tc->jumpBuf = 0; } static void CuFailInternal(CuTest* tc, const char* file, int line, CuString* string) { char buf[HUGE_STRING_LEN]; sprintf(buf, "%s:%d: ", file, line); CuStringInsert(string, buf, 0); tc->failed = 1; tc->message = string->buffer; if (tc->jumpBuf != 0) longjmp(*(tc->jumpBuf), 0); } void CuFail_Line(CuTest* tc, const char* file, int line, const char* message2, const char* message) { CuString string; CuStringInit(&string); if (message2 != NULL) { CuStringAppend(&string, message2); CuStringAppend(&string, ": "); } CuStringAppend(&string, message); CuFailInternal(tc, file, line, &string); } void CuAssert_Line(CuTest* tc, const char* file, int line, const char* message, int condition) { if (condition) return; CuFail_Line(tc, file, line, NULL, message); } void CuAssertStrEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, const char* expected, const char* actual) { CuString string; if ((expected == NULL && actual == NULL) || (expected != NULL && actual != NULL && strcmp(expected, actual) == 0)) { return; } CuStringInit(&string); if (message != NULL) { CuStringAppend(&string, message); CuStringAppend(&string, ": "); } CuStringAppend(&string, "expected <"); CuStringAppend(&string, expected); CuStringAppend(&string, "> but was <"); CuStringAppend(&string, actual); CuStringAppend(&string, ">"); CuFailInternal(tc, file, line, &string); } void CuAssertIntEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, int expected, int actual) { char buf[STRING_MAX]; if (expected == actual) return; sprintf(buf, "expected <%d> but was <%d>", expected, actual); CuFail_Line(tc, file, line, message, buf); } void CuAssertDblEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, double expected, double actual, double delta) { char buf[STRING_MAX]; if (fabs(expected - actual) <= delta) return; sprintf(buf, "expected <%f> but was <%f>", expected, actual); CuFail_Line(tc, file, line, message, buf); } void CuAssertPtrEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, void* expected, void* actual) { char buf[STRING_MAX]; if (expected == actual) return; sprintf(buf, "expected pointer <0x%p> but was <0x%p>", expected, actual); CuFail_Line(tc, file, line, message, buf); } /*-------------------------------------------------------------------------* * CuSuite *-------------------------------------------------------------------------*/ void CuSuiteInit(CuSuite* testSuite) { testSuite->count = 0; testSuite->failCount = 0; memset(testSuite->list, 0, sizeof(testSuite->list)); } CuSuite* CuSuiteNew(void) { CuSuite* testSuite = CU_ALLOC(CuSuite); CuSuiteInit(testSuite); return testSuite; } void CuSuiteDelete(CuSuite *testSuite) { unsigned int n; for (n=0; n < MAX_TEST_CASES; n++) { if (testSuite->list[n]) { CuTestDelete(testSuite->list[n]); } } free(testSuite); } void CuSuiteAdd(CuSuite* testSuite, CuTest *testCase) { assert(testSuite->count < MAX_TEST_CASES); testSuite->list[testSuite->count] = testCase; testSuite->count++; } void CuSuiteAddSuite(CuSuite* testSuite, CuSuite* testSuite2) { int i; for (i = 0 ; i < testSuite2->count ; ++i) { CuTest* testCase = testSuite2->list[i]; CuSuiteAdd(testSuite, testCase); } } void CuSuiteRun(CuSuite* testSuite) { int i; for (i = 0 ; i < testSuite->count ; ++i) { CuTest* testCase = testSuite->list[i]; CuTestRun(testCase); if (testCase->failed) { testSuite->failCount += 1; } } } void CuSuiteSummary(CuSuite* testSuite, CuString* summary) { int i; for (i = 0 ; i < testSuite->count ; ++i) { CuTest* testCase = testSuite->list[i]; CuStringAppend(summary, testCase->failed ? "F" : "."); } CuStringAppend(summary, "\n\n"); } void CuSuiteDetails(CuSuite* testSuite, CuString* details) { int i; int failCount = 0; if (testSuite->failCount == 0) { int passCount = testSuite->count - testSuite->failCount; const char* testWord = passCount == 1 ? "test" : "tests"; CuStringAppendFormat(details, "OK (%d %s)\n", passCount, testWord); } else { if (testSuite->failCount == 1) CuStringAppend(details, "There was 1 failure:\n"); else CuStringAppendFormat(details, "There were %d failures:\n", testSuite->failCount); for (i = 0 ; i < testSuite->count ; ++i) { CuTest* testCase = testSuite->list[i]; if (testCase->failed) { failCount++; CuStringAppendFormat(details, "%d) %s: %s\n", failCount, testCase->name, testCase->message); } } CuStringAppend(details, "\n!!!FAILURES!!!\n"); CuStringAppendFormat(details, "Runs: %d ", testSuite->count); CuStringAppendFormat(details, "Passes: %d ", testSuite->count - testSuite->failCount); CuStringAppendFormat(details, "Fails: %d\n", testSuite->failCount); } } libsepol-3.8.1/cil/test/unit/CuTest.h000066400000000000000000000116141476211737200174360ustar00rootroot00000000000000/* * Copyright (c) 2003 Asim Jalis * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages * arising from the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software in * a product, an acknowledgment in the product documentation would be * appreciated but is not required. * * 2. Altered source versions must be plainly marked as such, and must not * be misrepresented as being the original software. * * 3. This notice may not be removed or altered from any source * distribution. */ #ifndef CU_TEST_H #define CU_TEST_H #include #include #define CUTEST_VERSION "CuTest 1.5" /* CuString */ char* CuStrAlloc(int size); char* CuStrCopy(const char* old); #define CU_ALLOC(TYPE) ((TYPE*) malloc(sizeof(TYPE))) #define HUGE_STRING_LEN 8192 #define STRING_MAX 256 #define STRING_INC 256 typedef struct { int length; int size; char* buffer; } CuString; void CuStringInit(CuString* str); CuString* CuStringNew(void); void CuStringRead(CuString* str, const char* path); void CuStringAppend(CuString* str, const char* text); void CuStringAppendChar(CuString* str, char ch); void CuStringAppendFormat(CuString* str, const char* format, ...); void CuStringInsert(CuString* str, const char* text, int pos); void CuStringResize(CuString* str, int newSize); void CuStringDelete(CuString* str); /* CuTest */ typedef struct CuTest CuTest; typedef void (*TestFunction)(CuTest *); struct CuTest { char* name; TestFunction function; int failed; int ran; const char* message; jmp_buf *jumpBuf; }; void CuTestInit(CuTest* t, const char* name, TestFunction function); CuTest* CuTestNew(const char* name, TestFunction function); void CuTestRun(CuTest* tc); void CuTestDelete(CuTest *t); /* Internal versions of assert functions -- use the public versions */ void CuFail_Line(CuTest* tc, const char* file, int line, const char* message2, const char* message); void CuAssert_Line(CuTest* tc, const char* file, int line, const char* message, int condition); void CuAssertStrEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, const char* expected, const char* actual); void CuAssertIntEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, int expected, int actual); void CuAssertDblEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, double expected, double actual, double delta); void CuAssertPtrEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, void* expected, void* actual); /* public assert functions */ #define CuFail(tc, ms) CuFail_Line( (tc), __FILE__, __LINE__, NULL, (ms)) #define CuAssert(tc, ms, cond) CuAssert_Line((tc), __FILE__, __LINE__, (ms), (cond)) #define CuAssertTrue(tc, cond) CuAssert_Line((tc), __FILE__, __LINE__, "assert failed", (cond)) #define CuAssertStrEquals(tc,ex,ac) CuAssertStrEquals_LineMsg((tc),__FILE__,__LINE__,NULL,(ex),(ac)) #define CuAssertStrEquals_Msg(tc,ms,ex,ac) CuAssertStrEquals_LineMsg((tc),__FILE__,__LINE__,(ms),(ex),(ac)) #define CuAssertIntEquals(tc,ex,ac) CuAssertIntEquals_LineMsg((tc),__FILE__,__LINE__,NULL,(ex),(ac)) #define CuAssertIntEquals_Msg(tc,ms,ex,ac) CuAssertIntEquals_LineMsg((tc),__FILE__,__LINE__,(ms),(ex),(ac)) #define CuAssertDblEquals(tc,ex,ac,dl) CuAssertDblEquals_LineMsg((tc),__FILE__,__LINE__,NULL,(ex),(ac),(dl)) #define CuAssertDblEquals_Msg(tc,ms,ex,ac,dl) CuAssertDblEquals_LineMsg((tc),__FILE__,__LINE__,(ms),(ex),(ac),(dl)) #define CuAssertPtrEquals(tc,ex,ac) CuAssertPtrEquals_LineMsg((tc),__FILE__,__LINE__,NULL,(ex),(ac)) #define CuAssertPtrEquals_Msg(tc,ms,ex,ac) CuAssertPtrEquals_LineMsg((tc),__FILE__,__LINE__,(ms),(ex),(ac)) #define CuAssertPtrNotNull(tc,p) CuAssert_Line((tc),__FILE__,__LINE__,"null pointer unexpected",(p != NULL)) #define CuAssertPtrNotNullMsg(tc,msg,p) CuAssert_Line((tc),__FILE__,__LINE__,(msg),(p != NULL)) /* CuSuite */ #define MAX_TEST_CASES 1024 #define SUITE_ADD_TEST(SUITE,TEST) CuSuiteAdd(SUITE, CuTestNew(#TEST, TEST)) typedef struct { int count; CuTest* list[MAX_TEST_CASES]; int failCount; } CuSuite; void CuSuiteInit(CuSuite* testSuite); CuSuite* CuSuiteNew(void); void CuSuiteDelete(CuSuite *testSuite); void CuSuiteAdd(CuSuite* testSuite, CuTest *testCase); void CuSuiteAddSuite(CuSuite* testSuite, CuSuite* testSuite2); void CuSuiteRun(CuSuite* testSuite); void CuSuiteSummary(CuSuite* testSuite, CuString* summary); void CuSuiteDetails(CuSuite* testSuite, CuString* details); #endif /* CU_TEST_H */ libsepol-3.8.1/cil/test/unit/test_cil.c000066400000000000000000000125311476211737200200270ustar00rootroot00000000000000/* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #include #include "CuTest.h" #include "test_cil.h" #include "../../src/cil_internal.h" #include "../../src/cil_tree.h" void test_cil_symtab_array_init(CuTest *tc) { struct cil_db *test_new_db; test_new_db = malloc(sizeof(*test_new_db)); cil_symtab_array_init(test_new_db->symtab, cil_sym_sizes[CIL_SYM_ARRAY_ROOT]); CuAssertPtrNotNull(tc, test_new_db->symtab); free(test_new_db); } void test_cil_db_init(CuTest *tc) { struct cil_db *test_db; cil_db_init(&test_db); CuAssertPtrNotNull(tc, test_db->ast); CuAssertPtrNotNull(tc, test_db->symtab); CuAssertPtrNotNull(tc, test_db->symtab); } // TODO: Reach SEPOL_ERR return in cil_db_init ( currently can't produce a method to do so ) void test_cil_get_symtab_block(CuTest *tc) { symtab_t *symtab = NULL; struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->parent->flavor = CIL_BLOCK; test_ast_node->line = 1; int rc = cil_get_symtab(test_db, test_ast_node->parent, &symtab, CIL_SYM_BLOCKS); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertPtrNotNull(tc, symtab); } void test_cil_get_symtab_class(CuTest *tc) { symtab_t *symtab = NULL; struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->parent->flavor = CIL_CLASS; test_ast_node->line = 1; int rc = cil_get_symtab(test_db, test_ast_node->parent, &symtab, CIL_SYM_BLOCKS); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertPtrNotNull(tc, symtab); } void test_cil_get_symtab_root(CuTest *tc) { symtab_t *symtab = NULL; struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->parent->flavor = CIL_ROOT; test_ast_node->line = 1; int rc = cil_get_symtab(test_db, test_ast_node->parent, &symtab, CIL_SYM_BLOCKS); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertPtrNotNull(tc, symtab); } void test_cil_get_symtab_flavor_neg(CuTest *tc) { symtab_t *symtab = NULL; struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->parent->flavor = 1234567; test_ast_node->line = 1; int rc = cil_get_symtab(test_db, test_ast_node->parent, &symtab, CIL_SYM_BLOCKS); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertPtrEquals(tc, symtab, NULL); } void test_cil_get_symtab_null_neg(CuTest *tc) { symtab_t *symtab = NULL; struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = NULL; test_ast_node->line = 1; int rc = cil_get_symtab(test_db, test_ast_node->parent, &symtab, CIL_SYM_BLOCKS); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertPtrEquals(tc, symtab, NULL); } void test_cil_get_symtab_node_null_neg(CuTest *tc) { symtab_t *symtab = NULL; struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_get_symtab(test_db, test_ast_node, &symtab, CIL_SYM_BLOCKS); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertPtrEquals(tc, symtab, NULL); CuAssertPtrEquals(tc, test_ast_node, NULL); } void test_cil_get_symtab_parent_null_neg(CuTest *tc) { symtab_t *symtab = NULL; struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = NULL; test_ast_node->line = 1; int rc = cil_get_symtab(test_db, test_ast_node->parent, &symtab, CIL_SYM_BLOCKS); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertPtrEquals(tc, symtab, NULL); } libsepol-3.8.1/cil/test/unit/test_cil.h000066400000000000000000000041301476211737200200300ustar00rootroot00000000000000/* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #ifndef TEST_CIL_H_ #define TEST_CIL_H_ #include "CuTest.h" void test_cil_symtab_array_init(CuTest *); void test_cil_symtab_array_init_null_symtab_neg(CuTest *); void test_cil_db_init(CuTest *); void test_cil_get_symtab_block(CuTest *); void test_cil_get_symtab_class(CuTest *); void test_cil_get_symtab_root(CuTest *); void test_cil_get_symtab_flavor_neg(CuTest *); void test_cil_get_symtab_null_neg(CuTest *); void test_cil_get_symtab_node_null_neg(CuTest *); void test_cil_get_symtab_parent_null_neg(CuTest *); #endif libsepol-3.8.1/cil/test/unit/test_cil_build_ast.c000066400000000000000000021564561476211737200220760ustar00rootroot00000000000000/* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #include #include "CuTest.h" #include "CilTest.h" #include "test_cil_build_ast.h" #include "../../src/cil_build_ast.h" #include "../../src/cil_tree.h" int __cil_build_ast_node_helper(struct cil_tree_node *, uint32_t *, void *); int __cil_build_ast_last_child_helper(__attribute__((unused)) struct cil_tree_node *parse_current, void *); //int __cil_build_constrain_tree(struct cil_tree_node *parse_current, struct cil_tree_node *expr_root); struct cil_args_build { struct cil_tree_node *ast; struct cil_db *db; struct cil_tree_node *macro; struct cil_tree_node *tifstack; }; struct cil_args_build *gen_build_args(struct cil_tree_node *node, struct cil_db *db, struct cil_tree_node * macro, struct cil_tree_node *tifstack) { struct cil_args_build *args = cil_malloc(sizeof(*args)); args->ast = node; args->db = db; args->macro = macro; args->tifstack = tifstack; return args; } // First seen in cil_gen_common void test_cil_parse_to_list(CuTest *tc) { char *line[] = {"(", "allow", "test", "foo", "(", "bar", "(", "read", "write", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_current; test_current = test_tree->root->cl_head->cl_head; struct cil_avrule *test_avrule; cil_avrule_init(&test_avrule); test_avrule->rule_kind = CIL_AVRULE_ALLOWED; test_avrule->src_str = cil_strdup(test_current->next->data); test_avrule->tgt_str = cil_strdup(test_current->next->next->data); cil_classpermset_init(&test_avrule->classpermset); test_avrule->classpermset->class_str = cil_strdup(test_current->next->next->next->cl_head->data); cil_permset_init(&test_avrule->classpermset->permset); cil_list_init(&test_avrule->classpermset->permset->perms_list_str); test_current = test_current->next->next->next->cl_head->next->cl_head; int rc = cil_parse_to_list(test_current, test_avrule->classpermset->permset->perms_list_str, CIL_AST_STR); CuAssertIntEquals(tc, SEPOL_OK, rc); cil_destroy_avrule(test_avrule); } void test_cil_parse_to_list_currnull_neg(CuTest *tc) { char *line[] = {"(", "allow", "test", "foo", "(", "bar", "(", "read", "write", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_current; test_current = test_tree->root->cl_head->cl_head; struct cil_avrule *test_avrule; cil_avrule_init(&test_avrule); test_avrule->rule_kind = CIL_AVRULE_ALLOWED; test_avrule->src_str = cil_strdup(test_current->next->data); test_avrule->tgt_str = cil_strdup(test_current->next->next->data); cil_classpermset_init(&test_avrule->classpermset); test_avrule->classpermset->class_str = cil_strdup(test_current->next->next->next->cl_head->data); cil_permset_init(&test_avrule->classpermset->permset); cil_list_init(&test_avrule->classpermset->permset->perms_list_str); test_current = NULL; int rc = cil_parse_to_list(test_current, test_avrule->classpermset->permset->perms_list_str, CIL_AST_STR); CuAssertIntEquals(tc, SEPOL_ERR, rc); cil_destroy_avrule(test_avrule); } void test_cil_parse_to_list_listnull_neg(CuTest *tc) { char *line[] = {"(", "allow", "test", "foo", "(", "bar", "(", "read", "write", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_current; test_current = test_tree->root->cl_head->cl_head; struct cil_avrule *test_avrule; cil_avrule_init(&test_avrule); test_avrule->rule_kind = CIL_AVRULE_ALLOWED; test_avrule->src_str = cil_strdup(test_current->next->data); test_avrule->tgt_str = cil_strdup(test_current->next->next->data); cil_classpermset_init(&test_avrule->classpermset); test_avrule->classpermset->class_str = cil_strdup(test_current->next->next->next->cl_head->data); cil_permset_init(&test_avrule->classpermset->permset); test_current = test_current->next->next->next->cl_head->next->cl_head; int rc = cil_parse_to_list(test_current, test_avrule->classpermset->permset->perms_list_str, CIL_AST_STR); CuAssertIntEquals(tc, SEPOL_ERR, rc); cil_destroy_avrule(test_avrule); } void test_cil_set_to_list(CuTest *tc) { char *line[] = {"(", "foo1", "foo2", "(", "foo3", ")", ")", NULL}; struct cil_tree *test_tree; struct cil_list *cil_l = NULL; struct cil_list *sub_list = NULL; gen_test_tree(&test_tree, line); cil_list_init(&cil_l); int rc = cil_set_to_list(test_tree->root->cl_head, cil_l, 1); sub_list = (struct cil_list *)cil_l->head->next->next->data; CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertStrEquals(tc, "foo1", (char*)cil_l->head->data); CuAssertStrEquals(tc, "foo2", (char*)cil_l->head->next->data); CuAssertStrEquals(tc, "foo3", (char*)sub_list->head->data); } void test_cil_set_to_list_tree_node_null_neg(CuTest *tc) { struct cil_list *cil_l = NULL; int rc = cil_set_to_list(NULL, cil_l, 1); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_set_to_list_cl_head_null_neg(CuTest *tc) { char *line[] = {"(", "foo", "bar", ")", NULL}; struct cil_list *cil_l; struct cil_tree *test_tree = NULL; cil_list_init(&cil_l); gen_test_tree(&test_tree, line); test_tree->root->cl_head = NULL; int rc = cil_set_to_list(test_tree->root, cil_l, 1); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_set_to_list_listnull_neg(CuTest *tc) { char *line[] = {"(", "foo1", "foo2", "foo3", ")", NULL}; struct cil_tree *test_tree = NULL; gen_test_tree(&test_tree, line); int rc = cil_set_to_list(test_tree->root, NULL, 1); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_block(CuTest *tc) { char *line[] = {"(", "block", "a", "(", "type", "log", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_block(test_db, test_tree->root->cl_head->cl_head, test_ast_node, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertPtrNotNull(tc, test_ast_node->data); CuAssertIntEquals(tc, ((struct cil_block*)test_ast_node->data)->is_abstract, 0); CuAssertIntEquals(tc, test_ast_node->flavor, CIL_BLOCK); } void test_cil_gen_block_justblock_neg(CuTest *tc) { char *line[] = {"(", "block", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_block(test_db, test_tree->root->cl_head->cl_head, test_ast_node, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_block_noname_neg(CuTest *tc) { char *line[] = {"(", "block", "(", "type", "log", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_block(test_db, test_tree->root->cl_head->cl_head, test_ast_node, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_block_dbnull_neg(CuTest *tc) { char *line[] = {"(", "block", "foo", "(", "type", "log", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_block(test_db, test_tree->root->cl_head->cl_head, test_ast_node, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_block_treenull_neg(CuTest *tc) { char *line[] = {"(", "block", "foo", "(", "type", "log", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_tree->root->cl_head->cl_head = NULL; struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_block(test_db, test_tree->root->cl_head->cl_head, test_ast_node, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_block_nodenull_neg(CuTest *tc) { char *line[] = {"(", "block", "foo", "(", "type", "log", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_block(test_db, test_tree->root->cl_head->cl_head, test_ast_node, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_block_nodeparentnull_neg(CuTest *tc) { char *line[] = {"(", "block", "foo", "(", "type", "log", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = NULL; test_ast_node->line = 1; int rc = cil_gen_block(test_db, test_tree->root->cl_head->cl_head, test_ast_node, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_destroy_block(CuTest *tc) { char *line[] = {"(", "block", "a", "(", "type", "log", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_block(test_db, test_tree->root->cl_head->cl_head, test_ast_node, 0); cil_destroy_block((struct cil_block*)test_ast_node->data); CuAssertPtrEquals(tc, NULL,test_ast_node->data); } void test_cil_gen_blockinherit(CuTest *tc) { char *line[] = {"(", "blockinherit", "foo", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_blockinherit(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_blockinherit_namelist_neg(CuTest *tc) { char *line[] = {"(", "blockinherit", "(", "foo", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_blockinherit(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_blockinherit_namenull_neg(CuTest *tc) { char *line[] = {"(", "blockinherit", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_blockinherit(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_blockinherit_extra_neg(CuTest *tc) { char *line[] = {"(", "blockinherit", "foo", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_blockinherit(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_blockinherit_dbnull_neg(CuTest *tc) { char *line[] = {"(", "blockinherit", "foo", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_blockinherit(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_blockinherit_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_blockinherit(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_blockinherit_astnull_neg(CuTest *tc) { char *line[] = {"(", "blockinherit", "foo", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_blockinherit(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_perm(CuTest *tc) { char *line[] = {"(", "class", "foo", "(", "read", "write", "open", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); struct cil_class *new_node; cil_class_init(&new_node); struct cil_tree_node *new_tree_node; cil_tree_node_init(&new_tree_node); new_tree_node->data = new_node; new_tree_node->flavor = CIL_CLASS; test_ast_node->parent = new_tree_node; test_ast_node->line = 1; int rc = cil_gen_perm(test_db, test_tree->root->cl_head->cl_head->next->next->cl_head, test_ast_node); int rc1 = cil_gen_perm(test_db, test_tree->root->cl_head->cl_head->next->next->cl_head->next, test_ast_node); int rc2 = cil_gen_perm(test_db, test_tree->root->cl_head->cl_head->next->next->cl_head->next->next, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, SEPOL_OK, rc1); CuAssertIntEquals(tc, SEPOL_OK, rc2); } void test_cil_gen_perm_dbnull_neg(CuTest *tc) { char *line[] = {"(", "class", "file", "(", "read", "write", "open", ")", ")", NULL}; int rc = 0; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_current_perm = NULL; struct cil_tree_node *test_new_ast = NULL; struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; test_current_perm = test_tree->root->cl_head->cl_head->next->next->cl_head; cil_tree_node_init(&test_new_ast); test_new_ast->parent = test_ast_node; test_new_ast->line = test_current_perm->line; rc = cil_gen_perm(test_db, test_current_perm, test_new_ast); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_perm_currnull_neg(CuTest *tc) { char *line[] = {"(", "class", "file", "(", "read", "write", "open", ")", ")", NULL}; int rc = 0; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_current_perm = NULL; struct cil_tree_node *test_new_ast = NULL; struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; test_current_perm = NULL; cil_tree_node_init(&test_new_ast); test_new_ast->parent = test_ast_node; rc = cil_gen_perm(test_db, test_current_perm, test_new_ast); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_perm_astnull_neg(CuTest *tc) { char *line[] = {"(", "class", "foo", "(", "read", "write", "open", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); struct cil_class *new_node; cil_class_init(&new_node); struct cil_tree_node *new_tree_node; cil_tree_node_init(&new_tree_node); new_tree_node->data = new_node; new_tree_node->flavor = CIL_CLASS; int rc = cil_gen_perm(test_db, test_tree->root->cl_head->cl_head->next->next->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_perm_nodenull_neg(CuTest *tc) { char *line[] = {"(", "class", "file", "(", "read", "write", "open", ")", ")", NULL}; int rc = 0; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_current_perm = NULL; struct cil_tree_node *test_new_ast = NULL; struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); test_current_perm = test_tree->root->cl_head->cl_head->next->next->cl_head; cil_tree_node_init(&test_new_ast); test_new_ast->parent = test_ast_node; test_new_ast->line = test_current_perm->line; rc = cil_gen_perm(test_db, test_current_perm, test_new_ast); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_permset(CuTest *tc) { char *line[] = {"(", "permissionset", "foo", "(", "read", "write", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_permset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_permset_noname_neg(CuTest *tc) { char *line[] = {"(", "permissionset", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_permset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_permset_nameinparens_neg(CuTest *tc) { char *line[] = {"(", "permissionset", "(", "foo", ")", "(", "read", "write", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_permset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_permset_noperms_neg(CuTest *tc) { char *line[] = {"(", "permissionset", "foo", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_permset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_permset_emptyperms_neg(CuTest *tc) { char *line[] = {"(", "permissionset", "foo", "(", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_permset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_permset_extra_neg(CuTest *tc) { char *line[] = {"(", "permissionset", "foo", "(", "read", "write", ")", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_permset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_permset_dbnull_neg(CuTest *tc) { char *line[] = {"(", "permissionset", "foo", "(", "read", "write", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_permset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_permset_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_permset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_permset_astnull_neg(CuTest *tc) { char *line[] = {"(", "permissionset", "foo", "(", "read", "write", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_permset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_perm_nodes(CuTest *tc) { char *line[] = {"(", "class", "file", "(", "read", "write", "open", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); char *test_key = test_tree->root->cl_head->cl_head->next->data; struct cil_class *test_cls; cil_class_init(&test_cls); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_symtab_insert(&test_db->symtab[CIL_SYM_CLASSES], (hashtab_key_t)test_key, (struct cil_symtab_datum*)test_cls, test_ast_node); test_ast_node->data = test_cls; test_ast_node->flavor = CIL_CLASS; int rc = cil_gen_perm_nodes(test_db, test_tree->root->cl_head->cl_head->next->next->cl_head, test_ast_node, CIL_PERM); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_perm_nodes_failgen_neg(CuTest *tc) { char *line[] = {"(", "class", "file", "(", "read", "write", "open", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); char *test_key = test_tree->root->cl_head->cl_head->next->data; struct cil_class *test_cls; cil_class_init(&test_cls); cil_symtab_destroy(&test_cls->perms); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_symtab_insert(&test_db->symtab[CIL_SYM_CLASSES], (hashtab_key_t)test_key, (struct cil_symtab_datum*)test_cls, test_ast_node); test_ast_node->data = test_cls; test_ast_node->flavor = CIL_CLASS; int rc = cil_gen_perm_nodes(test_db, test_tree->root->cl_head->cl_head->next->next->cl_head, test_ast_node, CIL_PERM); CuAssertIntEquals(tc, SEPOL_ENOMEM, rc); } void test_cil_gen_perm_nodes_inval_perm_neg(CuTest *tc) { char *line[] = {"(", "class", "file", "(", "read", "(", "write", "open", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); char *test_key = test_tree->root->cl_head->cl_head->next->data; struct cil_class *test_cls; cil_class_init(&test_cls); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_symtab_insert(&test_db->symtab[CIL_SYM_CLASSES], (hashtab_key_t)test_key, (struct cil_symtab_datum*)test_cls, test_ast_node); test_ast_node->data = test_cls; test_ast_node->flavor = CIL_CLASS; int rc = cil_gen_perm_nodes(test_db, test_tree->root->cl_head->cl_head->next->next->cl_head, test_ast_node, CIL_PERM); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_fill_permset(CuTest *tc) { char *line[] = {"(", "permissionset", "foo", "(", "read", "write", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_permset *permset; cil_permset_init(&permset); int rc = cil_fill_permset(test_tree->root->cl_head->cl_head->next->next->cl_head, permset); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_fill_permset_sublist_neg(CuTest *tc) { char *line[] = {"(", "permissionset", "foo", "(", "read", "(", "write", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_permset *permset; cil_permset_init(&permset); int rc = cil_fill_permset(test_tree->root->cl_head->cl_head->next->next->cl_head, permset); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_fill_permset_startpermnull_neg(CuTest *tc) { char *line[] = {"(", "permissionset", "foo", "(", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_permset *permset; cil_permset_init(&permset); int rc = cil_fill_permset(test_tree->root->cl_head->cl_head->next->next->cl_head, permset); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_fill_permset_permsetnull_neg(CuTest *tc) { char *line[] = {"(", "permissionset", "foo", "(", "read", "write", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_permset *permset = NULL; int rc = cil_fill_permset(test_tree->root->cl_head->cl_head->next->next->cl_head, permset); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_in(CuTest *tc) { char *line[] = {"(", "in", "foo", "(", "allow", "test", "baz", "(", "char", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_in(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_in_blockstrnull_neg(CuTest *tc) { char *line[] = {"(", "in", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_in(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_in_extra_neg(CuTest *tc) { char *line[] = {"(", "in", "foo", "(", "allow", "test", "baz", "(", "char", "(", "read", ")", ")", ")", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_in(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_in_dbnull_neg(CuTest *tc) { char *line[] = {"(", "in", "foo", "(", "allow", "test", "baz", "(", "char", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_in(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_in_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_in(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_in_astnull_neg(CuTest *tc) { char *line[] = {"(", "in", "foo", "(", "allow", "test", "baz", "(", "char", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_in(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_class(CuTest *tc) { char *line[] = {"(", "class", "file", "(", "read", "write", "open", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_class(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertPtrNotNull(tc, test_ast_node->cl_tail); CuAssertPtrNotNull(tc, test_ast_node->data); CuAssertIntEquals(tc, test_ast_node->flavor, CIL_CLASS); } void test_cil_gen_class_noname_neg(CuTest *tc) { char *line[] = {"(", "class", "(", "read", "write", "open", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_class(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_class_nodenull_neg(CuTest *tc) { char *line[] = {"(", "class", "(", "read", "write", "open", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_class(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_class_dbnull_neg(CuTest *tc) { char *line[] = {"(", "class", "(", "read", "write", "open", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_class(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_class_currnull_neg(CuTest *tc) { char *line[] = {"(", "class", "(", "read", "write", "open", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_tree->root->cl_head->cl_head = NULL; int rc = cil_gen_class(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_class_noclass_neg(CuTest *tc) { char *line[] = {"(", "test", "read", "write", "open", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_class(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_class_noclassname_neg(CuTest *tc) { char *line[] = {"(", "class", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_class(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_class_namesublist_neg(CuTest *tc) { char *line[] = {"(", "class", "(", "foo", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_class(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_class_noperms(CuTest *tc) { char *line[] = {"(", "class", "foo", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_class(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_class_permsnotinlist_neg(CuTest *tc) { char *line[] = {"(", "class", "foo", "read", "write", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_class(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_class_extrapermlist_neg(CuTest *tc) { char *line[] = {"(", "class", "foo", "(", "read", ")", "(", "write", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_class(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_class_listinlist_neg(CuTest *tc) { char *line[] = {"(", "class", "test", "(", "read", "(", "write", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_class(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_fill_classpermset_anonperms(CuTest *tc) { char *line[] = {"(", "classpermissionset", "char_w", "(", "char", "(", "write", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_classpermset *cps; cil_classpermset_init(&cps); int rc = cil_fill_classpermset(test_tree->root->cl_head->cl_head->next->next->cl_head, cps); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_fill_classpermset_anonperms_neg(CuTest *tc) { char *line[] = {"(", "classpermissionset", "char_w", "(", "char", "(", "write", "(", "extra", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_classpermset *cps; cil_classpermset_init(&cps); int rc = cil_fill_classpermset(test_tree->root->cl_head->cl_head->next->next->cl_head, cps); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_fill_classpermset_namedperms(CuTest *tc) { char *line[] = {"(", "classpermissionset", "char_w", "(", "char", "perms", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_classpermset *cps; cil_classpermset_init(&cps); int rc = cil_fill_classpermset(test_tree->root->cl_head->cl_head->next->next->cl_head, cps); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_fill_classpermset_extra_neg(CuTest *tc) { char *line[] = {"(", "classpermissionset", "char_w", "(", "char", "(", "write", ")", "extra", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_classpermset *cps; cil_classpermset_init(&cps); int rc = cil_fill_classpermset(test_tree->root->cl_head->cl_head->next->next->cl_head, cps); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_fill_classpermset_emptypermslist_neg(CuTest *tc) { char *line[] = {"(", "classpermissionset", "char_w", "(", "char", "(", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_classpermset *cps; cil_classpermset_init(&cps); int rc = cil_fill_classpermset(test_tree->root->cl_head->cl_head->next->next->cl_head, cps); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_fill_classpermset_noperms_neg(CuTest *tc) { char *line[] = {"(", "classpermissionset", "char_w", "(", "char", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_classpermset *cps; cil_classpermset_init(&cps); int rc = cil_fill_classpermset(test_tree->root->cl_head->cl_head->next->next->cl_head, cps); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_fill_classpermset_noclass_neg(CuTest *tc) { char *line[] = {"(", "classpermissionset", "char_w", "(", "(", "write", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_classpermset *cps; cil_classpermset_init(&cps); int rc = cil_fill_classpermset(test_tree->root->cl_head->cl_head->next->next->cl_head, cps); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_fill_classpermset_classnodenull_neg(CuTest *tc) { char *line[] = {"(", "classpermissionset", "char_w", "(", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_classpermset *cps; cil_classpermset_init(&cps); int rc = cil_fill_classpermset(test_tree->root->cl_head->cl_head->next->next->cl_head, cps); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_fill_classpermset_cpsnull_neg(CuTest *tc) { char *line[] = {"(", "classpermissionset", "char_w", "(", "char", "(", "read", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_classpermset *cps = NULL; int rc = cil_fill_classpermset(test_tree->root->cl_head->cl_head->next->next->cl_head, cps); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_classpermset(CuTest *tc) { char *line[] = {"(", "classpermissionset", "char_w", "(", "char", "(", "write", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_classpermset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_classpermset_noname_neg(CuTest *tc) { char *line[] = {"(", "classpermissionset", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_classpermset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_classpermset_nameinparens_neg(CuTest *tc) { char *line[] = {"(", "classpermissionset", "(", "foo", ")", "(", "read", "(", "write", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_classpermset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_classpermset_noclass_neg(CuTest *tc) { char *line[] = {"(", "classpermissionset", "foo", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_classpermset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_classpermset_noperms_neg(CuTest *tc) { char *line[] = {"(", "classpermissionset", "foo", "(", "char", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_classpermset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_classpermset_emptyperms_neg(CuTest *tc) { char *line[] = {"(", "classpermissionset", "foo", "(", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_classpermset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_classpermset_extra_neg(CuTest *tc) { char *line[] = {"(", "classpermissionset", "foo", "(", "read", "(", "write", ")", ")", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_classpermset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_classpermset_dbnull_neg(CuTest *tc) { char *line[] = {"(", "classpermissionset", "foo", "(", "read", "(", "write", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_classpermset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_classpermset_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_classpermset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_classpermset_astnull_neg(CuTest *tc) { char *line[] = {"(", "classpermissionset", "foo", "(", "read", "(", "write", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_classpermset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_classmap_perm(CuTest *tc) { char *line[] = {"(", "classmap", "files", "(", "read", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_classmap *map = NULL; cil_classmap_init(&map); test_ast_node->flavor = CIL_CLASSMAP; test_ast_node->data = map; struct cil_tree_node *test_ast_node_a; cil_tree_node_init(&test_ast_node_a); test_ast_node_a->parent = test_ast_node; test_ast_node_a->line = test_tree->root->cl_head->cl_head->next->next->cl_head->line; test_ast_node_a->path = test_tree->root->cl_head->cl_head->next->next->cl_head->path; int rc = cil_gen_classmap_perm(test_db, test_tree->root->cl_head->cl_head->next->next->cl_head, test_ast_node_a); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_classmap_perm_dupeperm_neg(CuTest *tc) { char *line[] = {"(", "classmap", "files", "(", "read", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_classmap(test_db, test_tree->root->cl_head->cl_head, test_ast_node); struct cil_tree_node *test_ast_node_a; cil_tree_node_init(&test_ast_node_a); test_ast_node_a->parent = test_ast_node; test_ast_node_a->line = test_tree->root->cl_head->cl_head->next->next->cl_head->line; test_ast_node_a->path = test_tree->root->cl_head->cl_head->next->next->cl_head->path; int rc = cil_gen_classmap_perm(test_db, test_tree->root->cl_head->cl_head->next->next->cl_head, test_ast_node_a); CuAssertIntEquals(tc, SEPOL_EEXIST, rc); } void test_cil_gen_classmap_perm_dbnull_neg(CuTest *tc) { char *line[] = {"(", "classmap", "files", "(", "read", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_classmap(test_db, test_tree->root->cl_head->cl_head, test_ast_node); struct cil_tree_node *test_ast_node_a; cil_tree_node_init(&test_ast_node_a); test_ast_node_a->parent = test_ast_node; test_ast_node_a->line = test_tree->root->cl_head->cl_head->line; test_ast_node_a->path = test_tree->root->cl_head->cl_head->path; test_db = NULL; int rc = cil_gen_classmap_perm(test_db, test_tree->root->cl_head->cl_head->next->next->cl_head, test_ast_node_a); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_classmap_perm_currnull_neg(CuTest *tc) { char *line[] = {"(", "classmap", "files", "(", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_classmap(test_db, test_tree->root->cl_head->cl_head, test_ast_node); struct cil_tree_node *test_ast_node_a; cil_tree_node_init(&test_ast_node_a); test_ast_node_a->parent = test_ast_node; test_ast_node_a->line = test_tree->root->cl_head->cl_head->line; test_ast_node_a->path = test_tree->root->cl_head->cl_head->path; int rc = cil_gen_classmap_perm(test_db, test_tree->root->cl_head->cl_head->next->next->cl_head, test_ast_node_a); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_classmap_perm_astnull_neg(CuTest *tc) { char *line[] = {"(", "classmap", "files", "(", "read", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_classmap(test_db, test_tree->root->cl_head->cl_head, test_ast_node); struct cil_tree_node *test_ast_node_a = NULL; int rc = cil_gen_classmap_perm(test_db, test_tree->root->cl_head->cl_head->next->next->cl_head, test_ast_node_a); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_classmap(CuTest *tc) { char *line[] = {"(", "classmap", "files", "(", "read", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_classmap(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_classmap_extra_neg(CuTest *tc) { char *line[] = {"(", "classmap", "files", "(", "read", ")", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_classmap(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_classmap_noname_neg(CuTest *tc) { char *line[] = {"(", "classmap", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_classmap(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_classmap_emptyperms_neg(CuTest *tc) { char *line[] = {"(", "classmap", "files", "(", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_classmap(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_classmap_dbnull_neg(CuTest *tc) { char *line[] = {"(", "classmap", "files", "(", "read", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_classmap(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_classmap_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_classmap(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_classmap_astnull_neg(CuTest *tc) { char *line[] = {"(", "classmap", "files", "(", "read", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_classmap(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_classmapping_anonpermset(CuTest *tc) { char *line[] = {"(", "classmapping", "files", "read", "(", "file", "(", "open", "read", "getattr", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_classmapping(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_classmapping_anonpermset_neg(CuTest *tc) { char *line[] = {"(", "classmapping", "files", "read", "(", "file", "(", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_classmapping(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_classmapping_namedpermset(CuTest *tc) { char *line[] = {"(", "classmapping", "files", "read", "char_w", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_classmapping(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_classmapping_noclassmapname_neg(CuTest *tc) { char *line[] = {"(", "classmapping", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_classmapping(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_classmapping_noclassmapperm_neg(CuTest *tc) { char *line[] = {"(", "classmapping", "files", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_classmapping(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_classmapping_nopermissionsets_neg(CuTest *tc) { char *line[] = {"(", "classmapping", "files", "read", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_classmapping(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_classmapping_dbnull_neg(CuTest *tc) { char *line[] = {"(", "classmapping", "files", "read", "(", "file", "(", "open", "read", "getattr", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_classmapping(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_classmapping_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_classmapping(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_classmapping_astnull_neg(CuTest *tc) { char *line[] = {"(", "classmapping", "files", "read", "(", "file", "(", "open", "read", "getattr", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_classmapping(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_common(CuTest *tc) { char *line[] = {"(", "common", "test", "(", "read", "write", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_common(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertPtrNotNull(tc, test_ast_node->data); CuAssertIntEquals(tc, test_ast_node->flavor, CIL_COMMON); } void test_cil_gen_common_dbnull_neg(CuTest *tc) { char *line[] = {"(", "common", "test", "(", "read", "write", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_common(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_common_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_common(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_common_astnull_neg(CuTest *tc) { char *line[] = {"(", "common", "test", "(", "read", "write", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_common(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_common_noname_neg(CuTest *tc) { char *line[] = {"(", "common", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_common(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_common_twoperms_neg(CuTest *tc) { char *line[] = {"(", "common", "foo", "(", "write", ")", "(", "read", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_common(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_common_permsublist_neg(CuTest *tc) { char *line[] = {"(", "common", "test", "(", "read", "(", "write", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_common(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_common_noperms_neg(CuTest *tc) { char *line[] = {"(", "common", "test", "(", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_common(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_sid(CuTest *tc) { char *line[] = {"(", "sid", "foo", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_sid(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_sid_noname_neg(CuTest *tc) { char *line[] = {"(", "sid", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_sid(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_sid_nameinparens_neg(CuTest *tc) { char *line[] = {"(", "sid", "(", "foo", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_sid(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_sid_extra_neg(CuTest *tc) { char *line[] = {"(", "sid", "foo", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_sid(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_sid_dbnull_neg(CuTest *tc) { char *line[] = {"(", "sid", "foo", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_sid(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_sid_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_sid(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_sid_astnull_neg(CuTest *tc) { char *line[] = {"(", "sid", "foo", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_sid(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_sidcontext(CuTest *tc) { char *line[] = {"(", "sidcontext", "test", "(", "blah", "blah", "blah", "(", "(", "s0", "(", "c0", ")", ")", "(", "s0", "(", "c0", ")", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_sidcontext(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertPtrNotNull(tc, test_ast_node->data); CuAssertIntEquals(tc, test_ast_node->flavor, CIL_SIDCONTEXT); } void test_cil_gen_sidcontext_namedcontext(CuTest *tc) { char *line[] = {"(", "sidcontext", "test", "something", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_sidcontext(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertPtrNotNull(tc, test_ast_node->data); CuAssertIntEquals(tc, test_ast_node->flavor, CIL_SIDCONTEXT); } void test_cil_gen_sidcontext_halfcontext_neg(CuTest *tc) { char *line[] = {"(", "sidcontext", "test", "(", "blah", "blah", "blah", "(", "(", "s0", "(", "c0", ")", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_sidcontext(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_sidcontext_noname_neg(CuTest *tc) { char *line[] = {"(", "sidcontext", "(", "blah", "blah", "blah", "(", "s0", "(", "c0", ")", ")", "(", "s0", "(", "c0", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_sidcontext(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_sidcontext_empty_neg(CuTest *tc) { char *line[] = {"(", "sidcontext", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_sidcontext(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_sidcontext_nocontext_neg(CuTest *tc) { char *line[] = {"(", "sidcontext", "test", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_sidcontext(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_sidcontext_dblname_neg(CuTest *tc) { char *line[] = {"(", "sidcontext", "test", "test2", "(", "blah", "blah", "blah", "(", "s0", "(", "c0", ")", ")", "(", "s0", "(", "c0", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_sidcontext(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_sidcontext_dbnull_neg(CuTest *tc) { char *line[] = {"(", "sidcontext", "test", "(", "blah", "blah", "blah", "(", "s0", "(", "c0", ")", ")", "(", "s0", "(", "c0", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_sidcontext(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_sidcontext_pcurrnull_neg(CuTest *tc) { struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_sidcontext(test_db, NULL, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_sidcontext_astnodenull_neg(CuTest *tc) { char *line[] = {"(", "sidcontext", "test", "(", "blah", "blah", "blah", "(", "s0", "(", "c0", ")", ")", "(", "s0", "(", "c0", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_sidcontext(test_db, test_tree->root->cl_head->cl_head, NULL); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_type(CuTest *tc) { char *line[] = {"(", "type", "test", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_type(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertPtrNotNull(tc, test_ast_node->data); CuAssertIntEquals(tc, test_ast_node->flavor, CIL_TYPE); } void test_cil_gen_type_dbnull_neg(CuTest *tc) { char *line[] = {"(", "type", "test", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_type(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_type_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_type(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_type_astnull_neg(CuTest *tc) { char *line[] = {"(", "type", "test", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_type(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_type_extra_neg(CuTest *tc) { char *line[] = {"(", "type", "foo", "bar," ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_type(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_typeattribute(CuTest *tc) { char *line[] = {"(", "typeattribute", "test", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_typeattribute(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertPtrNotNull(tc, test_ast_node->data); CuAssertIntEquals(tc, test_ast_node->flavor, CIL_TYPEATTRIBUTE); } void test_cil_gen_typeattribute_dbnull_neg(CuTest *tc) { char *line[] = {"(", "typeattribute", "test", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_typeattribute(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_typeattribute_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_typeattribute(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_typeattribute_astnull_neg(CuTest *tc) { char *line[] = {"(", "typeattribute", "test", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_typeattribute(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_typeattribute_extra_neg(CuTest *tc) { char *line[] = {"(", "typeattribute", "foo", "bar," ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_typeattribute(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_typebounds(CuTest *tc) { char *line[] = {"(", "typebounds", "type_a", "type_b", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_typebounds(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_typebounds_notype1_neg(CuTest *tc) { char *line[] = {"(", "typebounds", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_typebounds(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_typebounds_type1inparens_neg(CuTest *tc) { char *line[] = {"(", "typebounds", "(", "type_a", ")", "type_b", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_typebounds(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_typebounds_notype2_neg(CuTest *tc) { char *line[] = {"(", "typebounds", "type_a", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_typebounds(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_typebounds_type2inparens_neg(CuTest *tc) { char *line[] = {"(", "typebounds", "type_a", "(", "type_b", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_typebounds(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_typebounds_extra_neg(CuTest *tc) { char *line[] = {"(", "typebounds", "type_a", "type_b", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_typebounds(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_typebounds_dbnull_neg(CuTest *tc) { char *line[] = {"(", "typebounds", "type_a", "type_b", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_typebounds(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_typebounds_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_typebounds(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_typebounds_astnull_neg(CuTest *tc) { char *line[] = {"(", "typebounds", "type_a", "type_b", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_typebounds(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_typepermissive(CuTest *tc) { char *line[] = {"(", "typepermissive", "type_a", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_typepermissive(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_typepermissive_noname_neg(CuTest *tc) { char *line[] = {"(", "typepermissive", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_typepermissive(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_typepermissive_typeinparens_neg(CuTest *tc) { char *line[] = {"(", "typepermissive", "(", "type_a", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_typepermissive(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_typepermissive_extra_neg(CuTest *tc) { char *line[] = {"(", "typepermissive", "type_a", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_typepermissive(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_typepermissive_dbnull_neg(CuTest *tc) { char *line[] = {"(", "typepermissive", "type_a", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_typepermissive(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_typepermissive_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_typepermissive(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_typepermissive_astnull_neg(CuTest *tc) { char *line[] = {"(", "typepermissive", "type_a", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_typepermissive(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_nametypetransition(CuTest *tc) { char *line[] = {"(", "nametypetransition", "str", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_nametypetransition(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_nametypetransition_strinparens_neg(CuTest *tc) { char *line[] = {"(", "nametypetransition", "(", "str", ")", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_nametypetransition(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_nametypetransition_nostr_neg(CuTest *tc) { char *line[] = {"(", "nametypetransition", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_nametypetransition(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_nametypetransition_srcinparens_neg(CuTest *tc) { char *line[] = {"(", "nametypetransition", "str", "(", "foo", ")", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_nametypetransition(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_nametypetransition_nosrc_neg(CuTest *tc) { char *line[] = {"(", "nametypetransition", "str", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_nametypetransition(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_nametypetransition_tgtinparens_neg(CuTest *tc) { char *line[] = {"(", "nametypetransition", "str", "foo", "(", "bar", ")", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_nametypetransition(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_nametypetransition_notgt_neg(CuTest *tc) { char *line[] = {"(", "nametypetransition", "str", "foo", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_nametypetransition(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_nametypetransition_classinparens_neg(CuTest *tc) { char *line[] = {"(", "nametypetransition", "str", "foo", "bar", "(", "file", ")", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_nametypetransition(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_nametypetransition_noclass_neg(CuTest *tc) { char *line[] = {"(", "nametypetransition", "str", "foo", "bar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_nametypetransition(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_nametypetransition_destinparens_neg(CuTest *tc) { char *line[] = {"(", "nametypetransition", "str", "foo", "bar", "file", "(", "foobar", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_nametypetransition(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_nametypetransition_nodest_neg(CuTest *tc) { char *line[] = {"(", "nametypetransition", "str", "foo", "bar", "file", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_nametypetransition(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_nametypetransition_extra_neg(CuTest *tc) { char *line[] = {"(", "nametypetransition", "str", "foo", "bar", "file", "foobar", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_nametypetransition(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_nametypetransition_dbnull_neg(CuTest *tc) { char *line[] = {"(", "nametypetransition", "str", "foo", "bar", "file", "foobar", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_nametypetransition(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_nametypetransition_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_nametypetransition(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_nametypetransition_astnull_neg(CuTest *tc) { char *line[] = {"(", "nametypetransition", "str", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_nametypetransition(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_rangetransition(CuTest *tc) { char *line[] = {"(", "rangetransition", "type_a_t", "type_b_t", "class", "(", "low_l", "high_l", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_rangetransition(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_rangetransition_namedtransition(CuTest *tc) { char *line[] = {"(", "rangetransition", "type_a_t", "type_b_t", "class", "namedtrans", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_rangetransition(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_rangetransition_anon_low_l(CuTest *tc) { char *line[] = {"(", "rangetransition", "type_a_t", "type_b_t", "class", "(", "(", "s0", "(", "c0", ")", ")", "high_l", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_rangetransition(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_rangetransition_anon_low_l_neg(CuTest *tc) { char *line[] = {"(", "rangetransition", "type_a_t", "type_b_t", "class", "(", "(", "s0", "(", ")", ")", "high_l", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_rangetransition(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_rangetransition_anon_high_l(CuTest *tc) { char *line[] = {"(", "rangetransition", "type_a_t", "type_b_t", "class", "(", "low_l", "(", "s0", "(", "c0", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_rangetransition(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_rangetransition_anon_high_l_neg(CuTest *tc) { char *line[] = {"(", "rangetransition", "type_a_t", "type_b_t", "class", "(", "low_l", "(", "s0", "(", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_rangetransition(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_rangetransition_dbnull_neg(CuTest *tc) { char *line[] = {"(", "rangetransition", "type_a_t", "type_b_t", "class", "(", "low_l", "high_l", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_rangetransition(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_rangetransition_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_rangetransition(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_rangetransition_astnull_neg(CuTest *tc) { char *line[] = {"(", "rangetransition", "type_a_t", "type_b_t", "class", "(", "low_l", "high_l", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_rangetransition(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_rangetransition_nofirsttype_neg(CuTest *tc) { char *line[] = {"(", "rangetransition", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_rangetransition(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_rangetransition_firsttype_inparens_neg(CuTest *tc) { char *line[] = {"(", "rangetransition", "(", "type_a_t", ")", "type_b_t", "class", "(", "low_l", "high_l", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_rangetransition(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_rangetransition_nosecondtype_neg(CuTest *tc) { char *line[] = {"(", "rangetransition", "type_a_t", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_rangetransition(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_rangetransition_secondtype_inparens_neg(CuTest *tc) { char *line[] = {"(", "rangetransition", "type_a_t", "(", "type_b_t", ")", "class", "(", "low_l", "high_l", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_rangetransition(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_rangetransition_noclass_neg(CuTest *tc) { char *line[] = {"(", "rangetransition", "type_a_t", "type_b_t", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_rangetransition(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_rangetransition_class_inparens_neg(CuTest *tc) { char *line[] = {"(", "rangetransition", "type_a_t", "type_b_t", "(", "class", ")", "(", "low_l", "high_l", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_rangetransition(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_rangetransition_nolevel_l_neg(CuTest *tc) { char *line[] = {"(", "rangetransition", "type_a_t", "type_b_t", "class", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_rangetransition(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_rangetransition_nolevel_h_neg(CuTest *tc) { char *line[] = {"(", "rangetransition", "type_a_t", "type_b_t", "class", "(", "low_l", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_rangetransition(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_rangetransition_extra_neg(CuTest *tc) { char *line[] = {"(", "rangetransition", "type_a_t", "type_b_t", "class", "(", "low_l", "high_l", ")", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_rangetransition(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_expr_stack_and(CuTest *tc) { char *line[] = {"(", "booleanif", "(", "and", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "baz", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_booleanif *bif; cil_boolif_init(&bif); int rc = cil_gen_expr_stack(test_tree->root->cl_head->cl_head->next, CIL_BOOL, &bif->expr_stack); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_expr_stack_or(CuTest *tc) { char *line[] = {"(", "booleanif", "(", "or", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "baz", "(", "read", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_booleanif *bif; cil_boolif_init(&bif); int rc = cil_gen_expr_stack(test_tree->root->cl_head->cl_head->next, CIL_BOOL, &bif->expr_stack); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_expr_stack_xor(CuTest *tc) { char *line[] = {"(", "booleanif", "(", "xor", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "baz", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_booleanif *bif; cil_boolif_init(&bif); int rc = cil_gen_expr_stack(test_tree->root->cl_head->cl_head->next, CIL_BOOL, &bif->expr_stack); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_expr_stack_not(CuTest *tc) { char *line[] = {"(", "booleanif", "(", "not", "foo", ")", "(", "true", "(", "allow", "foo", "bar", "baz", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_booleanif *bif; cil_boolif_init(&bif); int rc = cil_gen_expr_stack(test_tree->root->cl_head->cl_head->next, CIL_BOOL, &bif->expr_stack); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_expr_stack_not_noexpr_neg(CuTest *tc) { char *line[] = {"(", "booleanif", "(", "not", ")", "(", "true", "(", "allow", "foo", "bar", "baz", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_booleanif *bif; cil_boolif_init(&bif); int rc = cil_gen_expr_stack(test_tree->root->cl_head->cl_head->next, CIL_BOOL, &bif->expr_stack); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_expr_stack_not_extraexpr_neg(CuTest *tc) { char *line[] = {"(", "booleanif", "(", "not", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "baz", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_booleanif *bif; cil_boolif_init(&bif); int rc = cil_gen_expr_stack(test_tree->root->cl_head->cl_head->next, CIL_BOOL, &bif->expr_stack); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_expr_stack_eq(CuTest *tc) { char *line[] = {"(", "booleanif", "(", "eq", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "baz", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_booleanif *bif; cil_boolif_init(&bif); int rc = cil_gen_expr_stack(test_tree->root->cl_head->cl_head->next, CIL_BOOL, &bif->expr_stack); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_expr_stack_neq(CuTest *tc) { char *line[] = {"(", "booleanif", "(", "neq", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "baz", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_booleanif *bif; cil_boolif_init(&bif); int rc = cil_gen_expr_stack(test_tree->root->cl_head->cl_head->next, CIL_BOOL, &bif->expr_stack); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_expr_stack_nested(CuTest *tc) { char *line[] = {"(", "booleanif", "(", "or", "(","neq", "foo", "bar", ")", "(", "eq", "baz", "boo", ")", ")", "(", "true", "(", "allow", "foo", "bar", "baz", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_booleanif *bif; cil_boolif_init(&bif); int rc = cil_gen_expr_stack(test_tree->root->cl_head->cl_head->next, CIL_BOOL, &bif->expr_stack); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_expr_stack_nested_neg(CuTest *tc) { char *line[] = {"(", "booleanif", "(", "(","neq", "foo", "bar", ")", ")", "(", "true", "(", "allow", "foo", "bar", "baz", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_booleanif *bif; cil_boolif_init(&bif); int rc = cil_gen_expr_stack(test_tree->root->cl_head->cl_head->next, CIL_BOOL, &bif->expr_stack); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_expr_stack_nested_emptyargs_neg(CuTest *tc) { char *line[] = {"(", "booleanif", "(", "eq", "(", ")", "(", ")", ")", "(", "true", "(", "allow", "foo", "bar", "baz", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_booleanif *bif; cil_boolif_init(&bif); int rc = cil_gen_expr_stack(test_tree->root->cl_head->cl_head->next, CIL_BOOL, &bif->expr_stack); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_expr_stack_nested_missingoperator_neg(CuTest *tc) { char *line[] = {"(", "booleanif", "(", "or", "(","foo", "bar", ")", "(", "eq", "baz", "boo", ")", ")", "(", "true", "(", "allow", "foo", "bar", "baz", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_booleanif *bif; cil_boolif_init(&bif); int rc = cil_gen_expr_stack(test_tree->root->cl_head->cl_head->next, CIL_BOOL, &bif->expr_stack); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_expr_stack_arg1null_neg(CuTest *tc) { char *line[] = {"(", "booleanif", "(", "eq", ")", "(", "true", "(", "allow", "foo", "bar", "baz", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_booleanif *bif; cil_boolif_init(&bif); int rc = cil_gen_expr_stack(test_tree->root->cl_head->cl_head->next, CIL_BOOL, &bif->expr_stack); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_expr_stack_arg2null_neg(CuTest *tc) { char *line[] = {"(", "booleanif", "(", "eq", "foo", ")", "(", "true", "(", "allow", "foo", "bar", "baz", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_booleanif *bif; cil_boolif_init(&bif); int rc = cil_gen_expr_stack(test_tree->root->cl_head->cl_head->next, CIL_BOOL, &bif->expr_stack); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_expr_stack_extraarg_neg(CuTest *tc) { char *line[] = {"(", "booleanif", "(", "eq", "foo", "bar", "extra", ")", "(", "true", "(", "allow", "foo", "bar", "baz", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_booleanif *bif; cil_boolif_init(&bif); int rc = cil_gen_expr_stack(test_tree->root->cl_head->cl_head->next, CIL_BOOL, &bif->expr_stack); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_expr_stack_currnull_neg(CuTest *tc) { char *line[] = {"(", "booleanif", "(", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_booleanif *bif; cil_boolif_init(&bif); int rc = cil_gen_expr_stack(test_tree->root->cl_head->cl_head->next, CIL_BOOL, &bif->expr_stack); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_expr_stack_stacknull_neg(CuTest *tc) { char *line[] = {"(", "booleanif", "(", "xor", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_expr_stack(test_tree->root->cl_head->cl_head->next, CIL_BOOL, NULL); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_boolif_multiplebools_true(CuTest *tc) { char *line[] = {"(", "booleanif", "(", "and", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "(", "read", ")", ")", ")", "(", "true", "(", "allow", "foo", "bar", "(", "write", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_boolif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_boolif_multiplebools_false(CuTest *tc) { char *line[] = {"(", "booleanif", "(", "and", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "(", "read", ")", ")", ")", "(", "false", "(", "allow", "foo", "bar", "(", "write", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_boolif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_boolif_multiplebools_unknowncond_neg(CuTest *tc) { char *line[] = {"(", "booleanif", "(", "and", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "(", "read", ")", ")", ")", "(", "dne", "(", "allow", "foo", "bar", "(", "write", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_boolif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_boolif_true(CuTest *tc) { char *line[] = {"(", "booleanif", "(", "and", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_boolif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_boolif_false(CuTest *tc) { char *line[] = {"(", "booleanif", "(", "and", "foo", "bar", ")", "(", "false", "(", "allow", "foo", "bar", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_boolif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_boolif_unknowncond_neg(CuTest *tc) { char *line[] = {"(", "booleanif", "(", "and", "foo", "bar", ")", "(", "dne", "(", "allow", "foo", "bar", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_boolif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_boolif_nested(CuTest *tc) { char *line[] = {"(", "booleanif", "(", "and", "(", "or", "foo", "bar", ")", "baz", ")", "(", "true", "(", "allow", "foo", "baz", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_boolif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_boolif_nested_neg(CuTest *tc) { char *line[] = {"(", "booleanif", "(", "(", "or", "foo", "bar", ")", "baz", ")", "(", "true", "(", "allow", "foo", "baz", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_boolif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_boolif_extra_neg(CuTest *tc) { char *line[] = {"(", "booleanif", "(", "and", "(", "or", "foo", "bar", ")", "baz", "beef", ")", "(", "true", "(", "allow", "foo", "baz", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_boolif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_boolif_extra_parens_neg(CuTest *tc) { char *line[] = {"(", "booleanif", "(", "(", "or", "foo", "bar", ")", ")", "(", "true", "(", "allow", "foo", "baz", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_boolif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_boolif_nocond(CuTest *tc) { char *line[] = {"(", "booleanif", "baz", "(", "true", "(", "allow", "foo", "bar", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_boolif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_boolif_neg(CuTest *tc) { char *line[] = {"(", "booleanif", "(", "**", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_boolif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_boolif_dbnull_neg(CuTest *tc) { char *line[] = {"(", "booleanif", "(", "and", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_boolif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_boolif_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_boolif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_boolif_astnull_neg(CuTest *tc) { char *line[] = {"(", "booleanif", "(", "and", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_boolif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_boolif_nocond_neg(CuTest *tc) { char *line[] = {"(", "booleanif", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_boolif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_boolif_notruelist_neg(CuTest *tc) { char *line[] = {"(", "booleanif", "(", "and", "foo", "bar", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_boolif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_boolif_empty_cond_neg(CuTest *tc) { char *line[] = {"(", "booleanif", "(", ")", "(", "true", "(", "allow", "foo", "bar", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_boolif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_tunif_multiplebools_true(CuTest *tc) { char *line[] = {"(", "tunableif", "(", "and", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "(", "read", ")", ")", ")", "(", "true", "(", "allow", "foo", "bar", "(", "write", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_tunif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_tunif_multiplebools_false(CuTest *tc) { char *line[] = {"(", "tunableif", "(", "and", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "(", "read", ")", ")", ")", "(", "false", "(", "allow", "foo", "bar", "(", "write", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_tunif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_tunif_multiplebools_unknowncond_neg(CuTest *tc) { char *line[] = {"(", "tunableif", "(", "and", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "(", "read", ")", ")", ")", "(", "dne", "(", "allow", "foo", "bar", "(", "write", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_tunif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_tunif_true(CuTest *tc) { char *line[] = {"(", "tunableif", "(", "and", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_tunif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_tunif_false(CuTest *tc) { char *line[] = {"(", "tunableif", "(", "and", "foo", "bar", ")", "(", "false", "(", "allow", "foo", "bar", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_tunif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_tunif_unknowncond_neg(CuTest *tc) { char *line[] = {"(", "tunableif", "(", "and", "foo", "bar", ")", "(", "dne", "(", "allow", "foo", "bar", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_tunif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_tunif_nocond(CuTest *tc) { char *line[] = {"(", "tunableif", "baz", "(", "true", "(", "allow", "foo", "bar", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_tunif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_tunif_nested(CuTest *tc) { char *line[] = {"(", "tunableif", "(", "and", "(", "or", "foo", "bar", ")", "baz", ")", "(", "true", "(", "allow", "foo", "baz", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_tunif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_tunif_nested_neg(CuTest *tc) { char *line[] = {"(", "tunableif", "(", "(", "or", "foo", "bar", ")", "baz", ")", "(", "true", "(", "allow", "foo", "baz", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_tunif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_tunif_extra_neg(CuTest *tc) { char *line[] = {"(", "tunableif", "(", "and", "(", "or", "foo", "bar", ")", "baz", "beef", ")", "(", "true", "(", "allow", "foo", "baz", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_tunif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_tunif_extra_parens_neg(CuTest *tc) { char *line[] = {"(", "tunableif", "(", "(", "or", "foo", "bar", ")", ")", "(", "true", "(", "allow", "foo", "baz", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_tunif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_tunif_neg(CuTest *tc) { char *line[] = {"(", "tunableif", "(", "**", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_tunif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_tunif_dbnull_neg(CuTest *tc) { char *line[] = {"(", "tunableif", "(", "and", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_tunif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_tunif_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_tunif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_tunif_astnull_neg(CuTest *tc) { char *line[] = {"(", "tunableif", "(", "and", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_tunif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_tunif_nocond_neg(CuTest *tc) { char *line[] = {"(", "tunableif", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_tunif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_tunif_notruelist_neg(CuTest *tc) { char *line[] = {"(", "tunableif", "(", "and", "foo", "bar", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_tunif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_condblock_true(CuTest *tc) { char *line[] = {"(", "true", "(", "allow", "foo", "bar", "baz", "(", "read", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_condblock(test_db, test_tree->root->cl_head->cl_head, test_ast_node, CIL_CONDTRUE); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_condblock_false(CuTest *tc) { char *line[] = {"(", "false", "(", "allow", "foo", "bar", "baz", "(", "read", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_condblock(test_db, test_tree->root->cl_head->cl_head, test_ast_node, CIL_CONDFALSE); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_condblock_dbnull_neg(CuTest *tc) { char *line[] = {"(", "false", "(", "allow", "foo", "bar", "baz", "(", "read", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_condblock(test_db, test_tree->root->cl_head->cl_head, test_ast_node, CIL_CONDFALSE); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_condblock_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_condblock(test_db, test_tree->root->cl_head->cl_head, test_ast_node, CIL_CONDFALSE); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_condblock_astnull_neg(CuTest *tc) { char *line[] = {"(", "false", "(", "allow", "foo", "bar", "baz", "(", "read", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_condblock(test_db, test_tree->root->cl_head->cl_head, test_ast_node, CIL_CONDFALSE); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_condblock_nocond_neg(CuTest *tc) { char *line[] = {"(", "true", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_condblock(test_db, test_tree->root->cl_head->cl_head, test_ast_node, CIL_CONDTRUE); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_condblock_extra_neg(CuTest *tc) { char *line[] = {"(", "true", "(", "allow", "foo", "bar", "baz", "(", "read", ")", ")", "Extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_condblock(test_db, test_tree->root->cl_head->cl_head, test_ast_node, CIL_CONDTRUE); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_typealias(CuTest *tc) { char *line[] = {"(", "typealias", ".test.type", "type_t", ")", "(", "type", "test", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_typealias(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertPtrNotNull(tc, test_ast_node->data); CuAssertStrEquals(tc, ((struct cil_typealias*)test_ast_node->data)->type_str, test_tree->root->cl_head->cl_head->next->data); CuAssertIntEquals(tc, test_ast_node->flavor, CIL_TYPEALIAS); } void test_cil_gen_typealias_incomplete_neg(CuTest *tc) { char *line[] = {"(", "typealias", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_typealias(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_typealias_incomplete_neg2(CuTest *tc) { char *line[] = {"(", "typealias", ".test.type", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_typealias(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_typealias_extratype_neg(CuTest *tc) { char *line[] = {"(", "typealias", ".test.type", "foo", "extra_t", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_typealias(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_typealias_dbnull_neg(CuTest *tc) { char *line[] = {"(", "typealias", ".test.type", "type_t", ")", "(", "type", "test", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_typealias(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_typealias_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_typealias(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_typealias_astnull_neg(CuTest *tc) { char *line[] = {"(", "typealias", ".test.type", "type_t", ")", "(", "type", "test", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_typealias(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_typeattributeset(CuTest *tc) { char *line[] = {"(", "typeattributeset", "filetypes", "test_t", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_typeattributeset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertPtrNotNull(tc, test_ast_node->data); } void test_cil_gen_typeattributeset_and_two_types(CuTest *tc) { char *line[] = {"(", "typeattributeset", "filetypes", "(", "and", "test_t", "test2_t", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_typeattributeset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertPtrNotNull(tc, test_ast_node->data); } void test_cil_gen_typeattributeset_not(CuTest *tc) { char *line[] = {"(", "typeattributeset", "filetypes", "(", "not", "notypes_t", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_typeattributeset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertPtrNotNull(tc, test_ast_node->data); } void test_cil_gen_typeattributeset_exclude_attr(CuTest *tc) { char *line[] = {"(", "typeattributeset", "filetypes", "(", "not", "attr", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_typeattributeset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertPtrNotNull(tc, test_ast_node->data); } void test_cil_gen_typeattributeset_exclude_neg(CuTest *tc) { char *line[] = {"(", "typeattributeset", "filetypes", "(", "not", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_typeattributeset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_typeattributeset_dbnull_neg(CuTest *tc) { char *line[] = {"(", "typeattributeset", "filetypes", "(", "not", "type_t", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_typeattributeset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_typeattributeset_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_typeattributeset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_typeattributeset_astnull_neg(CuTest *tc) { char *line[] = {"(", "typeattributeset", "filetypes", "(", "not", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_typeattributeset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_typeattributeset_noname_neg(CuTest *tc) { char *line[] = {"(", "typeattributeset", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_typeattributeset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_typeattributeset_nameinparens_neg(CuTest *tc) { char *line[] = {"(", "typeattributeset", "(", "filetypes", ")", "(", "test_t", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_typeattributeset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_typeattributeset_emptylists_neg(CuTest *tc) { char *line[] = {"(", "typeattributeset", "filetypes", "(", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_typeattributeset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_typeattributeset_listinparens_neg(CuTest *tc) { char *line[] = {"(", "typeattributeset", "filetypes", "(", "(", "test_t", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_typeattributeset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_typeattributeset_extra_neg(CuTest *tc) { char *line[] = {"(", "typeattributeset", "filetypes", "(", "test_t", ")", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_typeattributeset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_userbounds(CuTest *tc) { char *line[] = {"(", "userbounds", "user1", "user2", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_userbounds(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, rc, SEPOL_OK); } void test_cil_gen_userbounds_notype1_neg(CuTest *tc) { char *line[] = {"(", "userbounds", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_userbounds(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, rc, SEPOL_ERR); } void test_cil_gen_userbounds_type1_inparens_neg(CuTest *tc) { char *line[] = {"(", "userbounds", "(", "user1", ")", "user2", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_userbounds(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, rc, SEPOL_ERR); } void test_cil_gen_userbounds_notype2_neg(CuTest *tc) { char *line[] = {"(", "userbounds", "user1", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_userbounds(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, rc, SEPOL_ERR); } void test_cil_gen_userbounds_type2_inparens_neg(CuTest *tc) { char *line[] = {"(", "userbounds", "user1", "(", "user2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_userbounds(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, rc, SEPOL_ERR); } void test_cil_gen_userbounds_extra_neg(CuTest *tc) { char *line[] = {"(", "userbounds", "user1", "user2", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_userbounds(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, rc, SEPOL_ERR); } void test_cil_gen_userbounds_dbnull_neg(CuTest *tc) { char *line[] = {"(", "userbounds", "user1", "user2", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_userbounds(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, rc, SEPOL_ERR); } void test_cil_gen_userbounds_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_userbounds(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, rc, SEPOL_ERR); } void test_cil_gen_userbounds_astnull_neg(CuTest *tc) { char *line[] = {"(", "userbounds", "user1", "user2", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_userbounds(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, rc, SEPOL_ERR); } void test_cil_gen_role(CuTest *tc) { char *line[] = {"(", "role", "test_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_role(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertPtrNotNull(tc, test_ast_node->data); CuAssertIntEquals(tc, test_ast_node->flavor, CIL_ROLE); } void test_cil_gen_role_dbnull_neg(CuTest *tc) { char *line[] = {"(", "role", "test_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_role(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_role_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_role(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_role_astnull_neg(CuTest *tc) { char *line[] = {"(", "role", "test_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_role(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_role_extrarole_neg(CuTest *tc) { char *line[] = {"(", "role", "test_r", "extra_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_role(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_role_noname_neg(CuTest *tc) { char *line[] = {"(", "role", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_role(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_roletransition(CuTest *tc) { char *line[] = {"(", "roletransition", "foo_r", "bar_t", "process", "foobar_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_roletransition(test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertPtrNotNull(tc, test_ast_node->data); CuAssertIntEquals(tc, test_ast_node->flavor, CIL_ROLETRANSITION); } void test_cil_gen_roletransition_currnull_neg(CuTest *tc) { struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_roletransition(NULL, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_roletransition_astnull_neg (CuTest *tc) { char *line[] = {"(", "roletransition" "foo_r", "bar_t", "process", "foobar_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; int rc = cil_gen_roletransition(test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_roletransition_srcnull_neg(CuTest *tc) { char *line[] = {"(", "roletransition", "foo_r", "bar_t", "process", "foobar_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); test_tree->root->cl_head->cl_head->next = NULL; struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_roletransition(test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_roletransition_tgtnull_neg(CuTest *tc) { char *line[] = {"(", "roletransition", "foo_r", "bar_t", "process", "foobar_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); test_tree->root->cl_head->cl_head->next->next = NULL; struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_roletransition(test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_roletransition_resultnull_neg(CuTest *tc) { char *line[] = {"(", "roletransition", "foo_r", "bar_t", "process", "foobar_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); test_tree->root->cl_head->cl_head->next->next->next->next = NULL; struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_roletransition(test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_roletransition_extra_neg(CuTest *tc) { char *line[] = {"(", "roletransition", "foo_r", "bar_t", "process", "foobar_r", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_roletransition(test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_bool_true(CuTest *tc) { char *line[] = {"(", "boolean", "foo", "true", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_bool(test_db, test_tree->root->cl_head->cl_head, test_ast_node, CIL_BOOL); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertPtrNotNull(tc, test_ast_node->data); CuAssertIntEquals(tc, ((struct cil_bool*)test_ast_node->data)->value, 1); CuAssertIntEquals(tc, test_ast_node->flavor, CIL_BOOL); } void test_cil_gen_bool_tunable_true(CuTest *tc) { char *line[] = {"(", "tunable", "foo", "true", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_bool(test_db, test_tree->root->cl_head->cl_head, test_ast_node, CIL_TUNABLE); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertPtrNotNull(tc, test_ast_node->data); CuAssertIntEquals(tc, ((struct cil_bool*)test_ast_node->data)->value, 1); CuAssertIntEquals(tc, test_ast_node->flavor, CIL_TUNABLE); } void test_cil_gen_bool_false(CuTest *tc) { char *line[] = {"(", "boolean", "bar", "false", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_bool(test_db, test_tree->root->cl_head->cl_head, test_ast_node, CIL_BOOL); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertPtrNotNull(tc, test_ast_node->data); CuAssertIntEquals(tc, ((struct cil_bool*)test_ast_node->data)->value, 0); CuAssertIntEquals(tc, test_ast_node->flavor, CIL_BOOL); } void test_cil_gen_bool_tunable_false(CuTest *tc) { char *line[] = {"(", "tunable", "bar", "false", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_bool(test_db, test_tree->root->cl_head->cl_head, test_ast_node, CIL_TUNABLE); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertPtrNotNull(tc, test_ast_node->data); CuAssertIntEquals(tc, ((struct cil_bool*)test_ast_node->data)->value, 0); CuAssertIntEquals(tc, test_ast_node->flavor, CIL_TUNABLE); } void test_cil_gen_bool_none_neg(CuTest *tc) { char *line[] = {"(", "boolean", "foo", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_bool(test_db, test_tree->root->cl_head->cl_head, test_ast_node, CIL_BOOL); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_bool_dbnull_neg(CuTest *tc) { char *line[] = {"(", "boolean", "foo", "bar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_bool(test_db, test_tree->root->cl_head->cl_head, test_ast_node, CIL_BOOL); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_bool_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_bool(test_db, test_tree->root->cl_head->cl_head, test_ast_node, CIL_BOOL); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_bool_astnull_neg(CuTest *tc) { char *line[] = {"(", "boolean", "foo", "bar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_bool(test_db, test_tree->root->cl_head->cl_head, test_ast_node, CIL_BOOL); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_bool_notbool_neg(CuTest *tc) { char *line[] = {"(", "boolean", "foo", "bar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_bool(test_db, test_tree->root->cl_head->cl_head, test_ast_node, CIL_BOOL); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_bool_boolname_neg(CuTest *tc) { char *line[] = {"(", "boolean", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_bool(test_db, test_tree->root->cl_head->cl_head, test_ast_node, CIL_BOOL); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_bool_extraname_false_neg(CuTest *tc) { char *line[] = {"(", "boolean", "foo", "false", "bar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_bool(test_db, test_tree->root->cl_head->cl_head, test_ast_node, CIL_BOOL); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_bool_extraname_true_neg(CuTest *tc) { char *line[] = {"(", "boolean", "foo", "true", "bar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_bool(test_db, test_tree->root->cl_head->cl_head, test_ast_node, CIL_BOOL); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_eq2_t1type(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "t1", "type_t", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_constrain_expr_stack_eq2_t1t1_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "t1", "t1", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_eq2_t2type(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "t2", "type_t", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_constrain_expr_stack_eq2_t2t2_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "t2", "t2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_eq2_r1role(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "r1", "role_r", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_constrain_expr_stack_eq2_r1r1_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "r1", "r1", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_eq2_r2role(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "r2", "role_r", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_constrain_expr_stack_eq2_r2r2_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "r2", "r2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_eq2_t1t2(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "t1", "t2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_constrain_expr_stack_eq_r1r2(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "r1", "r2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_constrain_expr_stack_eq2_r1r2(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "r1", "r2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_constrain_expr_stack_eq2_u1u2(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "u1", "u2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_constrain_expr_stack_eq2_u1user(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "u1", "user_u", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_constrain_expr_stack_eq2_u1u1_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "u1", "u1", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_eq2_u2user(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "u2", "user_u", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_constrain_expr_stack_eq2_u2u2_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "u2", "u2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_eq_l2h2(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "l2", "h2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_constrain_expr_stack_eq_l2_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "l2", "h1", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_eq_l1l2(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "l1", "l2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_constrain_expr_stack_eq_l1h1(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "l1", "h1", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_constrain_expr_stack_eq_l1h2(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "l1", "h2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_constrain_expr_stack_eq_h1l2(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "h1", "l2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_constrain_expr_stack_eq_h1h2(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "h1", "h2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_constrain_expr_stack_eq_h1_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "h1", "l1", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_eq_l1l1_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "l1", "l1", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_eq2_l1l2_constrain_neg(CuTest *tc) { char *line[] = {"(", "constrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "l1", "l2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_CONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_eq_l1l2_constrain_neg(CuTest *tc) { char *line[] = {"(", "constrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "l1", "l2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_CONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_eq_leftkeyword_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "h2", "h1", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_eq_noexpr1_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_eq_expr1inparens_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "(", "l1", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_eq_noexpr2_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "l1", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_eq_expr2inparens_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "l1", "(", "h2", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_eq_extraexpr_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "foo", "foo", "extra", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_eq2(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "l2", "h2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_constrain_expr_stack_eq2_noexpr1_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_eq2_expr1inparens_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "(", "l1", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_eq2_noexpr2_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "l1", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_eq2_expr2inparens_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "l1", "(", "h2", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_eq2_extraexpr_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "foo", "foo", "extra", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_noteq(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "neq", "l2", "h2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_constrain_expr_stack_noteq_noexpr1_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "neq", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_noteq_expr1inparens_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "neq", "(", "l1", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_noteq_noexpr2_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "neq", "l1", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_noteq_expr2inparens_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "neq", "l1", "(", "h2", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_noteq_extraexpr_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "neq", "foo", "foo", "extra", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_not(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "not", "(", "neq", "l2", "h2", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_constrain_expr_stack_not_noexpr_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "not", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_not_emptyparens_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "not", "(", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_not_extraparens_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "not", "(", "neq", "l2", "h2", ")", "(", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_or(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "or", "(", "neq", "l1", "l2", ")", "(", "neq", "l1", "h1", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_constrain_expr_stack_or_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "or", "(", "foo", ")", "(", "neq", "l1", "h1", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_or_noexpr_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "or", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_or_emptyfirstparens_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "or", "(", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_or_missingsecondexpr_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "or", "(", "foo", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_or_emptysecondparens_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "or", "(", "foo", ")", "(", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_or_extraexpr_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "or", "(", "foo", ")", "(", "foo", ")", "(", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_and(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "and", "(", "neq", "l1", "l2", ")", "(", "neq", "l1", "h1", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_constrain_expr_stack_and_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "and", "(", "foo", ")", "(", "neq", "l1", "h1", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_and_noexpr_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "and", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_and_emptyfirstparens_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "and", "(", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_and_missingsecondexpr_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "and", "(", "foo", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_and_emptysecondparens_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "and", "(", "foo", ")", "(", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_and_extraexpr_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "and", "(", "foo", ")", "(", "foo", ")", "(", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_dom(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "dom", "l2", "h2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_constrain_expr_stack_dom_noexpr1_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "dom", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_dom_expr1inparens_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "dom", "(", "l1", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_dom_noexpr2_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "dom", "l1", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_dom_expr2inparens_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "dom", "l1", "(", "h2", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_dom_extraexpr_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "dom", "foo", "foo", "extra", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_domby(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "domby", "l2", "h2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_constrain_expr_stack_domby_noexpr1_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "domby", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_domby_expr1inparens_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "domby", "(", "l1", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_domby_noexpr2_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "domby", "l1", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_domby_expr2inparens_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "domby", "l1", "(", "h2", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_domby_extraexpr_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "domby", "foo", "foo", "extra", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_incomp(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "incomp", "l2", "h2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_constrain_expr_stack_incomp_noexpr1_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "incomp", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_incomp_expr1inparens_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "incomp", "(", "l1", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_incomp_noexpr2_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "incomp", "l1", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_incomp_expr2inparens_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "incomp", "l1", "(", "h2", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_incomp_extraexpr_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "incomp", "foo", "foo", "extra", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_currnull_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_stacknull_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "t1", "type_t", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, NULL); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_operatorinparens_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "(", "eq", ")", "t1", "type_t", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expr_stack_incorrectcall_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "t1", "type_t", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *parse_current = test_tree->root->cl_head->cl_head; struct cil_constrain *cons; cil_constrain_init(&cons); cil_classpermset_init(&cons->classpermset); cil_fill_classpermset(parse_current->next->cl_head, cons->classpermset); int rc = cil_gen_expr_stack(parse_current->next->next->cl_head->next->next, CIL_MLSCONSTRAIN, &cons->expr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_roleallow(CuTest *tc) { char *line[] = {"(", "roleallow", "staff_r", "sysadm_r", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_current; test_current = test_tree->root->cl_head->cl_head; test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_roleallow(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertPtrNotNull(tc, test_ast_node->data); CuAssertStrEquals(tc, ((struct cil_roleallow*)test_ast_node->data)->src_str, test_current->next->data); CuAssertStrEquals(tc, ((struct cil_roleallow*)test_ast_node->data)->tgt_str, test_current->next->next->data); CuAssertIntEquals(tc, test_ast_node->flavor, CIL_ROLEALLOW); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_roleallow_dbnull_neg(CuTest *tc) { char *line[] = {"(", "roleallow", "foo", "bar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_roleallow(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_roleallow_currnull_neg(CuTest *tc) { struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_roleallow(test_db, NULL, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_roleallow_astnull_neg(CuTest *tc) { char *line[] = {"(", "roleallow", "foo", "bar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node = NULL; int rc = cil_gen_roleallow(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_roleallow_srcnull_neg(CuTest *tc) { char *line[] = {"(", "roleallow", "foo", "bar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); test_tree->root->cl_head->cl_head->next = NULL; struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_roleallow(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_roleallow_tgtnull_neg(CuTest *tc) { char *line[] = {"(", "roleallow", "foo", "bar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); test_tree->root->cl_head->cl_head->next->next = NULL; struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_roleallow(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_roleallow_extra_neg(CuTest *tc) { char *line[] = {"(", "roleallow", "foo", "bar", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_roleallow(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_rolebounds(CuTest *tc) { char *line[] = {"(", "rolebounds", "role1", "role2", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_rolebounds(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, rc, SEPOL_OK); } void test_cil_gen_rolebounds_norole1_neg(CuTest *tc) { char *line[] = {"(", "rolebounds", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_rolebounds(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, rc, SEPOL_ERR); } void test_cil_gen_rolebounds_role1_inparens_neg(CuTest *tc) { char *line[] = {"(", "rolebounds", "(", "role1", ")", "role2", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_rolebounds(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, rc, SEPOL_ERR); } void test_cil_gen_rolebounds_norole2_neg(CuTest *tc) { char *line[] = {"(", "rolebounds", "role1", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_rolebounds(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, rc, SEPOL_ERR); } void test_cil_gen_rolebounds_role2_inparens_neg(CuTest *tc) { char *line[] = {"(", "rolebounds", "role1", "(", "role2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_rolebounds(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, rc, SEPOL_ERR); } void test_cil_gen_rolebounds_extra_neg(CuTest *tc) { char *line[] = {"(", "rolebounds", "role1", "role2", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_rolebounds(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, rc, SEPOL_ERR); } void test_cil_gen_rolebounds_dbnull_neg(CuTest *tc) { char *line[] = {"(", "rolebounds", "role1", "role2", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_rolebounds(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, rc, SEPOL_ERR); } void test_cil_gen_rolebounds_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_rolebounds(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, rc, SEPOL_ERR); } void test_cil_gen_rolebounds_astnull_neg(CuTest *tc) { char *line[] = {"(", "rolebounds", "role1", "role2", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_rolebounds(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, rc, SEPOL_ERR); } void test_cil_gen_avrule(CuTest *tc) { char *line[] = {"(", "allow", "test", "foo", "(", "bar", "(", "read", "write", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *test_current; test_current = test_tree->root->cl_head->cl_head; int rc = cil_gen_avrule(test_current, test_ast_node, CIL_AVRULE_ALLOWED); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertPtrNotNull(tc, test_ast_node->data); CuAssertStrEquals(tc, ((struct cil_avrule*)test_ast_node->data)->src_str, test_current->next->data); CuAssertStrEquals(tc, ((struct cil_avrule*)test_ast_node->data)->tgt_str, test_current->next->next->data); CuAssertStrEquals(tc, ((struct cil_avrule*)test_ast_node->data)->classpermset->class_str, test_current->next->next->next->cl_head->data); CuAssertIntEquals(tc, test_ast_node->flavor, CIL_AVRULE); CuAssertPtrNotNull(tc, ((struct cil_avrule*)test_ast_node->data)->classpermset->permset->perms_list_str); struct cil_list_item *test_list = ((struct cil_avrule*)test_ast_node->data)->classpermset->permset->perms_list_str->head; test_current = test_current->next->next->next->cl_head->next->cl_head; while(test_list != NULL) { CuAssertIntEquals(tc, test_list->flavor, CIL_AST_STR); CuAssertStrEquals(tc, test_list->data, test_current->data ); test_list = test_list->next; test_current = test_current->next; } } void test_cil_gen_avrule_permset(CuTest *tc) { char *line[] = {"(", "allow", "test", "foo", "(", "bar", "permset", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *test_current; test_current = test_tree->root->cl_head->cl_head; int rc = cil_gen_avrule(test_current, test_ast_node, CIL_AVRULE_ALLOWED); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_avrule_permset_anon(CuTest *tc) { char *line[] = {"(", "allow", "test", "foo", "(", "bar", "(", "read", "write", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *test_current; test_current = test_tree->root->cl_head->cl_head; int rc = cil_gen_avrule(test_current, test_ast_node, CIL_AVRULE_ALLOWED); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_avrule_extra_neg(CuTest *tc) { char *line[] = {"(", "allow", "test", "foo", "(", "bar", "permset", ")", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *test_current; test_current = test_tree->root->cl_head->cl_head; int rc = cil_gen_avrule(test_current, test_ast_node, CIL_AVRULE_ALLOWED); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_avrule_sourceparens(CuTest *tc) { char *line[] = {"(", "allow", "(", "test", ")", "foo", "(", "bar", "(", "read", "write", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *test_current; test_current = test_tree->root->cl_head->cl_head; int rc = cil_gen_avrule(test_current, test_ast_node, CIL_AVRULE_ALLOWED); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_avrule_sourceemptyparen_neg(CuTest *tc) { char *line[] = {"(", "allow", "(", ")", "bar", "file", "(", "read", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *test_current; test_current = test_tree->root->cl_head->cl_head; int rc = cil_gen_avrule(test_current, test_ast_node, CIL_AVRULE_ALLOWED); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_avrule_targetparens(CuTest *tc) { char *line[] = {"(", "allow", "test", "(", "foo", ")", "bar", "(", "read", "write", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *test_current; test_current = test_tree->root->cl_head->cl_head; int rc = cil_gen_avrule(test_current, test_ast_node, CIL_AVRULE_ALLOWED); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_avrule_targetemptyparen_neg(CuTest *tc) { char *line[] = {"(", "allow", "bar", "(", ")", "file", "(", "read", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *test_current; test_current = test_tree->root->cl_head->cl_head; int rc = cil_gen_avrule(test_current, test_ast_node, CIL_AVRULE_ALLOWED); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_avrule_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *test_current; test_current = test_tree->root->cl_head->cl_head; int rc = cil_gen_avrule(test_current, test_ast_node, CIL_AVRULE_ALLOWED); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_avrule_astnull_neg(CuTest *tc) { char *line[] = {"(", "allow", "test", "foo", "bar", "(", "read", "write", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_tree_node *test_current; test_current = test_tree->root->cl_head->cl_head; int rc = cil_gen_avrule(test_current, test_ast_node, CIL_AVRULE_ALLOWED); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_avrule_sourcedomainnull_neg(CuTest *tc) { char *line[] = {"(", "allow", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *test_current; test_current = test_tree->root->cl_head->cl_head; int rc = cil_gen_avrule(test_current, test_ast_node, CIL_AVRULE_ALLOWED); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_avrule_targetdomainnull_neg(CuTest *tc) { char *line[] = {"(", "allow", "foo", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *test_current; test_current = test_tree->root->cl_head->cl_head; int rc = cil_gen_avrule(test_current, test_ast_node, CIL_AVRULE_ALLOWED); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_avrule_objectclassnull_neg(CuTest *tc) { char *line[] = {"(", "allow", "foo", "bar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *test_current; test_current = test_tree->root->cl_head->cl_head; int rc = cil_gen_avrule(test_current, test_ast_node, CIL_AVRULE_ALLOWED); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_avrule_permsnull_neg(CuTest *tc) { char *line[] = {"(", "allow", "foo", "bar", "(", "baz", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *test_current; test_current = test_tree->root->cl_head->cl_head; int rc = cil_gen_avrule(test_current, test_ast_node, CIL_AVRULE_ALLOWED); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_avrule_twolists_neg(CuTest *tc) { char *line[] = {"(", "allow", "test", "foo", "bar", "(", "write", ")", "(", "read", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *test_current; test_current = test_tree->root->cl_head->cl_head; int rc = cil_gen_avrule(test_current, test_ast_node, CIL_AVRULE_ALLOWED); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_type_rule_transition(CuTest *tc) { char *line[] = {"(", "typetransition", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_type_rule(test_tree->root->cl_head->cl_head, test_ast_node, CIL_TYPE_TRANSITION); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertStrEquals(tc, ((struct cil_type_rule*)test_ast_node->data)->src_str, test_tree->root->cl_head->cl_head->next->data); CuAssertStrEquals(tc, ((struct cil_type_rule*)test_ast_node->data)->tgt_str, test_tree->root->cl_head->cl_head->next->next->data); CuAssertStrEquals(tc, ((struct cil_type_rule*)test_ast_node->data)->obj_str, test_tree->root->cl_head->cl_head->next->next->next->data); CuAssertStrEquals(tc, ((struct cil_type_rule*)test_ast_node->data)->result_str, test_tree->root->cl_head->cl_head->next->next->next->next->data); CuAssertIntEquals(tc, ((struct cil_type_rule*)test_ast_node->data)->rule_kind, CIL_TYPE_TRANSITION); CuAssertIntEquals(tc, test_ast_node->flavor, CIL_TYPE_RULE); } void test_cil_gen_type_rule_transition_currnull_neg(CuTest *tc) { struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_type_rule(NULL, test_ast_node, CIL_TYPE_TRANSITION); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_type_rule_transition_astnull_neg(CuTest *tc) { char *line[] = {"(", "typetransition", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; int rc = cil_gen_type_rule(test_tree->root->cl_head->cl_head, test_ast_node, CIL_TYPE_TRANSITION); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_type_rule_transition_srcnull_neg(CuTest *tc) { char *line[] = {"(", "typetransition", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; test_tree->root->cl_head->cl_head->next = NULL; int rc = cil_gen_type_rule(test_tree->root->cl_head->cl_head, test_ast_node, CIL_TYPE_TRANSITION); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_type_rule_transition_tgtnull_neg(CuTest *tc) { char *line[] = {"(", "typetransition", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; test_tree->root->cl_head->cl_head->next->next = NULL; int rc = cil_gen_type_rule(test_tree->root->cl_head->cl_head, test_ast_node, CIL_TYPE_TRANSITION); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_type_rule_transition_objnull_neg(CuTest *tc) { char *line[] = {"(", "typetransition", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; test_tree->root->cl_head->cl_head->next->next->next = NULL; int rc = cil_gen_type_rule(test_tree->root->cl_head->cl_head, test_ast_node, CIL_TYPE_TRANSITION); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_type_rule_transition_resultnull_neg(CuTest *tc) { char *line[] = {"(", "typetransition", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; test_tree->root->cl_head->cl_head->next->next->next->next = NULL; int rc = cil_gen_type_rule(test_tree->root->cl_head->cl_head, test_ast_node, CIL_TYPE_TRANSITION); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_type_rule_transition_extra_neg(CuTest *tc) { char *line[] = {"(", "typetransition", "foo", "bar", "file", "foobar", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_type_rule(test_tree->root->cl_head->cl_head, test_ast_node, CIL_TYPE_TRANSITION); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_type_rule_change(CuTest *tc) { char *line[] = {"(", "typechange", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_type_rule(test_tree->root->cl_head->cl_head, test_ast_node, CIL_TYPE_CHANGE); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertStrEquals(tc, ((struct cil_type_rule*)test_ast_node->data)->src_str, test_tree->root->cl_head->cl_head->next->data); CuAssertStrEquals(tc, ((struct cil_type_rule*)test_ast_node->data)->tgt_str, test_tree->root->cl_head->cl_head->next->next->data); CuAssertStrEquals(tc, ((struct cil_type_rule*)test_ast_node->data)->obj_str, test_tree->root->cl_head->cl_head->next->next->next->data); CuAssertStrEquals(tc, ((struct cil_type_rule*)test_ast_node->data)->result_str, test_tree->root->cl_head->cl_head->next->next->next->next->data); CuAssertIntEquals(tc, ((struct cil_type_rule*)test_ast_node->data)->rule_kind, CIL_TYPE_CHANGE); CuAssertIntEquals(tc, test_ast_node->flavor, CIL_TYPE_RULE); } void test_cil_gen_type_rule_change_currnull_neg(CuTest *tc) { struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_type_rule(NULL, test_ast_node, CIL_TYPE_CHANGE); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_type_rule_change_astnull_neg(CuTest *tc) { char *line[] = {"(", "typechange", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; int rc = cil_gen_type_rule(test_tree->root->cl_head->cl_head, test_ast_node, CIL_TYPE_CHANGE); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_type_rule_change_srcnull_neg(CuTest *tc) { char *line[] = {"(", "typechange", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; test_tree->root->cl_head->cl_head->next = NULL; int rc = cil_gen_type_rule(test_tree->root->cl_head->cl_head, test_ast_node, CIL_TYPE_CHANGE); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_type_rule_change_tgtnull_neg(CuTest *tc) { char *line[] = {"(", "typechange", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; test_tree->root->cl_head->cl_head->next->next = NULL; int rc = cil_gen_type_rule(test_tree->root->cl_head->cl_head, test_ast_node, CIL_TYPE_CHANGE); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_type_rule_change_objnull_neg(CuTest *tc) { char *line[] = {"(", "typechange", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; test_tree->root->cl_head->cl_head->next->next->next = NULL; int rc = cil_gen_type_rule(test_tree->root->cl_head->cl_head, test_ast_node, CIL_TYPE_CHANGE); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_type_rule_change_resultnull_neg(CuTest *tc) { char *line[] = {"(", "typechange", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; test_tree->root->cl_head->cl_head->next->next->next->next = NULL; int rc = cil_gen_type_rule(test_tree->root->cl_head->cl_head, test_ast_node, CIL_TYPE_CHANGE); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_type_rule_change_extra_neg(CuTest *tc) { char *line[] = {"(", "typechange", "foo", "bar", "file", "foobar", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_type_rule(test_tree->root->cl_head->cl_head, test_ast_node, CIL_TYPE_CHANGE); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_type_rule_member(CuTest *tc) { char *line[] = {"(", "typemember", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_type_rule(test_tree->root->cl_head->cl_head, test_ast_node, CIL_TYPE_MEMBER); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertStrEquals(tc, ((struct cil_type_rule*)test_ast_node->data)->src_str, test_tree->root->cl_head->cl_head->next->data); CuAssertStrEquals(tc, ((struct cil_type_rule*)test_ast_node->data)->tgt_str, test_tree->root->cl_head->cl_head->next->next->data); CuAssertStrEquals(tc, ((struct cil_type_rule*)test_ast_node->data)->obj_str, test_tree->root->cl_head->cl_head->next->next->next->data); CuAssertStrEquals(tc, ((struct cil_type_rule*)test_ast_node->data)->result_str, test_tree->root->cl_head->cl_head->next->next->next->next->data); CuAssertIntEquals(tc, ((struct cil_type_rule*)test_ast_node->data)->rule_kind, CIL_TYPE_MEMBER); CuAssertIntEquals(tc, test_ast_node->flavor, CIL_TYPE_RULE); } void test_cil_gen_type_rule_member_currnull_neg(CuTest *tc) { struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_type_rule(NULL, test_ast_node, CIL_TYPE_MEMBER); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_type_rule_member_astnull_neg(CuTest *tc) { char *line[] = {"(", "typemember", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; int rc = cil_gen_type_rule(test_tree->root->cl_head->cl_head, test_ast_node, CIL_TYPE_MEMBER); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_type_rule_member_srcnull_neg(CuTest *tc) { char *line[] = {"(", "typemember", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; test_tree->root->cl_head->cl_head->next = NULL; int rc = cil_gen_type_rule(test_tree->root->cl_head->cl_head, test_ast_node, CIL_TYPE_MEMBER); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_type_rule_member_tgtnull_neg(CuTest *tc) { char *line[] = {"(", "typemember", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; test_tree->root->cl_head->cl_head->next->next = NULL; int rc = cil_gen_type_rule(test_tree->root->cl_head->cl_head, test_ast_node, CIL_TYPE_MEMBER); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_type_rule_member_objnull_neg(CuTest *tc) { char *line[] = {"(", "typemember", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; test_tree->root->cl_head->cl_head->next->next->next = NULL; int rc = cil_gen_type_rule(test_tree->root->cl_head->cl_head, test_ast_node, CIL_TYPE_MEMBER); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_type_rule_member_resultnull_neg(CuTest *tc) { char *line[] = {"(", "typemember", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; test_tree->root->cl_head->cl_head->next->next->next->next = NULL; int rc = cil_gen_type_rule(test_tree->root->cl_head->cl_head, test_ast_node, CIL_TYPE_MEMBER); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_type_rule_member_extra_neg(CuTest *tc) { char *line[] = {"(", "typemember", "foo", "bar", "file", "foobar", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_type_rule(test_tree->root->cl_head->cl_head, test_ast_node, CIL_TYPE_MEMBER); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_user(CuTest *tc) { char *line[] = {"(", "user", "sysadm", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_user(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, CIL_USER, test_ast_node->flavor); CuAssertPtrNotNull(tc, test_ast_node->data); CuAssertPtrEquals(tc, test_ast_node, ((struct cil_symtab_datum*)test_ast_node->data)->node); CuAssertStrEquals(tc, test_tree->root->cl_head->cl_head->next->data, ((struct cil_symtab_datum*)test_ast_node->data)->name); } void test_cil_gen_user_dbnull_neg(CuTest *tc) { char *line[] = {"(", "user", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_user(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_user_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_user(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_user_astnull_neg(CuTest *tc) { char *line[] = {"(", "user", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_user(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_user_nouser_neg(CuTest *tc) { char *line[] = {"(", "user", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_user(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_user_xsinfo_neg(CuTest *tc) { char *line[] = {"(", "user", "sysadm", "xsinfo", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_user(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_userlevel(CuTest *tc) { char *line[] = {"(", "userlevel", "user_u", "lvl_l", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_userlevel(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_userlevel_anon_level(CuTest *tc) { char *line[] = {"(", "userlevel", "user_u", "(", "s0", "(", "c0", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_userlevel(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_userlevel_anon_level_neg(CuTest *tc) { char *line[] = {"(", "userlevel", "user_u", "(", "s0", "(", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_userlevel(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_userlevel_usernull_neg(CuTest *tc) { char *line[] = {"(", "userlevel", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_userlevel(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_userlevel_userrange_neg(CuTest *tc) { char *line[] = {"(", "userlevel", "(", "user", ")", "level", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_userlevel(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_userlevel_levelnull_neg(CuTest *tc) { char *line[] = {"(", "userlevel", "user_u", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_userlevel(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_userlevel_levelrangeempty_neg(CuTest *tc) { char *line[] = {"(", "userlevel", "user_u", "(", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_userlevel(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_userlevel_extra_neg(CuTest *tc) { char *line[] = {"(", "userlevel", "user_u", "level", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_userlevel(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_userlevel_dbnull_neg(CuTest *tc) { char *line[] = {"(", "userlevel", "user", "level", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_userlevel(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_userlevel_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_userlevel(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_userlevel_astnull_neg(CuTest *tc) { char *line[] = {"(", "userlevel", "user", "level", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_userlevel(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_userrange_named(CuTest *tc) { char *line[] = {"(", "userrange", "user_u", "range", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_userrange(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_userrange_anon(CuTest *tc) { char *line[] = {"(", "userrange", "user_u", "(", "low", "high", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_userrange(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_userrange_usernull_neg(CuTest *tc) { char *line[] = {"(", "userrange", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_userrange(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_userrange_anonuser_neg(CuTest *tc) { char *line[] = {"(", "userrange", "(", "user_u", ")", "(", "low", "high", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_userrange(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_userrange_rangenamenull_neg(CuTest *tc) { char *line[] = {"(", "userrange", "user_u", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_userrange(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_userrange_anonrangeinvalid_neg(CuTest *tc) { char *line[] = {"(", "userrange", "user_u", "(", "low", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_userrange(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_userrange_anonrangeempty_neg(CuTest *tc) { char *line[] = {"(", "userrange", "user_u", "(", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_userrange(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_userrange_extra_neg(CuTest *tc) { char *line[] = {"(", "userrange", "user_u", "(", "low", "high", ")", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_userrange(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_userrange_dbnull_neg(CuTest *tc) { char *line[] = {"(", "userrange", "user", "range", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_userrange(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_userrange_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_userrange(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_userrange_astnull_neg(CuTest *tc) { char *line[] = {"(", "userrange", "user", "range", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_userrange(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_sensitivity(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_sensitivity(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertPtrNotNull(tc, test_ast_node->data); CuAssertIntEquals(tc, test_ast_node->flavor, CIL_SENS); } void test_cil_gen_sensitivity_dbnull_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_sensitivity(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_sensitivity_currnull_neg(CuTest *tc) { struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_sensitivity(test_db, NULL, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_sensitivity_astnull_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node = NULL; int rc = cil_gen_sensitivity(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_sensitivity_sensnull_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); test_tree->root->cl_head->cl_head->next = NULL; struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_sensitivity(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_sensitivity_senslist_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "(", "s0", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_sensitivity(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_sensitivity_extra_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_sensitivity(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_sensalias(CuTest *tc) { char *line[] = {"(", "sensitivityalias", "s0", "alias", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_sensalias(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_sensalias_dbnull_neg(CuTest *tc) { char *line[] = {"(", "sensitivityalias", "s0", "alias", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db = NULL; struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_sensalias(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_sensalias_currnull_neg(CuTest *tc) { struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_sensalias(test_db, NULL, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_sensalias_astnull_neg(CuTest *tc) { char *line[] = {"(", "sensitivityalias", "s0", "alias", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init (&test_db); struct cil_tree_node *test_ast_node = NULL; int rc = cil_gen_sensalias(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_sensalias_sensnull_neg(CuTest *tc) { char *line[] = {"(", "sensitivityalias", "s0", "alias", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); test_tree->root->cl_head->cl_head->next = NULL; struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_sensalias(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_sensalias_senslist_neg(CuTest *tc) { char *line[] = {"(", "sensitivityalias", "(", "s0", "s1", ")", "alias", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_sensalias(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_sensalias_aliasnull_neg(CuTest *tc) { char *line[] = {"(", "sensitivityalias", "s0", "alias", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); test_tree->root->cl_head->cl_head->next->next = NULL; struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_sensalias(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_sensalias_aliaslist_neg(CuTest *tc) { char *line[] = {"(", "sensitivityalias", "s0", "(", "alias", "alias2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_sensalias(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_sensalias_extra_neg(CuTest *tc) { char *line[] = {"(", "sensitivityalias", "s0", "alias", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_sensalias(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_category(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_category(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_category_dbnull_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db = NULL; struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_category(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_category_astnull_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node = NULL; int rc = cil_gen_category(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_category_currnull_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_category(test_db, NULL, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_category_catnull_neg(CuTest *tc){ char *line[] = {"(", "category", "c0", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); test_tree->root->cl_head->cl_head->next = NULL; struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_category(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_category_catlist_neg(CuTest *tc){ char *line[] = {"(", "category", "(", "c0", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_category(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_category_extra_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_category(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_catset(CuTest *tc) { char *line[] = {"(", "categoryset", "somecats", "(", "c0", "c1", "c2", "(", "c3", "c4", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_catset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_catset_dbnull_neg(CuTest *tc) { char *line[] = {"(", "categoryset", "somecats", "(", "c0", "c1", "c2", "(", "c3", "c4", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db = NULL; struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_catset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_catset_currnull_neg(CuTest *tc) { char *line[] = {"(", "categoryset", "somecats", "(", "c0", "c1", "c2", "(", "c3", "c4", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_catset(test_db, NULL, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_catset_astnull_neg(CuTest *tc) { char *line[] = {"(", "categoryset", "somecats", "(", "c0", "c1", "c2", "(", "c3", "c4", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node = NULL; int rc = cil_gen_catset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_catset_namenull_neg(CuTest *tc) { char *line[] = {"(", "categoryset", "somecats", "(", "c0", "c1", "c2", "(", "c3", "c4", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); test_tree->root->cl_head->cl_head->next = NULL; struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_catset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_catset_setnull_neg(CuTest *tc) { char *line[] = {"(", "categoryset", "somecats", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_catset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_catset_namelist_neg(CuTest *tc) { //This should fail before gen_node call - additional syntax checks are needed char *line[] = {"(", "categoryset", "(", "somecats", ")", "(", "c0", "c1", "c2", "(", "c3", "c4", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_catset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_catset_extra_neg(CuTest *tc) { char *line[] = {"(", "categoryset", "somecats", "(", "c0", "c1", "c2", "(", "c3", "c4", ")", ")", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_catset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_catset_notset_neg(CuTest *tc) { char *line[] = {"(", "categoryset", "somecats", "blah", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_catset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } // TODO: This doesn't actually test failure of gen_node void test_cil_gen_catset_nodefail_neg(CuTest *tc) { char *line[] = {"(", "categoryset", "somecats", "(", "c0", "c1", "c2", "(", "c3", "c4", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db = NULL; struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_catset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_catset_settolistfail_neg(CuTest *tc) { char *line[] = {"(", "categoryset", "somecats", "(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_catset(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_catalias(CuTest *tc) { char *line[] = {"(", "categoryalias", "c0", "red", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_catalias(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_catalias_dbnull_neg(CuTest *tc) { char *line[] = {"(", "categoryalias", "c0", "red", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db = NULL; struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_catalias(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_catalias_currnull_neg(CuTest *tc) { char *line[] = {"(", "categoryalias", "c0", "red", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_catalias(test_db, NULL, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_catalias_astnull_neg(CuTest *tc) { char *line[] = {"(", "categoryalias", "c0", "red", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node = NULL; int rc = cil_gen_catalias(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_catalias_catnull_neg(CuTest *tc) { char *line[] = {"(", "categoryalias", "c0", "red", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); test_tree->root->cl_head->cl_head->next = NULL; struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_catalias(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_catalias_aliasnull_neg(CuTest *tc) { char *line[] = {"(", "categoryalias", "c0", "red", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); test_tree->root->cl_head->cl_head->next->next = NULL; struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_catalias(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_catalias_extra_neg(CuTest *tc) { char *line[] = {"(", "categoryalias", "c0", "red", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_catalias(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_catrange(CuTest *tc) { char *line[] = {"(", "categoryrange", "range", "(", "c0", "c1", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_catrange(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_catrange_noname_neg(CuTest *tc) { char *line[] = {"(", "categoryrange", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_catrange(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_catrange_norange_neg(CuTest *tc) { char *line[] = {"(", "categoryrange", "range", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_catrange(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_catrange_emptyrange_neg(CuTest *tc) { char *line[] = {"(", "categoryrange", "range", "(", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_catrange(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_catrange_extrarange_neg(CuTest *tc) { char *line[] = {"(", "categoryrange", "range", "(", "c0", "c1", "c2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_catrange(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_catrange_dbnull_neg(CuTest *tc) { char *line[] = {"(", "categoryrange", "range", "(", "c0", "c1", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db = NULL; struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_catrange(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_catrange_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_catrange(test_db, NULL, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_catrange_astnull_neg(CuTest *tc) { char *line[] = {"(", "categoryrange", "range", "(", "c0", "c1", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node = NULL; int rc = cil_gen_catrange(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_catrange_extra_neg(CuTest *tc) { char *line[] = {"(", "categoryrange", "range", "(", "c0", "c1", ")", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_catrange(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_roletype(CuTest *tc) { char *line[] = {"(", "roletype", "admin_r", "admin_t", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_roletype(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_roletype_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_roletype(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_roletype_dbnull_neg(CuTest *tc) { char *line[] = {"(", "roletype", "admin_r", "admin_t", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db = NULL; struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_roletype(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_roletype_astnull_neg(CuTest *tc) { char *line[] = {"(", "roletype", "admin_r", "admin_t", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node = NULL; int rc = cil_gen_roletype(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_roletype_empty_neg(CuTest *tc) { char *line[] = {"(", "roletype", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_roletype(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_roletype_rolelist_neg(CuTest *tc) { char *line[] = {"(", "roletype", "(", "admin_r", ")", "admin_t", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_roletype(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } // TODO // Not sure this is actually testing roletype // I think this will just test that type is null void test_cil_gen_roletype_roletype_sublist_neg(CuTest *tc) { char *line[] = {"(", "(", "roletype", "admin_r", ")", "admin_t", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_roletype(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_roletype_typelist_neg(CuTest *tc) { char *line[] = {"(", "roletype", "admin_r", "(", "admin_t", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_roletype(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_userrole(CuTest *tc) { char *line[] = {"(", "userrole", "staff_u", "staff_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_userrole(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_userrole_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_userrole(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_userrole_dbnull_neg(CuTest *tc) { char *line[] = {"(", "userrole", "staff_u", "staff_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db = NULL; struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_userrole(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_userrole_astnull_neg(CuTest *tc) { char *line[] = {"(", "userrole", "staff_u", "staff_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node = NULL; int rc = cil_gen_userrole(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_userrole_empty_neg(CuTest *tc) { char *line[] = {"(", "userrole", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_userrole(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_userrole_userlist_neg(CuTest *tc) { char *line[] = {"(", "userrole", "(", "staff_u", ")", "staff_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_userrole(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } //TODO: see above void test_cil_gen_userrole_userrole_sublist_neg(CuTest *tc) { char *line[] = {"(", "(", "userrole", "staff_u", ")", "staff_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_userrole(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_userrole_rolelist_neg(CuTest *tc) { char *line[] = {"(", "userrole", "staff_u", "(", "staff_r", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_userrole(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_classcommon(CuTest *tc) { char *line[] = {"(", "classcommon", "file", "file", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); char *test_key = test_tree->root->cl_head->cl_head->next->data; struct cil_class *test_cls; cil_class_init(&test_cls); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_symtab_insert(&test_db->symtab[CIL_SYM_CLASSES], (hashtab_key_t)test_key, (struct cil_symtab_datum*)test_cls, test_ast_node); test_ast_node->data = test_cls; test_ast_node->flavor = CIL_CLASS; int rc = cil_gen_classcommon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_classcommon_dbnull_neg(CuTest *tc) { char *line[] = {"(", "classcommon", "file", "file", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_classcommon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_classcommon_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_classcommon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_classcommon_astnull_neg(CuTest *tc) { char *line[] = {"(", "classcommon", "file", "file", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_classcommon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_classcommon_missingclassname_neg(CuTest *tc) { char *line[] = {"(", "classcommon", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_classcommon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_classcommon_noperms_neg(CuTest *tc) { char *line[] = {"(", "classcommon", "file", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); char *test_key = test_tree->root->cl_head->cl_head->next->data; struct cil_class *test_cls; cil_class_init(&test_cls); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_symtab_insert(&test_db->symtab[CIL_SYM_CLASSES], (hashtab_key_t)test_key, (struct cil_symtab_datum*)test_cls, test_ast_node); test_ast_node->data = test_cls; test_ast_node->flavor = CIL_CLASS; int rc = cil_gen_classcommon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_classcommon_extraperms_neg(CuTest *tc) { char *line[] = {"(", "classcommon", "file", "file", "file", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); char *test_key = test_tree->root->cl_head->cl_head->next->data; struct cil_class *test_cls; cil_class_init(&test_cls); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_symtab_insert(&test_db->symtab[CIL_SYM_CLASSES], (hashtab_key_t)test_key, (struct cil_symtab_datum*)test_cls, test_ast_node); test_ast_node->data = test_cls; test_ast_node->flavor = CIL_CLASS; int rc = cil_gen_classcommon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_catorder(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c255", ")", "(", "categoryorder", "(", "c0", "c255", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_catorder(test_db, test_tree->root->cl_head->next->next->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_catorder_dbnull_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c255", ")", "(", "categoryorder", "(", "c0", "c255", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db = NULL; struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); int rc = cil_gen_catorder(test_db, test_tree->root->cl_head->next->next->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_catorder_currnull_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c255", ")", "(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_catorder(test_db, test_tree->root->cl_head->next->next->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_catorder_astnull_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c255", ")", "(", "categoryorder", "(", "c0", "c255", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node = NULL; int rc = cil_gen_catorder(test_db, test_tree->root->cl_head->next->next->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_catorder_missingcats_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c255", ")", "(", "categoryorder", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_catorder(test_db, test_tree->root->cl_head->next->next->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_catorder_nosublist_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c255", ")", "(", "categoryorder", "c0", "c255", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_catorder(test_db, test_tree->root->cl_head->next->next->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_catorder_nestedcat_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c255", ")", "(", "categoryorder", "(", "c0", "(", "c255", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_catorder(test_db, test_tree->root->cl_head->next->next->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_dominance(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "sensitivity", "s1", ")", "(", "sensitivity", "s2", ")", "(", "dominance", "(", "s0", "s1", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_dominance(test_db, test_tree->root->cl_head->next->next->next->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_dominance_dbnull_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "sensitivity", "s1", ")", "(", "sensitivity", "s2", ")", "(", "dominance", "(", "s0", "s1", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_dominance(test_db, test_tree->root->cl_head->next->next->next->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_dominance_currnull_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "sensitivity", "s1", ")", "(", "sensitivity", "s2", ")", "(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_dominance(test_db, test_tree->root->cl_head->next->next->next->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_dominance_astnull_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "sensitivity", "s1", ")", "(", "sensitivity", "s2", ")", "(", "dominance", "(", "s0", "s1", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_dominance(test_db, test_tree->root->cl_head->next->next->next->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_dominance_nosensitivities_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "sensitivity", "s1", ")", "(", "sensitivity", "s2", ")", "(", "dominance", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_dominance(test_db, test_tree->root->cl_head->next->next->next->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_dominance_nosublist_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "sensitivity", "s1", ")", "(", "sensitivity", "s2", ")", "(", "dominance", "s0", "s2", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_dominance(test_db, test_tree->root->cl_head->next->next->next->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_senscat(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "sensitivity", "s1", ")", "(", "dominance", "(", "s0", "s1", ")", ")", "(", "category", "c0", ")", "(", "category", "c255", ")", "(", "categoryorder", "(", "c0", "c255", ")", ")", "(", "sensitivitycategory", "s1", "(", "c0", "c255", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_senscat(test_db, test_tree->root->cl_head->next->next->next->next->next->next->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_senscat_nosublist(CuTest *tc) { char *line[] = {"(", "sensitivitycategory", "s1", "c0", "c255", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_senscat(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_senscat_dbnull_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "sensitivity", "s1", ")", "(", "dominance", "(", "s0", "s1", ")", ")", "(", "category", "c0", ")", "(", "category", "c255", ")", "(", "categoryorder", "(", "c0", "c255", ")", ")", "(", "sensitivitycategory", "s1", "(", "c0", "c255", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_senscat(test_db, test_tree->root->cl_head->next->next->next->next->next->next->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_senscat_currnull_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "sensitivity", "s1", ")", "(", "dominance", "(", "s0", "s1", ")", ")", "(", "category", "c0", ")", "(", "category", "c255", ")", "(", "categoryorder", "(", "c0", "c255", ")", ")", "(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_senscat(test_db, test_tree->root->cl_head->next->next->next->next->next->next->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_senscat_astnull_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "sensitivity", "s1", ")", "(", "dominance", "(", "s0", "s1", ")", ")", "(", "category", "c0", ")", "(", "category", "c255", ")", "(", "categoryorder", "(", "c0", "c255", ")", ")", "(", "sensitivitycategory", "s1", "(", "c0", "c255", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_senscat(test_db, test_tree->root->cl_head->next->next->next->next->next->next->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_senscat_nosensitivities_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "sensitivity", "s1", ")", "(", "dominance", "(", "s0", "s1", ")", ")", "(", "category", "c0", ")", "(", "category", "c255", ")", "(", "categoryorder", "(", "c0", "c255", ")", ")", "(", "sensitivitycategory", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_senscat(test_db, test_tree->root->cl_head->next->next->next->next->next->next->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_senscat_sublist_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "sensitivity", "s1", ")", "(", "dominance", "(", "s0", "s1", ")", ")", "(", "category", "c0", ")", "(", "category", "c255", ")", "(", "categoryorder", "(", "c0", "c255", ")", ")", "(", "sensitivitycategory", "s1", "(", "c0", "(", "c255", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_senscat(test_db, test_tree->root->cl_head->next->next->next->next->next->next->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_senscat_nocat_neg(CuTest *tc) { char *line[] = {"(", "sensitivitycategory", "s1", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_senscat(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_fill_level(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c1", ")", "(", "level", "low", "(", "s0", "(", "c1", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_level *test_level; cil_level_init(&test_level); int rc = cil_fill_level(test_tree->root->cl_head->next->next->cl_head->next->next->cl_head, test_level); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_fill_level_sensnull_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c1", ")", "(", "level", "low", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_level *test_level; cil_level_init(&test_level); int rc = cil_fill_level(test_tree->root->cl_head->next->next->cl_head->next->next, test_level); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_fill_level_levelnull_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c1", ")", "(", "level", "low", "(", "s0", "(", "c1", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_level *test_level = NULL; int rc = cil_fill_level(test_tree->root->cl_head->next->next->cl_head->next->next->cl_head, test_level); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_fill_level_nocat(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c1", ")", "(", "level", "low", "(", "s0", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_level *test_level; cil_level_init(&test_level); int rc = cil_fill_level(test_tree->root->cl_head->next->next->cl_head->next->next->cl_head, test_level); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_fill_level_emptycat_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c1", ")", "(", "level", "low", "(", "s0", "(", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_level *test_level; cil_level_init(&test_level); int rc = cil_fill_level(test_tree->root->cl_head->next->next->cl_head->next->next->cl_head, test_level); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_level(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c1", ")", "(", "level", "low", "(", "s0", "(", "c1", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_level(test_db, test_tree->root->cl_head->next->next->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_level_nameinparens_neg(CuTest *tc) { char *line[] = {"(", "level", "(", "low", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_level(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_level_emptysensparens_neg(CuTest *tc) { char *line[] = {"(", "level", "low", "(", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_level(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_level_extra_neg(CuTest *tc) { char *line[] = {"(", "level", "low", "(", "s0", "(", "c0", ")", ")", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_level(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_level_emptycat_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c1", ")", "(", "level", "low", "(", "s0", "(", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_level(test_db, test_tree->root->cl_head->next->next->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_level_noname_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c1", ")", "(", "level", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_level(test_db, test_tree->root->cl_head->next->next->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_level_nosens_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c1", ")", "(", "level", "low", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_level(test_db, test_tree->root->cl_head->next->next->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_level_dbnull_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c1", ")", "(", "level", "low", "(", "s0", "(", "c1", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_level(test_db, test_tree->root->cl_head->next->next->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_level_currnull_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c1", ")", "(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_level(test_db, test_tree->root->cl_head->next->next->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_level_astnull_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c1", ")", "(", "level", "low", "(", "s0", "(", "c1", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_level(test_db, test_tree->root->cl_head->next->next->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_levelrange(CuTest *tc) { char *line[] = {"(", "levelrange", "range", "(", "low", "high", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_levelrange(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_levelrange_rangeinvalid_neg(CuTest *tc) { char *line[] = {"(", "levelrange", "range", "(", "low", "high", "extra", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_levelrange(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_levelrange_namenull_neg(CuTest *tc) { char *line[] = {"(", "levelrange", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_levelrange(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_levelrange_rangenull_neg(CuTest *tc) { char *line[] = {"(", "levelrange", "range", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_levelrange(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_levelrange_rangeempty_neg(CuTest *tc) { char *line[] = {"(", "levelrange", "range", "(", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_levelrange(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_levelrange_extra_neg(CuTest *tc) { char *line[] = {"(", "levelrange", "range", "(", "low", "high", ")", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_levelrange(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_levelrange_dbnull_neg(CuTest *tc) { char *line[] = {"(", "levelrange", "range", "(", "low", "high", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_levelrange(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_levelrange_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_levelrange(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_levelrange_astnull_neg(CuTest *tc) { char *line[] = {"(", "levelrange", "range", "(", "low", "high", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_levelrange(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "l2", "h2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_constrain(test_db, test_tree->root->cl_head->cl_head, test_ast_node, CIL_MLSCONSTRAIN); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_constrain_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "dne", "l1", "l2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_constrain(test_db, test_tree->root->cl_head->cl_head, test_ast_node, CIL_MLSCONSTRAIN); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_classset_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_constrain(test_db, test_tree->root->cl_head->cl_head, test_ast_node, CIL_MLSCONSTRAIN); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_classset_noclass_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_constrain(test_db, test_tree->root->cl_head->cl_head, test_ast_node, CIL_MLSCONSTRAIN); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_classset_noperm_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_constrain(test_db, test_tree->root->cl_head->cl_head, test_ast_node, CIL_MLSCONSTRAIN); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_permset_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "dir", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_constrain(test_db, test_tree->root->cl_head->cl_head, test_ast_node, CIL_MLSCONSTRAIN); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_permset_noclass_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "dir", ")", "(", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_constrain(test_db, test_tree->root->cl_head->cl_head, test_ast_node, CIL_MLSCONSTRAIN); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_permset_noperm_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "dir", ")", "(", "create", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_constrain(test_db, test_tree->root->cl_head->cl_head, test_ast_node, CIL_MLSCONSTRAIN); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_expression_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_constrain(test_db, test_tree->root->cl_head->cl_head, test_ast_node, CIL_MLSCONSTRAIN); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_dbnull_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "12", "h2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_constrain(test_db, test_tree->root->cl_head->cl_head, test_ast_node, CIL_MLSCONSTRAIN); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_constrain(test_db, test_tree->root->cl_head->cl_head, test_ast_node, CIL_MLSCONSTRAIN); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_constrain_astnull_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "12", "h2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_constrain(test_db, test_tree->root->cl_head->cl_head, test_ast_node, CIL_MLSCONSTRAIN); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_fill_context(CuTest *tc) { char *line[] = {"(", "context", "localhost_node_label", "(", "system_u", "object_r", "node_lo_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_context *test_context; cil_context_init(&test_context); int rc = cil_fill_context(test_tree->root->cl_head->cl_head->next->next->cl_head, test_context); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_fill_context_unnamedlvl(CuTest *tc) { char *line[] = {"(", "context", "localhost_node_label", "(", "system_u", "object_r", "node_lo_t", "(", "(", "s0", ")", "(", "s0", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_context *test_context; cil_context_init(&test_context); int rc = cil_fill_context(test_tree->root->cl_head->cl_head->next->next->cl_head, test_context); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_fill_context_nocontext_neg(CuTest *tc) { char *line[] = {"(", "context", "localhost_node_label", "(", "system_u", "object_r", "node_lo_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_context *test_context = NULL; int rc = cil_fill_context(test_tree->root->cl_head->cl_head->next->next->cl_head, test_context); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_fill_context_nouser_neg(CuTest *tc) { char *line[] = {"(", "context", "localhost_node_label", "(", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_context *test_context; cil_context_init(&test_context); int rc = cil_fill_context(test_tree->root->cl_head->cl_head->next->next->cl_head, test_context); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_fill_context_norole_neg(CuTest *tc) { char *line[] = {"(", "context", "localhost_node_label", "(", "system_u", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_context *test_context; cil_context_init(&test_context); int rc = cil_fill_context(test_tree->root->cl_head->cl_head->next->next->cl_head, test_context); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_fill_context_notype_neg(CuTest *tc) { char *line[] = {"(", "context", "localhost_node_label", "(", "system_u", "object_r", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_context *test_context; cil_context_init(&test_context); int rc = cil_fill_context(test_tree->root->cl_head->cl_head->next->next->cl_head, test_context); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_fill_context_nolowlvl_neg(CuTest *tc) { char *line[] = {"(", "context", "localhost_node_label", "(", "system_u", "object_r", "type_t", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_context *test_context; cil_context_init(&test_context); int rc = cil_fill_context(test_tree->root->cl_head->cl_head->next->next->cl_head, test_context); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_fill_context_nohighlvl_neg(CuTest *tc) { char *line[] = {"(", "context", "localhost_node_label", "(", "system_u", "object_r", "type_t", "(", "low", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_context *test_context; cil_context_init(&test_context); int rc = cil_fill_context(test_tree->root->cl_head->cl_head->next->next->cl_head, test_context); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_fill_context_unnamedlvl_nocontextlow_neg(CuTest *tc) { char *line[] = {"(", "context", "localhost_node_label", "(", "system_u", "object_r", "type_t", "(", "s0", "(", ")", ")", "high", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_context *test_context; cil_context_init(&test_context); int rc = cil_fill_context(test_tree->root->cl_head->cl_head->next->next->cl_head, test_context); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_fill_context_unnamedlvl_nocontexthigh_neg(CuTest *tc) { char *line[] = {"(", "context", "localhost_node_label", "(", "system_u", "object_r", "type_t", "low", "(", "s0", "(", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_context *test_context; cil_context_init(&test_context); int rc = cil_fill_context(test_tree->root->cl_head->cl_head->next->next->cl_head, test_context); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_context(CuTest *tc) { char *line[] = {"(", "context", "packet_default", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_context(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_context_notinparens_neg(CuTest *tc) { char *line[] = {"(", "context", "packet_default", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_context(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_context_extralevel_neg(CuTest *tc) { char *line[] = {"(", "context", "packet_default", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", "extra", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_context(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_context_emptycontext_neg(CuTest *tc) { char *line[] = {"(", "context", "packet_default", "(", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_context(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_context_extra_neg(CuTest *tc) { char *line[] = {"(", "context", "packet_default", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", "(", "extra", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_context(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_context_doubleparen_neg(CuTest *tc) { char *line[] = {"(", "context", "packet_default", "(", "(", "system_u", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_context(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_context_norole_neg(CuTest *tc) { char *line[] = {"(", "context", "packet_default", "(", "system_u", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_context(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_context_roleinparens_neg(CuTest *tc) { char *line[] = {"(", "context", "packet_default", "(", "system_u", "(", "role_r", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_context(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_context_notype_neg(CuTest *tc) { char *line[] = {"(", "context", "packet_default", "(", "system_u", "role_r", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_context(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_context_typeinparens_neg(CuTest *tc) { char *line[] = {"(", "context", "packet_default", "(", "system_u", "role_r", "(", "type_t", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_context(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_context_nolevels_neg(CuTest *tc) { char *line[] = {"(", "context", "packet_default", "(", "system_u", "role_r", "type_t", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_context(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_context_nosecondlevel_neg(CuTest *tc) { char *line[] = {"(", "context", "packet_default", "(", "system_u", "role_r", "type_t", "(", "low", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_context(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_context_noname_neg(CuTest *tc) { char *line[] = {"(", "context", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_context(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_context_nouser_neg(CuTest *tc) { char *line[] = {"(", "context", "localhost_node_label", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_context(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_context_dbnull_neg(CuTest *tc) { char *line[] = {"(", "context", "localhost_node_label", "(", "system_u", "object_r", "node_lo_t", "(", "s0", ")", "(", "s0", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_context(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_context_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_context(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_context_astnull_neg(CuTest *tc) { char *line[] = {"(", "context", "localhost_node_label", "system_u", "object_r", "node_lo_t", "(", "s0", ")", "(", "s0", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_context(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_filecon_dir(CuTest *tc) { char *line[] = {"(", "filecon", "root", "path", "dir", "context", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_filecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_filecon_file(CuTest *tc) { char *line[] = {"(", "filecon", "root", "path", "file", "context", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_filecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_filecon_char(CuTest *tc) { char *line[] = {"(", "filecon", "root", "path", "char", "context", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_filecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_filecon_block(CuTest *tc) { char *line[] = {"(", "filecon", "root", "path", "block", "context", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_filecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_filecon_socket(CuTest *tc) { char *line[] = {"(", "filecon", "root", "path", "socket", "context", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_filecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_filecon_pipe(CuTest *tc) { char *line[] = {"(", "filecon", "root", "path", "pipe", "context", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_filecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_filecon_symlink(CuTest *tc) { char *line[] = {"(", "filecon", "root", "path", "symlink", "context", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_filecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_filecon_any(CuTest *tc) { char *line[] = {"(", "filecon", "root", "path", "any", "context", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_filecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_filecon_neg(CuTest *tc) { char *line[] = {"(", "filecon", "root", "path", "dne", "context", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_filecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_filecon_anon_context(CuTest *tc) { char *line[] = {"(", "filecon", "root", "path", "file", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_filecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_filecon_dbnull_neg(CuTest *tc) { char *line[] = {"(", "filecon", "root", "path", "file", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_filecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_filecon_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_filecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_filecon_astnull_neg(CuTest *tc) { char *line[] = {"(", "filecon", "root", "path", "file", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_filecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_filecon_str1null_neg(CuTest *tc) { char *line[] = {"(", "filecon", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_filecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_filecon_str1_inparens_neg(CuTest *tc) { char *line[] = {"(", "filecon", "(", "root", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_filecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_filecon_str2null_neg(CuTest *tc) { char *line[] = {"(", "filecon", "root", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_filecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_filecon_str2_inparens_neg(CuTest *tc) { char *line[] = {"(", "filecon", "root", "(", "path", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_filecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_filecon_classnull_neg(CuTest *tc) { char *line[] = {"(", "filecon", "root", "path", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_filecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_filecon_class_inparens_neg(CuTest *tc) { char *line[] = {"(", "filecon", "root", "path", "(", "file", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_filecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_filecon_contextnull_neg(CuTest *tc) { char *line[] = {"(", "filecon", "root", "path", "file", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_filecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_filecon_context_neg(CuTest *tc) { char *line[] = {"(", "filecon", "root", "path", "file", "(", "system_u", "object_r", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_filecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_filecon_extra_neg(CuTest *tc) { char *line[] = {"(", "filecon", "root", "path", "file", "context", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_filecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_portcon_udp(CuTest *tc) { char *line[] = {"(", "portcon", "udp", "80", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_portcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_portcon_tcp(CuTest *tc) { char *line[] = {"(", "portcon", "tcp", "80", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_portcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_portcon_unknownprotocol_neg(CuTest *tc) { char *line[] = {"(", "portcon", "unknown", "80", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_portcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_portcon_anon_context(CuTest *tc) { char *line[] = {"(", "portcon", "udp", "80", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_portcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_portcon_portrange(CuTest *tc) { char *line[] = {"(", "portcon", "udp", "(", "25", "75", ")", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_portcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_portcon_portrange_one_neg(CuTest *tc) { char *line[] = {"(", "portcon", "udp", "(", "0", ")", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_portcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_portcon_portrange_morethanone_neg(CuTest *tc) { char *line[] = {"(", "portcon", "udp", "(", "0", "1", "2", ")", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_portcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_portcon_singleport_neg(CuTest *tc) { char *line[] = {"(", "portcon", "udp", "foo", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_portcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_portcon_lowport_neg(CuTest *tc) { char *line[] = {"(", "portcon", "udp", "(", "foo", "90", ")", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_portcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_portcon_highport_neg(CuTest *tc) { char *line[] = {"(", "portcon", "udp", "(", "80", "foo", ")", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_portcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_portcon_dbnull_neg(CuTest *tc) { char *line[] = {"(", "portcon", "udp", "(", "0", "1", ")", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_portcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_portcon_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_portcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_portcon_astnull_neg(CuTest *tc) { char *line[] = {"(", "portcon", "udp", "(", "0", "1", ")", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_portcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_portcon_str1null_neg(CuTest *tc) { char *line[] = {"(", "portcon", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_portcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_portcon_str1parens_neg(CuTest *tc) { char *line[] = {"(", "portcon", "(", "80", ")", "port", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_portcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_portcon_portnull_neg(CuTest *tc) { char *line[] = {"(", "portcon", "udp", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_portcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_portcon_contextnull_neg(CuTest *tc) { char *line[] = {"(", "portcon", "udp", "port", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_portcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_portcon_context_neg(CuTest *tc) { char *line[] = {"(", "portcon", "udp", "80", "(", "system_u", "object_r", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_portcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_portcon_extra_neg(CuTest *tc) { char *line[] = {"(", "portcon", "udp", "80", "con", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_portcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_fill_ipaddr(CuTest *tc) { char *line[] = {"(", "nodecon", "(", "192.168.1.1", ")", "ipaddr", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_nodecon *nodecon; cil_nodecon_init(&nodecon); cil_ipaddr_init(&nodecon->addr); int rc = cil_fill_ipaddr(test_tree->root->cl_head->cl_head->next->cl_head, nodecon->addr); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_fill_ipaddr_addrnodenull_neg(CuTest *tc) { char *line[] = {"(", "nodecon", "(", "192.168.1.1", ")", "ipaddr", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_nodecon *nodecon; cil_nodecon_init(&nodecon); cil_ipaddr_init(&nodecon->addr); int rc = cil_fill_ipaddr(NULL, nodecon->addr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_fill_ipaddr_addrnull_neg(CuTest *tc) { char *line[] = {"(", "nodecon", "(", "192.168.1.1", ")", "ipaddr", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_nodecon *nodecon; cil_nodecon_init(&nodecon); nodecon->addr = NULL; int rc = cil_fill_ipaddr(test_tree->root->cl_head->cl_head->next->cl_head, nodecon->addr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_fill_ipaddr_addrinparens_neg(CuTest *tc) { char *line[] = {"(", "nodecon", "(", "(", "192.168.1.1", ")", ")", "ipaddr", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_nodecon *nodecon; cil_nodecon_init(&nodecon); cil_ipaddr_init(&nodecon->addr); int rc = cil_fill_ipaddr(test_tree->root->cl_head->cl_head->next->cl_head, nodecon->addr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_fill_ipaddr_extra_neg(CuTest *tc) { char *line[] = {"(", "nodecon", "(", "192.168.1.1", "extra", ")", "ipaddr", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_nodecon *nodecon; cil_nodecon_init(&nodecon); cil_ipaddr_init(&nodecon->addr); int rc = cil_fill_ipaddr(test_tree->root->cl_head->cl_head->next->cl_head, nodecon->addr); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_nodecon(CuTest *tc) { char *line[] = {"(", "nodecon", "ipaddr", "ipaddr", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_nodecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_nodecon_anon_context(CuTest *tc) { char *line[] = {"(", "nodecon", "ipaddr", "ipaddr", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_nodecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_nodecon_dbnull_neg(CuTest *tc) { char *line[] = {"(", "nodecon", "ipaddr", "ipaddr", "con", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_nodecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_nodecon_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_nodecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_nodecon_astnull_neg(CuTest *tc) { char *line[] = {"(", "nodecon", "ipaddr", "ipaddr", "con", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_nodecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_nodecon_ipnull_neg(CuTest *tc) { char *line[] = {"(", "nodecon", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_nodecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_nodecon_ipanon(CuTest *tc) { char *line[] = {"(", "nodecon", "(", "192.168.1.1", ")", "ipaddr", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_nodecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_nodecon_ipanon_neg(CuTest *tc) { char *line[] = {"(", "nodecon", "(", "192.1.1", ")", "ipaddr", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_nodecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_nodecon_netmasknull_neg(CuTest *tc) { char *line[] = {"(", "nodecon", "ipaddr", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_nodecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_nodecon_netmaskanon(CuTest *tc) { char *line[] = {"(", "nodecon", "ipaddr", "(", "255.255.255.4", ")", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_nodecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_nodecon_netmaskanon_neg(CuTest *tc) { char *line[] = {"(", "nodecon", "ipaddr", "(", "str0", ")", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_nodecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_nodecon_contextnull_neg(CuTest *tc) { char *line[] = {"(", "nodecon", "ipaddr", "ipaddr", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_nodecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_nodecon_context_neg(CuTest *tc) { char *line[] = {"(", "nodecon", "ipaddr", "ipaddr", "(", "system_u", "object_r", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_nodecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_nodecon_extra_neg(CuTest *tc) { char *line[] = {"(", "nodecon", "ipaddr", "ipaddr", "(", "system_u", "object_r", "type_t", "(", "low", "high", ")", ")", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_nodecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_genfscon(CuTest *tc) { char *line[] = {"(", "genfscon", "type", "path", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_genfscon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_genfscon_anon_context(CuTest *tc) { char *line[] = {"(", "genfscon", "type", "path", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_genfscon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_genfscon_dbnull_neg(CuTest *tc) { char *line[] = {"(", "genfscon", "type", "path", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_genfscon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_genfscon_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_genfscon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_genfscon_astnull_neg(CuTest *tc) { char *line[] = {"(", "genfscon", "type", "path", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_genfscon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_genfscon_typenull_neg(CuTest *tc) { char *line[] = {"(", "genfscon", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_genfscon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_genfscon_typeparens_neg(CuTest *tc) { char *line[] = {"(", "genfscon", "(", "type", ")", "path", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_genfscon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_genfscon_pathnull_neg(CuTest *tc) { char *line[] = {"(", "genfscon", "type", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_genfscon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_genfscon_pathparens_neg(CuTest *tc) { char *line[] = {"(", "genfscon", "type", "(", "path", ")", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_genfscon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_genfscon_contextnull_neg(CuTest *tc) { char *line[] = {"(", "genfscon", "type", "path", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_genfscon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_genfscon_context_neg(CuTest *tc) { char *line[] = {"(", "genfscon", "type", "path", "(", "system_u", "object_r", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_genfscon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_genfscon_extra_neg(CuTest *tc) { char *line[] = {"(", "genfscon", "type", "path", "con", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_genfscon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_netifcon(CuTest *tc) { char *line[] = {"(", "netifcon", "eth0", "if_default", "packet_default", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_netifcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_netifcon_nested(CuTest *tc) { char *line[] = {"(", "netifcon", "eth1", "(", "system_u", "object_r", "netif_t", "(", "low", "high", ")", ")", "(", "system_u", "object_r", "netif_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_netifcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_netifcon_nested_neg(CuTest *tc) { char *line[] = {"(", "netifcon", "(", "eth1", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_netifcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_netifcon_nested_emptysecondlist_neg(CuTest *tc) { char *line[] = {"(", "netifcon", "eth1", "(", "system_u", "object_r", "netif_t", "(", "low", "high", ")", ")", "(", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_netifcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_netifcon_extra_nested_secondlist_neg(CuTest *tc) { char *line[] = {"(", "netifcon", "eth0", "extra", "(", "system_u", "object_r", "netif_t", "(", "low", "high", ")", ")", "(", "foo", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_netifcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_netifcon_nested_missingobjects_neg(CuTest *tc) { char *line[] = {"(", "netifcon", "eth1", "(", "system_u", ")", "(", "system_u", "object_r", "netif_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_netifcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_netifcon_nested_secondnested_missingobjects_neg(CuTest *tc) { char *line[] = {"(", "netifcon", "eth1", "(", "system_u", "object_r", "netif_t", "(", "low", "high", ")", ")", "(", "system_u", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_netifcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_netifcon_dbnull_neg(CuTest *tc) { char *line[] = {"(", "netifcon", "eth0", "if_default", "packet_default", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_netifcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_netifcon_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_netifcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_netifcon_astnull_neg(CuTest *tc) { char *line[] = {"(", "netifcon", "eth0", "if_default", "packet_default", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_netifcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_netifcon_ethmissing_neg(CuTest *tc) { char *line[] = {"(", "netifcon", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_netifcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_netifcon_interfacemissing_neg(CuTest *tc) { char *line[] = {"(", "netifcon", "eth0", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_netifcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_netifcon_packetmissing_neg(CuTest *tc) { char *line[] = {"(", "netifcon", "eth0", "if_default", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_netifcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_pirqcon(CuTest *tc) { char *line[] = {"(", "pirqcon", "1", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_pirqcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_pirqcon_pirqnotint_neg(CuTest *tc) { char *line[] = {"(", "pirqcon", "notint", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_pirqcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_pirqcon_nopirq_neg(CuTest *tc) { char *line[] = {"(", "pirqcon", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_pirqcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_pirqcon_pirqrange_neg(CuTest *tc) { char *line[] = {"(", "pirqcon", "(", "1", ")", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_pirqcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_pirqcon_nocontext_neg(CuTest *tc) { char *line[] = {"(", "pirqcon", "1", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_pirqcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_pirqcon_anoncontext_neg(CuTest *tc) { char *line[] = {"(", "pirqcon", "1", "(", "con", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_pirqcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_pirqcon_extra_neg(CuTest *tc) { char *line[] = {"(", "pirqcon", "1", "con", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_pirqcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_pirqcon_dbnull_neg(CuTest *tc) { char *line[] = {"(", "pirqcon", "1", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_pirqcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_pirqcon_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_pirqcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_pirqcon_astnull_neg(CuTest *tc) { char *line[] = {"(", "pirqcon", "1", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_pirqcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_iomemcon(CuTest *tc) { char *line[] = {"(", "iomemcon", "1", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_iomemcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_iomemcon_iomemrange(CuTest *tc) { char *line[] = {"(", "iomemcon", "(", "1", "2", ")", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_iomemcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_iomemcon_iomemrange_firstnotint_neg(CuTest *tc) { char *line[] = {"(", "iomemcon", "(", "foo", "2", ")", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_iomemcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_iomemcon_iomemrange_secondnotint_neg(CuTest *tc) { char *line[] = {"(", "iomemcon", "(", "1", "foo", ")", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_iomemcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_iomemcon_iomemrange_empty_neg(CuTest *tc) { char *line[] = {"(", "iomemcon", "(", ")", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_iomemcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_iomemcon_iomemrange_singleiomem_neg(CuTest *tc) { char *line[] = {"(", "iomemcon", "(", "1", ")", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_iomemcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_iomemcon_iomemrange_morethantwoiomem_neg(CuTest *tc) { char *line[] = {"(", "iomemcon", "(", "1", "2", "3", ")", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_iomemcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_iomemcon_iomemnotint_neg(CuTest *tc) { char *line[] = {"(", "iomemcon", "notint", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_iomemcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_iomemcon_noiomem_neg(CuTest *tc) { char *line[] = {"(", "iomemcon", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_iomemcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_iomemcon_nocontext_neg(CuTest *tc) { char *line[] = {"(", "iomemcon", "1", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_iomemcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_iomemcon_anoncontext_neg(CuTest *tc) { char *line[] = {"(", "iomemcon", "1", "(", "con", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_iomemcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_iomemcon_extra_neg(CuTest *tc) { char *line[] = {"(", "iomemcon", "1", "con", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_iomemcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_iomemcon_dbnull_neg(CuTest *tc) { char *line[] = {"(", "iomemcon", "1", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_iomemcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_iomemcon_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_iomemcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_iomemcon_astnull_neg(CuTest *tc) { char *line[] = {"(", "iomemcon", "1", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_iomemcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_ioportcon(CuTest *tc) { char *line[] = {"(", "ioportcon", "1", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_ioportcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_ioportcon_ioportrange(CuTest *tc) { char *line[] = {"(", "ioportcon", "(", "1", "2", ")", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_ioportcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_ioportcon_ioportrange_firstnotint_neg(CuTest *tc) { char *line[] = {"(", "ioportcon", "(", "foo", "2", ")", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_ioportcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_ioportcon_ioportrange_secondnotint_neg(CuTest *tc) { char *line[] = {"(", "ioportcon", "(", "1", "foo", ")", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_ioportcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_ioportcon_ioportrange_empty_neg(CuTest *tc) { char *line[] = {"(", "ioportcon", "(", ")", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_ioportcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_ioportcon_ioportrange_singleioport_neg(CuTest *tc) { char *line[] = {"(", "ioportcon", "(", "1", ")", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_ioportcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_ioportcon_ioportrange_morethantwoioport_neg(CuTest *tc) { char *line[] = {"(", "ioportcon", "(", "1", "2", "3", ")", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_ioportcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_ioportcon_ioportnotint_neg(CuTest *tc) { char *line[] = {"(", "ioportcon", "notint", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_ioportcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_ioportcon_noioport_neg(CuTest *tc) { char *line[] = {"(", "ioportcon", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_ioportcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_ioportcon_nocontext_neg(CuTest *tc) { char *line[] = {"(", "ioportcon", "1", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_ioportcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_ioportcon_anoncontext_neg(CuTest *tc) { char *line[] = {"(", "ioportcon", "1", "(", "con", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_ioportcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_ioportcon_extra_neg(CuTest *tc) { char *line[] = {"(", "ioportcon", "1", "con", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_ioportcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_ioportcon_dbnull_neg(CuTest *tc) { char *line[] = {"(", "ioportcon", "1", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_ioportcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_ioportcon_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_ioportcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_ioportcon_astnull_neg(CuTest *tc) { char *line[] = {"(", "ioportcon", "1", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_ioportcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_pcidevicecon(CuTest *tc) { char *line[] = {"(", "pcidevicecon", "1", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_pcidevicecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_pcidevicecon_pcidevicenotint_neg(CuTest *tc) { char *line[] = {"(", "pcidevicecon", "notint", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_pcidevicecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_pcidevicecon_nopcidevice_neg(CuTest *tc) { char *line[] = {"(", "pcidevicecon", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_pcidevicecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_pcidevicecon_pcidevicerange_neg(CuTest *tc) { char *line[] = {"(", "pcidevicecon", "(", "1", ")", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_pcidevicecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_pcidevicecon_nocontext_neg(CuTest *tc) { char *line[] = {"(", "pcidevicecon", "1", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_pcidevicecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_pcidevicecon_anoncontext_neg(CuTest *tc) { char *line[] = {"(", "pcidevicecon", "1", "(", "con", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_pcidevicecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_pcidevicecon_extra_neg(CuTest *tc) { char *line[] = {"(", "pcidevicecon", "1", "con", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_pcidevicecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_pcidevicecon_dbnull_neg(CuTest *tc) { char *line[] = {"(", "pcidevicecon", "1", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_pcidevicecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_pcidevicecon_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_pcidevicecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_pcidevicecon_astnull_neg(CuTest *tc) { char *line[] = {"(", "pcidevicecon", "1", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_pcidevicecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_fsuse_anoncontext(CuTest *tc) { char *line[] = {"(", "fsuse", "xattr", "ext3", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_fsuse(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_fsuse_anoncontext_neg(CuTest *tc) { char *line[] = {"(", "fsuse", "xattr", "ext3", "(", "system_u", "etc_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_fsuse(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_fsuse_xattr(CuTest *tc) { char *line[] = {"(", "fsuse", "xattr", "ext3", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_fsuse(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_fsuse_task(CuTest *tc) { char *line[] = {"(", "fsuse", "task", "ext3", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_fsuse(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_fsuse_transition(CuTest *tc) { char *line[] = {"(", "fsuse", "trans", "ext3", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_fsuse(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_fsuse_invalidtype_neg(CuTest *tc) { char *line[] = {"(", "fsuse", "foo", "ext3", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_fsuse(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_fsuse_notype_neg(CuTest *tc) { char *line[] = {"(", "fsuse", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_fsuse(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_fsuse_typeinparens_neg(CuTest *tc) { char *line[] = {"(", "fsuse", "(", "xattr", ")", "ext3", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_fsuse(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_fsuse_nofilesystem_neg(CuTest *tc) { char *line[] = {"(", "fsuse", "xattr", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_fsuse(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_fsuse_filesysteminparens_neg(CuTest *tc) { char *line[] = {"(", "fsuse", "xattr", "(", "ext3", ")", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_fsuse(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_fsuse_nocontext_neg(CuTest *tc) { char *line[] = {"(", "fsuse", "xattr", "ext3", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_fsuse(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_fsuse_emptyconparens_neg(CuTest *tc) { char *line[] = {"(", "fsuse", "xattr", "ext3", "(", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_fsuse(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_fsuse_extra_neg(CuTest *tc) { char *line[] = {"(", "fsuse", "xattr", "ext3", "con", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_fsuse(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_fsuse_dbnull_neg(CuTest *tc) { char *line[] = {"(", "fsuse", "xattr", "ext3", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_fsuse(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_fsuse_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_fsuse(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_fsuse_astnull_neg(CuTest *tc) { char *line[] = {"(", "fsuse", "xattr", "ext3", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_fsuse(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_macro_noparams(CuTest *tc) { char *line[] = {"(", "macro", "mm", "(", ")", "(", "type", "b", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_macro(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_macro_type(CuTest *tc) { char *line[] = {"(", "macro", "mm", "(", "(", "type", "a", ")", ")", "(", "type", "b", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_macro(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_macro_role(CuTest *tc) { char *line[] = {"(", "macro", "mm", "(", "(", "role", "a", ")", ")", "(", "role", "b", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_macro(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_macro_user(CuTest *tc) { char *line[] = {"(", "macro", "mm", "(", "(", "user", "a", ")", ")", "(", "user", "b", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_macro(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_macro_sensitivity(CuTest *tc) { char *line[] = {"(", "macro", "mm", "(", "(", "sensitivity", "a", ")", ")", "(", "sensitivity", "b", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_macro(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_macro_category(CuTest *tc) { char *line[] = {"(", "macro", "mm", "(", "(", "category", "a", ")", ")", "(", "category", "b", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_macro(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_macro_catset(CuTest *tc) { char *line[] = {"(", "macro", "mm", "(", "(", "categoryset", "a", ")", ")", "(", "categoryset", "b", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_macro(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_macro_level(CuTest *tc) { char *line[] = {"(", "macro", "mm", "(", "(", "level", "a", ")", ")", "(", "level", "b", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_macro(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_macro_class(CuTest *tc) { char *line[] = {"(", "macro", "mm", "(", "(", "class", "a", ")", ")", "(", "class", "b", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_macro(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_macro_classmap(CuTest *tc) { char *line[] = {"(", "macro", "mm", "(", "(", "classmap", "a", ")", ")", "(", "classmap", "b", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_macro(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_macro_permset(CuTest *tc) { char *line[] = {"(", "macro", "mm", "(", "(", "permissionset", "a", ")", ")", "(", "allow", "foo", "bar", "baz", "a", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_macro(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_macro_duplicate(CuTest *tc) { char *line[] = {"(", "macro", "mm", "(", "(", "class", "a",")", "(", "class", "x", ")", ")", "(", "class", "b", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_macro(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_macro_duplicate_neg(CuTest *tc) { char *line[] = {"(", "macro", "mm", "(", "(", "class", "a",")", "(", "class", "a", ")", ")", "(", "class", "b", "(", "read," ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_macro(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_macro_unknown_neg(CuTest *tc) { char *line[] = {"(", "macro", "mm", "(", "(", "foo", "a", ")", ")", "(", "foo", "b", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_macro(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_macro_dbnull_neg(CuTest *tc) { char *line[] = {"(", "macro", "mm", "(", "(", "foo", "a", ")", ")", "(", "foo", "b", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_macro(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_macro_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_macro(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_macro_astnull_neg(CuTest *tc) { char *line[] = {"(", "macro", "mm", "(", "(", "foo", "a", ")", ")", "(", "foo", "b", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node = NULL; int rc = cil_gen_macro(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_macro_unnamed_neg(CuTest *tc) { char *line[] = {"(", "macro", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_macro(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_macro_noparam_neg(CuTest *tc) { char *line[] = {"(", "macro", "mm", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_macro(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_macro_nosecondparam_neg(CuTest *tc) { char *line[] = {"(", "macro", "mm", "(", "(", "foo", "a", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_macro(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_macro_noparam_name_neg(CuTest *tc) { char *line[] = {"(", "macro", "mm", "(", "(", "type", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_macro(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_macro_emptyparam_neg(CuTest *tc) { char *line[] = {"(", "macro", "mm", "(", "(", ")", ")", "(", "foo", "b", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_macro(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_macro_paramcontainsperiod_neg(CuTest *tc) { char *line[] = {"(", "macro", "mm", "(", "(", "type", "a.", ")", ")", "(", "type", "b", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_macro(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_call(CuTest *tc) { char *line[] = {"(", "call", "mm", "(", "foo", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_call(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_call_noargs(CuTest *tc) { char *line[] = {"(", "call", "mm", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_call(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_call_anon(CuTest *tc) { char *line[] = {"(", "call", "mm", "(", "(", "s0", "(", "c0", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_call(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_call_empty_call_neg(CuTest *tc) { char *line[] = {"(", "call", "mm", "(", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_call(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_call_dbnull_neg(CuTest *tc) { char *line[] = {"(", "call", "mm", "(", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_call(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_call_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_call(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_call_astnull_neg(CuTest *tc) { char *line[] = {"(", "call", "mm", "(", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_call(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_call_name_inparens_neg(CuTest *tc) { char *line[] = {"(", "call", "(", "mm", ")", "(", "foo", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_call(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_call_noname_neg(CuTest *tc) { char *line[] = {"(", "call", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_call(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_optional(CuTest *tc) { char *line[] = {"(", "optional", "opt", "(", "allow", "foo", "bar", "(", "file", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_optional(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_optional_dbnull_neg(CuTest *tc) { char *line[] = {"(", "optional", "opt", "(", "allow", "foo", "bar", "(", "file", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_optional(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_optional_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_optional(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_optional_astnull_neg(CuTest *tc) { char *line[] = {"(", "optional", "opt", "(", "allow", "foo", "bar", "(", "file", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_optional(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_optional_unnamed_neg(CuTest *tc) { char *line[] = {"(", "optional", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_optional(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_optional_extra_neg(CuTest *tc) { char *line[] = {"(", "optional", "opt", "(", "allow", "foo", "bar", "(", "file", "(", "read", ")", ")", ")", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_optional(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_optional_nameinparens_neg(CuTest *tc) { char *line[] = {"(", "optional", "(", "opt", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_optional(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_optional_emptyoptional(CuTest *tc) { char *line[] = {"(", "optional", "opt", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_optional(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_optional_norule_neg(CuTest *tc) { char *line[] = {"(", "optional", "opt", "(", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_optional(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_policycap(CuTest *tc) { char *line[] = {"(", "policycap", "open_perms", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_policycap(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_policycap_noname_neg(CuTest *tc) { char *line[] = {"(", "policycap", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_policycap(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_policycap_nameinparens_neg(CuTest *tc) { char *line[] = {"(", "policycap", "(", "pol", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_policycap(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_policycap_extra_neg(CuTest *tc) { char *line[] = {"(", "policycap", "pol", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_policycap(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_policycap_dbnull_neg(CuTest *tc) { char *line[] = {"(", "policycap", "pol", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_policycap(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_policycap_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_policycap(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_policycap_astnull_neg(CuTest *tc) { char *line[] = {"(", "policycap", "pol", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_policycap(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_policycap_neg(CuTest *tc) { char *line[] = {"(", "policycap", "pol", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_policycap(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_ipaddr_ipv4(CuTest *tc) { char *line[] = {"(", "ipaddr", "ip", "192.168.1.1", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_ipaddr(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_ipaddr_ipv4_neg(CuTest *tc) { char *line[] = {"(", "ipaddr", "ip", ".168.1.1", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_ipaddr(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_ipaddr_ipv6(CuTest *tc) { char *line[] = {"(", "ipaddr", "ip", "2001:0db8:85a3:0000:0000:8a2e:0370:7334", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_ipaddr(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_gen_ipaddr_ipv6_neg(CuTest *tc) { char *line[] = {"(", "ipaddr", "ip", "2001:0db8:85a3:0000:0000:8a2e:0370:::7334", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_ipaddr(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_ipaddr_noname_neg(CuTest *tc) { char *line[] = {"(", "ipaddr", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_ipaddr(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_ipaddr_nameinparens_neg(CuTest *tc) { char *line[] = {"(", "ipaddr", "(", "ip", ")", "192.168.1.1", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_ipaddr(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_ipaddr_noip_neg(CuTest *tc) { char *line[] = {"(", "ipaddr", "ip", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_ipaddr(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_ipaddr_ipinparens_neg(CuTest *tc) { char *line[] = {"(", "ipaddr", "ip", "(", "192.168.1.1", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_ipaddr(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_ipaddr_extra_neg(CuTest *tc) { char *line[] = {"(", "ipaddr", "ip", "192.168.1.1", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_ipaddr(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_ipaddr_dbnull_neg(CuTest *tc) { char *line[] = {"(", "ipaddr", "ip", "192.168.1.1", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db = NULL; int rc = cil_gen_ipaddr(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_ipaddr_currnull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; int rc = cil_gen_ipaddr(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_gen_ipaddr_astnull_neg(CuTest *tc) { char *line[] = {"(", "ipaddr", "ip", "192.168.1.1", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_gen_ipaddr(test_db, test_tree->root->cl_head->cl_head, test_ast_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } /* cil_build_ast test cases */ void test_cil_build_ast(CuTest *tc) { char *line[] = {"(", "type", "foo", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_build_ast(test_db, test_tree->root, test_db->ast->root); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_build_ast_dbnull_neg(CuTest *tc) { char *line[] = {"(", "test", "\"qstring\"", ")", ";comment", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *null_db = NULL; struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_build_ast(null_db, test_tree->root, test_db->ast->root); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_build_ast_astnull_neg(CuTest *tc) { char *line[] = {"(", "test", "\"qstring\"", ")", ";comment", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); test_db->ast->root = NULL; int rc = cil_build_ast(test_db, test_tree->root, test_db->ast->root); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_build_ast_suberr_neg(CuTest *tc) { char *line[] = {"(", "block", "test", "(", "block", "(", "type", "log", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); int rc = cil_build_ast(test_db, test_tree->root, test_db->ast->root); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_build_ast_treenull_neg(CuTest *tc) { char *line[] = {"(", "allow", "test", "foo", "bar", "(", "read", "write", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); test_tree->root = NULL; struct cil_db *test_db; cil_db_init(&test_db); test_db->ast->root = NULL; int rc = cil_build_ast(test_db, test_tree->root, test_db->ast->root); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_build_ast_node_helper_block(CuTest *tc) { char *line[] = {"(", "block", "test", "(", "type", "log", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_block_neg(CuTest *tc) { char *line[] = {"(", "block", "(", "type", "log", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_blockinherit(CuTest *tc) { char *line[] = {"(", "blockinherit", "test", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_blockinherit_neg(CuTest *tc) { char *line[] = {"(", "blockinherit", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_permset(CuTest *tc) { char *line[] = {"(", "permissionset", "foo", "(", "read", "write", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, CIL_TREE_SKIP_NEXT, finished); } void test_cil_build_ast_node_helper_permset_neg(CuTest *tc) { char *line[] = {"(", "permissionset", "foo", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_in(CuTest *tc) { char *line[] = {"(", "in", "foo", "(", "allow", "test", "baz", "(", "char", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_in_neg(CuTest *tc) { char *line[] = {"(", "in", "foo", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_class(CuTest *tc) { char *line[] = {"(", "class", "file", "(", "read", "write", "open", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 1, finished); } void test_cil_build_ast_node_helper_class_neg(CuTest *tc) { char *line[] = {"(", "class", "(", "read", "write", "open", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_classpermset(CuTest *tc) { char *line[] = {"(", "classpermissionset", "foo", "(", "read", "(", "write", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, CIL_TREE_SKIP_NEXT, finished); } void test_cil_build_ast_node_helper_classpermset_neg(CuTest *tc) { char *line[] = {"(", "classpermissionset", "foo", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_classmap(CuTest *tc) { char *line[] = {"(", "classmap", "files", "(", "read", "write", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 1, finished); } void test_cil_build_ast_node_helper_classmap_neg(CuTest *tc) { char *line[] = {"(", "classmap", "(", "read", "write", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_classmapping(CuTest *tc) { char *line[] = {"(", "classmapping", "files", "read", "char_w", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 1, finished); } void test_cil_build_ast_node_helper_classmapping_neg(CuTest *tc) { char *line[] = {"(", "classmapping", "files", "read", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_common(CuTest *tc) { char *line[] = {"(", "common", "test", "(", "read", "write", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 1, finished); } void test_cil_build_ast_node_helper_common_neg(CuTest *tc) { char *line[] = {"(", "common", "(", "read", "write", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_sid(CuTest *tc) { char *line[] = {"(", "sid", "test", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 1, finished); } void test_cil_build_ast_node_helper_sid_neg(CuTest *tc) { char *line[] = {"(", "sid", "(", "blah", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_sidcontext(CuTest *tc) { char *line[] = {"(", "sidcontext", "test", "(", "blah", "blah", "blah", "(", "(", "s0", "(", "c0", ")", ")", "(", "s0", "(", "c0", ")", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 1, finished); } void test_cil_build_ast_node_helper_sidcontext_neg(CuTest *tc) { char *line[] = {"(", "sidcontext", "(", "blah", "blah", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_user(CuTest *tc) { char *line[] = {"(", "user", "jimmypage", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_user_neg(CuTest *tc) { char *line[] = {"(", "user", "foo", "bar", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_userlevel(CuTest *tc) { char *line[] = {"(", "userlevel", "johnpauljones", "level", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 1, finished); } void test_cil_build_ast_node_helper_userlevel_neg(CuTest *tc) { char *line[] = {"(", "userlevel", "johnpauljones", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_userrange(CuTest *tc) { char *line[] = {"(", "userrange", "johnpauljones", "range", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 1, finished); } void test_cil_build_ast_node_helper_userrange_neg(CuTest *tc) { char *line[] = {"(", "userrange", "johnpauljones", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_type(CuTest *tc) { char *line[] = {"(", "type", "test", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_type_neg(CuTest *tc) { char *line[] = {"(", "type", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_attribute(CuTest *tc) { char *line[] = {"(", "typeattribute", "test", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_attribute_neg(CuTest *tc) { char *line[] = {"(", "typeattribute", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_typebounds(CuTest *tc) { char *line[] = {"(", "typebounds", "foo", "bar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_typebounds_neg(CuTest *tc) { char *line[] = {"(", "typebounds", "bar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_typepermissive(CuTest *tc) { char *line[] = {"(", "typepermissive", "foo", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_typepermissive_neg(CuTest *tc) { char *line[] = {"(", "typepermissive", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_nametypetransition(CuTest *tc) { char *line[] = {"(", "nametypetransition", "str", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_nametypetransition_neg(CuTest *tc) { char *line[] = {"(", "nametypetransition", "str", "foo", "bar", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_rangetransition(CuTest *tc) { char *line[] = {"(", "rangetransition", "type_a", "type_b", "class", "(", "low_l", "high_l", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 1, finished); } void test_cil_build_ast_node_helper_rangetransition_neg(CuTest *tc) { char *line[] = {"(", "rangetransition", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_boolif(CuTest *tc) { char *line[] = {"(", "booleanif", "(", "and", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "read", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_boolif_neg(CuTest *tc) { char *line[] = {"(", "booleanif", "(", "*&", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "read", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_condblock_true(CuTest *tc) { char *line[] = {"(", "true", "(", "allow", "foo", "bar", "baz", "(", "write", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_condblock_true_neg(CuTest *tc) { char *line[] = {"(", "true", "(", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_condblock_false(CuTest *tc) { char *line[] = {"(", "false", "(", "allow", "foo", "bar", "baz", "(", "write", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_condblock_false_neg(CuTest *tc) { char *line[] = {"(", "false", "(", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_tunif(CuTest *tc) { char *line[] = {"(", "tunableif", "(", "and", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "read", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_tunif_neg(CuTest *tc) { char *line[] = {"(", "tunableif", "(", "*&", "foo", "bar", ")", "(", "allow", "foo", "bar", "read", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_typealias(CuTest *tc) { char *line[] = {"(", "typealias", ".test.type", "type_t", ")", "(", "type", "test", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_typealias_notype_neg(CuTest *tc) { char *line[] = {"(", "typealias", ".test.type", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_typeattribute(CuTest *tc) { char *line[] = {"(", "typeattribute", "type", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_typeattribute_neg(CuTest *tc) { char *line[] = {"(", "typeattribute", ".fail.type", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_typeattributeset(CuTest *tc) { char *line[] = {"(", "typeattributeset", "filetypes", "(", "and", "test_t", "test2_t", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 1, finished); } void test_cil_build_ast_node_helper_typeattributeset_neg(CuTest *tc) { char *line[] = {"(", "typeattributeset", "files", "(", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_userbounds(CuTest *tc) { char *line[] = {"(", "userbounds", "user1", "user2", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_userbounds_neg(CuTest *tc) { char *line[] = {"(", "userbounds", "user1", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_role(CuTest *tc) { char *line[] = {"(", "role", "test_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_role_neg(CuTest *tc) { char *line[] = {"(", "role", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_roletransition(CuTest *tc) { char *line[] = {"(", "roletransition", "foo_r", "bar_t", "process", "foobar_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_roletransition_neg(CuTest *tc) { char *line[] = {"(", "roletransition", "foo_r", "bar_t", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_roleallow(CuTest *tc) { char *line[] = {"(", "roleallow", "staff_r", "sysadm_r", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_roleallow_neg(CuTest *tc) { char *line[] = {"(", "roleallow", "staff_r", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_rolebounds(CuTest *tc) { char *line[] = {"(", "rolebounds", "role1", "role2", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_rolebounds_neg(CuTest *tc) { char *line[] = {"(", "rolebounds", "role1", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_avrule_allow(CuTest *tc) { char *line[] = {"(", "allow", "test", "foo", "(", "bar", "(", "read", "write", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 1, finished); } void test_cil_build_ast_node_helper_avrule_allow_neg(CuTest *tc) { char *line[] = {"(", "allow", "foo", "bar", "(", "read", "write", ")", "blah", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_avrule_auditallow(CuTest *tc) { char *line[] = {"(", "auditallow", "test", "foo", "(", "bar", "(", "read", "write", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 1, finished); } void test_cil_build_ast_node_helper_avrule_auditallow_neg(CuTest *tc) { char *line[] = {"(", "auditallow", "foo", "bar", "(", "read", "write", ")", "blah", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_avrule_dontaudit(CuTest *tc) { char *line[] = {"(", "dontaudit", "test", "foo", "(", "bar", "(", "read", "write", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 1, finished); } void test_cil_build_ast_node_helper_avrule_dontaudit_neg(CuTest *tc) { char *line[] = {"(", "dontaudit", "foo", "bar", "(", "read", "write", ")", "blah", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_avrule_neverallow(CuTest *tc) { char *line[] = {"(", "neverallow", "test", "foo", "(", "bar", "(", "read", "write", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 1, finished); } void test_cil_build_ast_node_helper_avrule_neverallow_neg(CuTest *tc) { char *line[] = {"(", "neverallow", "foo", "bar", "(", "read", "write", ")", "blah", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_type_rule_transition(CuTest *tc) { char *line[] = {"(", "typetransition", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_type_rule_transition_neg(CuTest *tc) { char *line[] = {"(", "typetransition", "foo", "bar", "file", "foobar", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_type_rule_change(CuTest *tc) { char *line[] = {"(", "typechange", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_type_rule_change_neg(CuTest *tc) { char *line[] = {"(", "typechange", "foo", "bar", "file", "foobar", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_type_rule_member(CuTest *tc) { char *line[] = {"(", "typemember", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_type_rule_member_neg(CuTest *tc) { char *line[] = {"(", "typemember", "foo", "bar", "file", "foobar", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_bool(CuTest *tc) { char *line[] = {"(", "boolean", "foo", "true", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_bool_neg(CuTest *tc) { char *line[] = {"(", "boolean", "foo", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_bool_tunable(CuTest *tc) { char *line[] = {"(", "tunable", "foo", "true", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_bool_tunable_neg(CuTest *tc) { char *line[] = {"(", "tunable", "foo", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_sensitivity(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_sensitivity_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_sensalias(CuTest *tc) { char *line[] = {"(", "sensitivityalias", "s0", "alias", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_sensalias_neg(CuTest *tc) { char *line[] = {"(", "sensitivityalias", "s0", "alias", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_category(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_category_neg(CuTest *tc) { char *line[] = {"(", "category", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_catset(CuTest *tc) { char *line[] = {"(", "categoryset", "somecats", "(", "c0", "c1", "c2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 1, finished); } void test_cil_build_ast_node_helper_catset_neg(CuTest *tc) { char *line[] = {"(", "categoryset", "somecats", "(", "c0", "c1", "c2", ")", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_catorder(CuTest *tc) { char *line[] = {"(", "categoryorder", "(", "c0", "c1", "c2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 1, finished); } void test_cil_build_ast_node_helper_catorder_neg(CuTest *tc) { char *line[] = {"(", "categoryorder", "c0", "c1", "c2", "extra", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_catalias(CuTest *tc) { char *line[] = {"(", "categoryalias", "c0", "red", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_catalias_neg(CuTest *tc) { char *line[] = {"(", "categoryalias", "range", "(", "c0", "c1", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_catrange(CuTest *tc) { char *line[] = {"(", "categoryrange", "range", "(", "c0", "c1", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 1, finished); } void test_cil_build_ast_node_helper_catrange_neg(CuTest *tc) { char *line[] = {"(", "categoryrange", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_build_ast_node_helper_roletype(CuTest *tc) { char *line[] = {"(", "roletype", "admin_r", "admin_t", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_build_ast_node_helper_roletype_neg(CuTest *tc) { char *line[] = {"(", "roletype", "(", "admin_r", ")", "admin_t", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_build_ast_node_helper_userrole(CuTest *tc) { char *line[] = {"(", "userrole", "staff_u", "staff_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, 0, finished); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_build_ast_node_helper_userrole_neg(CuTest *tc) { char *line[] = {"(", "userrole", "staff_u", "(", "staff_r", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_build_ast_node_helper_gen_classcommon(CuTest *tc) { char *line[] = {"(", "classcommon", "foo", "foo", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_build_ast_node_helper_gen_classcommon_neg(CuTest *tc) { char *line[] = {"(", "classcommon", "staff_u", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_build_ast_node_helper_gen_dominance(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "sensitivity", "s1", ")", "(", "sensitivity", "s2", ")", "(", "dominance", "(", "s0", "s1", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->next->next->next->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 1); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_build_ast_node_helper_gen_dominance_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "sensitivity", "s1", ")", "(", "sensitivity", "s2", ")", "(", "dominance", "(", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->next->next->next->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_build_ast_node_helper_gen_senscat(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "sensitivity", "s1", ")", "(", "dominance", "(", "s0", "s1", ")", ")", "(", "category", "c0", ")", "(", "category", "c255", ")", "(", "categoryorder", "(", "c0", "c255", ")", ")", "(", "sensitivitycategory", "s1", "(", "c0", "c255", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->next->next->next->next->next->next->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 1); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_build_ast_node_helper_gen_senscat_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "sensitivity", "s1", ")", "(", "dominance", "(", "s0", "s1", ")", ")", "(", "category", "c0", ")", "(", "category", "c255", ")", "(", "categoryorder", "(", "c0", "c255", ")", ")", "(", "sensitivitycategory", "s1", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->next->next->next->next->next->next->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_build_ast_node_helper_gen_level(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c1", ")", "(", "level", "low", "(", "s0", "(", "c1", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->next->next->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 1); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_build_ast_node_helper_gen_level_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c1", ")", "(", "level", "low", "(", "s0", "(", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->next->next->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_build_ast_node_helper_gen_levelrange(CuTest *tc) { char *line[] = {"(", "levelrange", "range", "(", "low", "high", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 1); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_build_ast_node_helper_gen_levelrange_neg(CuTest *tc) { char *line[] = {"(", "levelrange", "range", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_build_ast_node_helper_gen_constrain(CuTest *tc) { char *line[] = {"(", "constrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "r1", "r2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 1); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_build_ast_node_helper_gen_constrain_neg(CuTest *tc) { char *line[] = {"(", "constrain", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_build_ast_node_helper_gen_mlsconstrain(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "l2", "h2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 1); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_build_ast_node_helper_gen_mlsconstrain_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_build_ast_node_helper_gen_context(CuTest *tc) { char *line[] = {"(", "context", "localhost_node_label", "(", "system_u", "object_r", "node_lo_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 1); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_build_ast_node_helper_gen_context_neg(CuTest *tc) { char *line[] = {"(", "context", "localhost_node_label", "(", "system_u", "object_r", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_build_ast_node_helper_gen_filecon(CuTest *tc) { char *line[] = {"(", "filecon", "root", "path", "file", "context", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 1); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_build_ast_node_helper_gen_filecon_neg(CuTest *tc) { char *line[] = {"(", "filecon", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_build_ast_node_helper_gen_portcon(CuTest *tc) { char *line[] = {"(", "portcon", "udp", "25", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 1); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_build_ast_node_helper_gen_portcon_neg(CuTest *tc) { char *line[] = {"(", "portcon", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_build_ast_node_helper_gen_nodecon(CuTest *tc) { char *line[] = {"(", "nodecon", "ipaddr", "ipaddr", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 1); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_build_ast_node_helper_gen_nodecon_neg(CuTest *tc) { char *line[] = {"(", "nodecon", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_build_ast_node_helper_gen_genfscon(CuTest *tc) { char *line[] = {"(", "genfscon", "type", "path", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 1); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_build_ast_node_helper_gen_genfscon_neg(CuTest *tc) { char *line[] = {"(", "genfscon", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_build_ast_node_helper_gen_netifcon(CuTest *tc) { char *line[] = {"(", "netifcon", "eth1", "(", "system_u", "object_r", "netif_t", "(", "low", "high", ")", ")", "(", "system_u", "object_r", "netif_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 1); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_build_ast_node_helper_gen_netifcon_neg(CuTest *tc) { char *line[] = {"(", "netifcon", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_build_ast_node_helper_gen_pirqcon(CuTest *tc) { char *line[] = {"(", "pirqcon", "1", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 1); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_build_ast_node_helper_gen_pirqcon_neg(CuTest *tc) { char *line[] = {"(", "pirqcon", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_build_ast_node_helper_gen_iomemcon(CuTest *tc) { char *line[] = {"(", "iomemcon", "1", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 1); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_build_ast_node_helper_gen_iomemcon_neg(CuTest *tc) { char *line[] = {"(", "iomemcon", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_build_ast_node_helper_gen_ioportcon(CuTest *tc) { char *line[] = {"(", "ioportcon", "1", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 1); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_build_ast_node_helper_gen_ioportcon_neg(CuTest *tc) { char *line[] = {"(", "ioportcon", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_build_ast_node_helper_gen_pcidevicecon(CuTest *tc) { char *line[] = {"(", "pcidevicecon", "1", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 1); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_build_ast_node_helper_gen_pcidevicecon_neg(CuTest *tc) { char *line[] = {"(", "pcidevicecon", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_build_ast_node_helper_gen_fsuse(CuTest *tc) { char *line[] = {"(", "fsuse", "xattr", "ext3", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 1); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_build_ast_node_helper_gen_fsuse_neg(CuTest *tc) { char *line[] = {"(", "fsuse", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_build_ast_node_helper_gen_macro(CuTest *tc) { char *line[] = {"(", "macro", "mm", "(", "(", "type", "a", ")", ")", "(", "type", "b", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_build_ast_node_helper_gen_macro_neg(CuTest *tc) { char *line[] = {"(", "macro", "mm", "(", "(", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_build_ast_node_helper_gen_macro_nested_macro_neg(CuTest *tc) { char *line[] = {"(", "macro", "mm", "(", "(", "type", "a", ")", ")", "(", "type", "b", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_macro *macro; cil_macro_init(¯o); struct cil_tree_node *macronode; cil_tree_node_init(¯onode); macronode->data = macro; macronode->flavor = CIL_MACRO; uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, macronode, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); cil_db_destroy(&test_db); cil_destroy_macro(macro); } void test_cil_build_ast_node_helper_gen_macro_nested_tunif_neg(CuTest *tc) { char *line[] = {"(", "tunableif", "(", "and", "foo", "bar", ")", "(", "allow", "foo", "bar", "(", "read", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_macro *macro; cil_macro_init(¯o); struct cil_tree_node *macronode; cil_tree_node_init(¯onode); macronode->data = macro; macronode->flavor = CIL_MACRO; uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, macronode, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); cil_db_destroy(&test_db); cil_destroy_macro(macro); } void test_cil_build_ast_node_helper_gen_call(CuTest *tc) { char *line[] = {"(", "call", "mm", "(", "foo", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 1); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_build_ast_node_helper_gen_call_neg(CuTest *tc) { char *line[] = {"(", "call", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_build_ast_node_helper_gen_optional(CuTest *tc) { char *line[] = {"(", "optional", "opt", "(", "allow", "foo", "bar", "(", "file", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_build_ast_node_helper_gen_optional_neg(CuTest *tc) { char *line[] = {"(", "optional", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_build_ast_node_helper_gen_policycap(CuTest *tc) { char *line[] = {"(", "policycap", "open_perms", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 1); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_build_ast_node_helper_gen_policycap_neg(CuTest *tc) { char *line[] = {"(", "policycap", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_build_ast_node_helper_gen_ipaddr(CuTest *tc) { char *line[] = {"(", "ipaddr", "ip", "192.168.1.1", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_build_ast_node_helper_gen_ipaddr_neg(CuTest *tc) { char *line[] = {"(", "ipaddr", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_build_ast_node_helper_extraargsnull_neg(CuTest *tc) { char *line[] = {"(", "ipaddr", "ip", "192.168.1.1", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_args_build *extra_args = NULL; uint32_t finished = 0; int rc = __cil_build_ast_node_helper(test_tree->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_build_ast_last_child_helper(CuTest *tc) { char *line[] = {"(", "ipaddr", "ip", "192.168.1.1", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_args_build *extra_args = gen_build_args(test_db->ast->root, test_db, NULL, NULL); int rc = __cil_build_ast_last_child_helper(test_tree->root->cl_head->cl_head, extra_args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_build_ast_last_child_helper_extraargsnull_neg(CuTest *tc) { char *line[] = {"(", "ipaddr", "ip", "192.168.1.1", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); int rc = __cil_build_ast_last_child_helper(test_tree->root->cl_head->cl_head, NULL); CuAssertIntEquals(tc, SEPOL_ERR, rc); } libsepol-3.8.1/cil/test/unit/test_cil_build_ast.h000066400000000000000000001562351476211737200220740ustar00rootroot00000000000000/* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #ifndef TEST_CIL_BUILD_AST_H_ #define TEST_CIL_BUILD_AST_H_ #include "CuTest.h" void test_cil_parse_to_list(CuTest *); void test_cil_parse_to_list_currnull_neg(CuTest *); void test_cil_parse_to_list_listnull_neg(CuTest *); void test_cil_set_to_list(CuTest *); void test_cil_set_to_list_tree_node_null_neg(CuTest *); void test_cil_set_to_list_cl_head_null_neg(CuTest *); void test_cil_set_to_list_listnull_neg(CuTest *); void test_cil_gen_block(CuTest *); void test_cil_gen_block_justblock_neg(CuTest *); void test_cil_gen_block_noname_neg(CuTest *); void test_cil_gen_block_dbnull_neg(CuTest *); void test_cil_gen_block_treenull_neg(CuTest *); void test_cil_gen_block_nodenull_neg(CuTest *); void test_cil_gen_block_nodeparentnull_neg(CuTest *); void test_cil_destroy_block(CuTest *); void test_cil_gen_blockinherit(CuTest *); void test_cil_gen_blockinherit_namelist_neg(CuTest *); void test_cil_gen_blockinherit_namenull_neg(CuTest *); void test_cil_gen_blockinherit_extra_neg(CuTest *); void test_cil_gen_blockinherit_dbnull_neg(CuTest *); void test_cil_gen_blockinherit_currnull_neg(CuTest *); void test_cil_gen_blockinherit_astnull_neg(CuTest *); void test_cil_gen_perm(CuTest *); void test_cil_gen_perm_noname_neg(CuTest *); void test_cil_gen_perm_dbnull_neg(CuTest *); void test_cil_gen_perm_currnull_neg(CuTest *); void test_cil_gen_perm_astnull_neg(CuTest *); void test_cil_gen_perm_nodenull_neg(CuTest *); void test_cil_gen_permset(CuTest *); void test_cil_gen_permset_noname_neg(CuTest *); void test_cil_gen_permset_nameinparens_neg(CuTest *); void test_cil_gen_permset_noperms_neg(CuTest *); void test_cil_gen_permset_emptyperms_neg(CuTest *); void test_cil_gen_permset_extra_neg(CuTest *); void test_cil_gen_permset_dbnull_neg(CuTest *); void test_cil_gen_permset_currnull_neg(CuTest *); void test_cil_gen_permset_astnull_neg(CuTest *); void test_cil_gen_perm_nodes(CuTest *); void test_cil_gen_perm_nodes_failgen_neg(CuTest *); void test_cil_gen_perm_nodes_inval_perm_neg(CuTest *); void test_cil_fill_permset(CuTest *); void test_cil_fill_permset_sublist_neg(CuTest *); void test_cil_fill_permset_startpermnull_neg(CuTest *); void test_cil_fill_permset_permsetnull_neg(CuTest *); void test_cil_gen_in(CuTest *); void test_cil_gen_in_blockstrnull_neg(CuTest *); void test_cil_gen_in_extra_neg(CuTest *); void test_cil_gen_in_dbnull_neg(CuTest *); void test_cil_gen_in_currnull_neg(CuTest *); void test_cil_gen_in_astnull_neg(CuTest *); void test_cil_gen_class(CuTest *); void test_cil_gen_class_noname_neg(CuTest *); void test_cil_gen_class_nodenull_neg(CuTest *); void test_cil_gen_class_dbnull_neg(CuTest *); void test_cil_gen_class_currnull_neg(CuTest *); void test_cil_gen_class_noclass_neg(CuTest *); void test_cil_gen_class_noclassname_neg(CuTest *); void test_cil_gen_class_namesublist_neg(CuTest *); void test_cil_gen_class_noperms(CuTest *); void test_cil_gen_class_permsnotinlist_neg(CuTest *); void test_cil_gen_class_extrapermlist_neg(CuTest *); void test_cil_gen_class_listinlist_neg(CuTest *); void test_cil_fill_classpermset_anonperms(CuTest *); void test_cil_fill_classpermset_anonperms_neg(CuTest *); void test_cil_fill_classpermset_namedperms(CuTest *); void test_cil_fill_classpermset_extra_neg(CuTest *); void test_cil_fill_classpermset_emptypermslist_neg(CuTest *); void test_cil_fill_classpermset_noperms_neg(CuTest *); void test_cil_fill_classpermset_noclass_neg(CuTest *); void test_cil_fill_classpermset_classnodenull_neg(CuTest *); void test_cil_fill_classpermset_cpsnull_neg(CuTest *); void test_cil_gen_classpermset(CuTest *); void test_cil_gen_classpermset_noname_neg(CuTest *); void test_cil_gen_classpermset_nameinparens_neg(CuTest *); void test_cil_gen_classpermset_noclass_neg(CuTest *); void test_cil_gen_classpermset_noperms_neg(CuTest *); void test_cil_gen_classpermset_emptyperms_neg(CuTest *); void test_cil_gen_classpermset_extra_neg(CuTest *); void test_cil_gen_classpermset_dbnull_neg(CuTest *); void test_cil_gen_classpermset_currnull_neg(CuTest *); void test_cil_gen_classpermset_astnull_neg(CuTest *); void test_cil_gen_classmap_perm(CuTest *); void test_cil_gen_classmap_perm_dupeperm_neg(CuTest *); void test_cil_gen_classmap_perm_dbnull_neg(CuTest *tc); void test_cil_gen_classmap_perm_currnull_neg(CuTest *tc); void test_cil_gen_classmap_perm_astnull_neg(CuTest *tc); void test_cil_gen_classmap(CuTest *); void test_cil_gen_classmap_extra_neg(CuTest *); void test_cil_gen_classmap_noname_neg(CuTest *); void test_cil_gen_classmap_emptyperms_neg(CuTest *); void test_cil_gen_classmap_dbnull_neg(CuTest *tc); void test_cil_gen_classmap_currnull_neg(CuTest *tc); void test_cil_gen_classmap_astnull_neg(CuTest *tc); void test_cil_gen_classmapping_anonpermset(CuTest *); void test_cil_gen_classmapping_anonpermset_neg(CuTest *); void test_cil_gen_classmapping_namedpermset(CuTest *); void test_cil_gen_classmapping_noclassmapname_neg(CuTest *); void test_cil_gen_classmapping_noclassmapperm_neg(CuTest *); void test_cil_gen_classmapping_nopermissionsets_neg(CuTest *); void test_cil_gen_classmapping_emptyperms_neg(CuTest *); void test_cil_gen_classmapping_dbnull_neg(CuTest *tc); void test_cil_gen_classmapping_currnull_neg(CuTest *tc); void test_cil_gen_classmapping_astnull_neg(CuTest *tc); void test_cil_gen_common(CuTest *); void test_cil_gen_common_dbnull_neg(CuTest *tc); void test_cil_gen_common_currnull_neg(CuTest *tc); void test_cil_gen_common_astnull_neg(CuTest *tc); void test_cil_gen_common_noname_neg(CuTest *tc); void test_cil_gen_common_twoperms_neg(CuTest *tc); void test_cil_gen_common_permsublist_neg(CuTest *tc); void test_cil_gen_common_noperms_neg(CuTest *tc); void test_cil_gen_sid(CuTest *); void test_cil_gen_sid_noname_neg(CuTest *); void test_cil_gen_sid_nameinparens_neg(CuTest *); void test_cil_gen_sid_extra_neg(CuTest *); void test_cil_gen_sid_dbnull_neg(CuTest *); void test_cil_gen_sid_currnull_neg(CuTest *); void test_cil_gen_sid_astnull_neg(CuTest *); void test_cil_gen_sidcontext(CuTest *); void test_cil_gen_sidcontext_namedcontext(CuTest *); void test_cil_gen_sidcontext_halfcontext_neg(CuTest *); void test_cil_gen_sidcontext_noname_neg(CuTest *); void test_cil_gen_sidcontext_empty_neg(CuTest *); void test_cil_gen_sidcontext_nocontext_neg(CuTest *); void test_cil_gen_sidcontext_dblname_neg(CuTest *); void test_cil_gen_sidcontext_dbnull_neg(CuTest *); void test_cil_gen_sidcontext_pcurrnull_neg(CuTest *); void test_cil_gen_sidcontext_astnodenull_neg(CuTest *); void test_cil_gen_type(CuTest *); void test_cil_gen_type_neg(CuTest *); void test_cil_gen_type_dbnull_neg(CuTest *tc); void test_cil_gen_type_currnull_neg(CuTest *tc); void test_cil_gen_type_astnull_neg(CuTest *tc); void test_cil_gen_type_extra_neg(CuTest *tc); void test_cil_gen_typeattribute(CuTest *); void test_cil_gen_typeattribute_dbnull_neg(CuTest *tc); void test_cil_gen_typeattribute_currnull_neg(CuTest *tc); void test_cil_gen_typeattribute_astnull_neg(CuTest *tc); void test_cil_gen_typeattribute_extra_neg(CuTest *tc); void test_cil_gen_typeattr(CuTest *); void test_cil_gen_typeattr_dbnull_neg(CuTest *); void test_cil_gen_typeattr_currnull_neg(CuTest *); void test_cil_gen_typeattr_astnull_neg(CuTest *); void test_cil_gen_typeattr_typenull_neg(CuTest *); void test_cil_gen_typeattr_attrnull_neg(CuTest *); void test_cil_gen_typeattr_attrlist_neg(CuTest *); void test_cil_gen_typeattr_extra_neg(CuTest *); void test_cil_gen_typebounds(CuTest *); void test_cil_gen_typebounds_notype1_neg(CuTest *); void test_cil_gen_typebounds_type1inparens_neg(CuTest *); void test_cil_gen_typebounds_notype2_neg(CuTest *); void test_cil_gen_typebounds_type2inparens_neg(CuTest *); void test_cil_gen_typebounds_extra_neg(CuTest *); void test_cil_gen_typebounds_dbnull_neg(CuTest *); void test_cil_gen_typebounds_currnull_neg(CuTest *); void test_cil_gen_typebounds_astnull_neg(CuTest *); void test_cil_gen_typepermissive(CuTest *); void test_cil_gen_typepermissive_noname_neg(CuTest *); void test_cil_gen_typepermissive_typeinparens_neg(CuTest *); void test_cil_gen_typepermissive_extra_neg(CuTest *); void test_cil_gen_typepermissive_dbnull_neg(CuTest *); void test_cil_gen_typepermissive_currnull_neg(CuTest *); void test_cil_gen_typepermissive_astnull_neg(CuTest *); void test_cil_gen_nametypetransition(CuTest *); void test_cil_gen_nametypetransition_nostr_neg(CuTest *); void test_cil_gen_nametypetransition_strinparens_neg(CuTest *); void test_cil_gen_nametypetransition_nosrc_neg(CuTest *); void test_cil_gen_nametypetransition_srcinparens_neg(CuTest *); void test_cil_gen_nametypetransition_notgt_neg(CuTest *); void test_cil_gen_nametypetransition_tgtinparens_neg(CuTest *); void test_cil_gen_nametypetransition_noclass_neg(CuTest *); void test_cil_gen_nametypetransition_classinparens_neg(CuTest *); void test_cil_gen_nametypetransition_nodest_neg(CuTest *); void test_cil_gen_nametypetransition_destinparens_neg(CuTest *); void test_cil_gen_nametypetransition_extra_neg(CuTest *); void test_cil_gen_nametypetransition_dbnull_neg(CuTest *); void test_cil_gen_nametypetransition_currnull_neg(CuTest *); void test_cil_gen_nametypetransition_astnull_neg(CuTest *); void test_cil_gen_rangetransition(CuTest *); void test_cil_gen_rangetransition_namedtransition(CuTest *); void test_cil_gen_rangetransition_anon_low_l(CuTest *); void test_cil_gen_rangetransition_anon_low_l_neg(CuTest *); void test_cil_gen_rangetransition_anon_high_l(CuTest *); void test_cil_gen_rangetransition_anon_high_l_neg(CuTest *); void test_cil_gen_rangetransition_dbnull_neg(CuTest *); void test_cil_gen_rangetransition_currnull_neg(CuTest *); void test_cil_gen_rangetransition_astnull_neg(CuTest *); void test_cil_gen_rangetransition_nofirsttype_neg(CuTest *); void test_cil_gen_rangetransition_firsttype_inparens_neg(CuTest *); void test_cil_gen_rangetransition_nosecondtype_neg(CuTest *); void test_cil_gen_rangetransition_secondtype_inparens_neg(CuTest *); void test_cil_gen_rangetransition_noclass_neg(CuTest *); void test_cil_gen_rangetransition_class_inparens_neg(CuTest *); void test_cil_gen_rangetransition_nolevel_l_neg(CuTest *); void test_cil_gen_rangetransition_nolevel_h_neg(CuTest *); void test_cil_gen_rangetransition_extra_neg(CuTest *); void test_cil_gen_expr_stack_and(CuTest *); void test_cil_gen_expr_stack_or(CuTest *); void test_cil_gen_expr_stack_xor(CuTest *); void test_cil_gen_expr_stack_not(CuTest *); void test_cil_gen_expr_stack_not_noexpr_neg(CuTest *); void test_cil_gen_expr_stack_not_extraexpr_neg(CuTest *); void test_cil_gen_expr_stack_eq(CuTest *); void test_cil_gen_expr_stack_neq(CuTest *); void test_cil_gen_expr_stack_nested(CuTest *); void test_cil_gen_expr_stack_nested_neg(CuTest *); void test_cil_gen_expr_stack_nested_emptyargs_neg(CuTest *); void test_cil_gen_expr_stack_nested_missingoperator_neg(CuTest *); void test_cil_gen_expr_stack_arg1null_neg(CuTest *); void test_cil_gen_expr_stack_arg2null_neg(CuTest *); void test_cil_gen_expr_stack_extraarg_neg(CuTest *); void test_cil_gen_expr_stack_currnull_neg(CuTest *); void test_cil_gen_expr_stack_stacknull_neg(CuTest *); void test_cil_gen_boolif_multiplebools_true(CuTest *); void test_cil_gen_boolif_multiplebools_false(CuTest *); void test_cil_gen_boolif_multiplebools_unknowncond_neg(CuTest *); void test_cil_gen_boolif_true(CuTest *); void test_cil_gen_boolif_false(CuTest *); void test_cil_gen_boolif_unknowncond_neg(CuTest *); void test_cil_gen_boolif_nested(CuTest *); void test_cil_gen_boolif_nested_neg(CuTest *); void test_cil_gen_boolif_extra_neg(CuTest *); void test_cil_gen_boolif_extra_parens_neg(CuTest *); void test_cil_gen_boolif_nocond(CuTest *); void test_cil_gen_boolif_neg(CuTest *); void test_cil_gen_boolif_dbnull_neg(CuTest *); void test_cil_gen_boolif_currnull_neg(CuTest *); void test_cil_gen_boolif_astnull_neg(CuTest *); void test_cil_gen_boolif_nocond_neg(CuTest *); void test_cil_gen_boolif_notruelist_neg(CuTest *); void test_cil_gen_boolif_empty_cond_neg(CuTest *); void test_cil_gen_else(CuTest *); void test_cil_gen_else_neg(CuTest *); void test_cil_gen_else_dbnull_neg(CuTest *); void test_cil_gen_else_currnull_neg(CuTest *); void test_cil_gen_else_astnull_neg(CuTest *); void test_cil_gen_tunif_multiplebools_true(CuTest *); void test_cil_gen_tunif_multiplebools_false(CuTest *); void test_cil_gen_tunif_multiplebools_unknowncond_neg(CuTest *); void test_cil_gen_tunif_true(CuTest *); void test_cil_gen_tunif_false(CuTest *); void test_cil_gen_tunif_unknowncond_neg(CuTest *); void test_cil_gen_tunif_nocond(CuTest *); void test_cil_gen_tunif_nested(CuTest *); void test_cil_gen_tunif_nested_neg(CuTest *); void test_cil_gen_tunif_extra_neg(CuTest *); void test_cil_gen_tunif_extra_parens_neg(CuTest *); void test_cil_gen_tunif_neg(CuTest *); void test_cil_gen_tunif_dbnull_neg(CuTest *); void test_cil_gen_tunif_currnull_neg(CuTest *); void test_cil_gen_tunif_astnull_neg(CuTest *); void test_cil_gen_tunif_nocond_neg(CuTest *); void test_cil_gen_tunif_notruelist_neg(CuTest *); void test_cil_gen_condblock_true(CuTest *); void test_cil_gen_condblock_false(CuTest *); void test_cil_gen_condblock_dbnull_neg(CuTest *); void test_cil_gen_condblock_currnull_neg(CuTest *); void test_cil_gen_condblock_astnull_neg(CuTest *); void test_cil_gen_condblock_nocond_neg(CuTest *); void test_cil_gen_condblock_extra_neg(CuTest *); void test_cil_gen_typealias(CuTest *); void test_cil_gen_typealias_incomplete_neg(CuTest *); void test_cil_gen_typealias_incomplete_neg2(CuTest *); void test_cil_gen_typealias_extratype_neg(CuTest *); void test_cil_gen_typealias_dbnull_neg(CuTest *tc); void test_cil_gen_typealias_currnull_neg(CuTest *tc); void test_cil_gen_typealias_astnull_neg(CuTest *tc); void test_cil_gen_typeattributeset(CuTest *); void test_cil_gen_typeattributeset_and_two_types(CuTest *); void test_cil_gen_typeattributeset_not(CuTest *); void test_cil_gen_typeattributeset_exclude_attr(CuTest *); void test_cil_gen_typeattributeset_exclude_neg(CuTest *); void test_cil_gen_typeattributeset_dbnull_neg(CuTest *); void test_cil_gen_typeattributeset_currnull_neg(CuTest *); void test_cil_gen_typeattributeset_astnull_neg(CuTest *); void test_cil_gen_typeattributeset_noname_neg(CuTest *); void test_cil_gen_typeattributeset_nameinparens_neg(CuTest *); void test_cil_gen_typeattributeset_emptylists_neg(CuTest *); void test_cil_gen_typeattributeset_listinparens_neg(CuTest *); void test_cil_gen_typeattributeset_extra_neg(CuTest *); void test_cil_gen_userbounds(CuTest *); void test_cil_gen_userbounds_notype1_neg(CuTest *); void test_cil_gen_userbounds_type1_inparens_neg(CuTest *); void test_cil_gen_userbounds_notype2_neg(CuTest *); void test_cil_gen_userbounds_type2_inparens_neg(CuTest *); void test_cil_gen_userbounds_extra_neg(CuTest *); void test_cil_gen_userbounds_dbnull_neg(CuTest *); void test_cil_gen_userbounds_currnull_neg(CuTest *); void test_cil_gen_userbounds_astnull_neg(CuTest *); void test_cil_gen_role(CuTest *); void test_cil_gen_role_dbnull_neg(CuTest *tc); void test_cil_gen_role_currnull_neg(CuTest *tc); void test_cil_gen_role_astnull_neg(CuTest *tc); void test_cil_gen_role_extrarole_neg(CuTest *tc); void test_cil_gen_role_noname_neg(CuTest *tc); void test_cil_gen_roletransition(CuTest *); void test_cil_gen_roletransition_currnull_neg(CuTest *); void test_cil_gen_roletransition_astnull_neg(CuTest *); void test_cil_gen_roletransition_srcnull_neg(CuTest *); void test_cil_gen_roletransition_tgtnull_neg(CuTest *); void test_cil_gen_roletransition_resultnull_neg(CuTest *); void test_cil_gen_roletransition_extra_neg(CuTest *); void test_cil_gen_bool_true(CuTest *); void test_cil_gen_bool_tunable_true(CuTest *); void test_cil_gen_bool_false(CuTest *); void test_cil_gen_bool_tunable_false(CuTest *); void test_cil_gen_bool_none_neg(CuTest *); void test_cil_gen_bool_dbnull_neg(CuTest *); void test_cil_gen_bool_currnull_neg(CuTest *); void test_cil_gen_bool_astnull_neg(CuTest *); void test_cil_gen_bool_notbool_neg(CuTest *); void test_cil_gen_bool_boolname_neg(CuTest *); void test_cil_gen_bool_extraname_false_neg(CuTest *); void test_cil_gen_bool_extraname_true_neg(CuTest *); void test_cil_gen_constrain_expr_stack_eq2_t1type(CuTest *); void test_cil_gen_constrain_expr_stack_eq2_t1t1_neg(CuTest *); void test_cil_gen_constrain_expr_stack_eq2_t2type(CuTest *); void test_cil_gen_constrain_expr_stack_eq2_t2t2_neg(CuTest *); void test_cil_gen_constrain_expr_stack_eq2_r1role(CuTest *); void test_cil_gen_constrain_expr_stack_eq2_r1r1_neg(CuTest *); void test_cil_gen_constrain_expr_stack_eq2_r2role(CuTest *); void test_cil_gen_constrain_expr_stack_eq2_r2r2_neg(CuTest *); void test_cil_gen_constrain_expr_stack_eq2_t1t2(CuTest *); void test_cil_gen_constrain_expr_stack_eq_r1r2(CuTest *); void test_cil_gen_constrain_expr_stack_eq2_r1r2(CuTest *); void test_cil_gen_constrain_expr_stack_eq2_u1u2(CuTest *); void test_cil_gen_constrain_expr_stack_eq2_u1user(CuTest *); void test_cil_gen_constrain_expr_stack_eq2_u1u1_neg(CuTest *); void test_cil_gen_constrain_expr_stack_eq2_u2user(CuTest *); void test_cil_gen_constrain_expr_stack_eq2_u2u2_neg(CuTest *); void test_cil_gen_constrain_expr_stack_eq_l2h2(CuTest *); void test_cil_gen_constrain_expr_stack_eq_l2_neg(CuTest *); void test_cil_gen_constrain_expr_stack_eq_l1l2(CuTest *); void test_cil_gen_constrain_expr_stack_eq_l1h1(CuTest *); void test_cil_gen_constrain_expr_stack_eq_l1h2(CuTest *); void test_cil_gen_constrain_expr_stack_eq_h1l2(CuTest *); void test_cil_gen_constrain_expr_stack_eq_h1h2(CuTest *); void test_cil_gen_constrain_expr_stack_eq_h1_neg(CuTest *); void test_cil_gen_constrain_expr_stack_eq_l1l1_neg(CuTest *); void test_cil_gen_constrain_expr_stack_eq2_l1l2_constrain_neg(CuTest *); void test_cil_gen_constrain_expr_stack_eq_l1l2_constrain_neg(CuTest *); void test_cil_gen_constrain_expr_stack_eq_leftkeyword_neg(CuTest *); void test_cil_gen_constrain_expr_stack_eq_noexpr1_neg(CuTest *); void test_cil_gen_constrain_expr_stack_eq_expr1inparens_neg(CuTest *); void test_cil_gen_constrain_expr_stack_eq_noexpr2_neg(CuTest *); void test_cil_gen_constrain_expr_stack_eq_expr2inparens_neg(CuTest *); void test_cil_gen_constrain_expr_stack_eq_extraexpr_neg(CuTest *); void test_cil_gen_constrain_expr_stack_eq2(CuTest *); void test_cil_gen_constrain_expr_stack_eq2_noexpr1_neg(CuTest *); void test_cil_gen_constrain_expr_stack_eq2_expr1inparens_neg(CuTest *); void test_cil_gen_constrain_expr_stack_eq2_noexpr2_neg(CuTest *); void test_cil_gen_constrain_expr_stack_eq2_expr2inparens_neg(CuTest *); void test_cil_gen_constrain_expr_stack_eq2_extraexpr_neg(CuTest *); void test_cil_gen_constrain_expr_stack_noteq(CuTest *); void test_cil_gen_constrain_expr_stack_noteq_noexpr1_neg(CuTest *); void test_cil_gen_constrain_expr_stack_noteq_expr1inparens_neg(CuTest *); void test_cil_gen_constrain_expr_stack_noteq_noexpr2_neg(CuTest *); void test_cil_gen_constrain_expr_stack_noteq_expr2inparens_neg(CuTest *); void test_cil_gen_constrain_expr_stack_noteq_extraexpr_neg(CuTest *); void test_cil_gen_constrain_expr_stack_not(CuTest *); void test_cil_gen_constrain_expr_stack_not_noexpr_neg(CuTest *); void test_cil_gen_constrain_expr_stack_not_emptyparens_neg(CuTest *); void test_cil_gen_constrain_expr_stack_not_extraparens_neg(CuTest *); void test_cil_gen_constrain_expr_stack_or(CuTest *); void test_cil_gen_constrain_expr_stack_or_neg(CuTest *); void test_cil_gen_constrain_expr_stack_or_noexpr_neg(CuTest *); void test_cil_gen_constrain_expr_stack_or_emptyfirstparens_neg(CuTest *); void test_cil_gen_constrain_expr_stack_or_missingsecondexpr_neg(CuTest *); void test_cil_gen_constrain_expr_stack_or_emptysecondparens_neg(CuTest *); void test_cil_gen_constrain_expr_stack_or_extraexpr_neg(CuTest *); void test_cil_gen_constrain_expr_stack_and(CuTest *); void test_cil_gen_constrain_expr_stack_and_neg(CuTest *); void test_cil_gen_constrain_expr_stack_and_noexpr_neg(CuTest *); void test_cil_gen_constrain_expr_stack_and_emptyfirstparens_neg(CuTest *); void test_cil_gen_constrain_expr_stack_and_missingsecondexpr_neg(CuTest *); void test_cil_gen_constrain_expr_stack_and_emptysecondparens_neg(CuTest *); void test_cil_gen_constrain_expr_stack_and_extraexpr_neg(CuTest *); void test_cil_gen_constrain_expr_stack_dom(CuTest *); void test_cil_gen_constrain_expr_stack_dom_noexpr1_neg(CuTest *); void test_cil_gen_constrain_expr_stack_dom_expr1inparens_neg(CuTest *); void test_cil_gen_constrain_expr_stack_dom_noexpr2_neg(CuTest *); void test_cil_gen_constrain_expr_stack_dom_expr2inparens_neg(CuTest *); void test_cil_gen_constrain_expr_stack_dom_extraexpr_neg(CuTest *); void test_cil_gen_constrain_expr_stack_domby(CuTest *); void test_cil_gen_constrain_expr_stack_domby_noexpr1_neg(CuTest *); void test_cil_gen_constrain_expr_stack_domby_expr1inparens_neg(CuTest *); void test_cil_gen_constrain_expr_stack_domby_noexpr2_neg(CuTest *); void test_cil_gen_constrain_expr_stack_domby_expr2inparens_neg(CuTest *); void test_cil_gen_constrain_expr_stack_domby_extraexpr_neg(CuTest *); void test_cil_gen_constrain_expr_stack_incomp(CuTest *); void test_cil_gen_constrain_expr_stack_incomp_noexpr1_neg(CuTest *); void test_cil_gen_constrain_expr_stack_incomp_expr1inparens_neg(CuTest *); void test_cil_gen_constrain_expr_stack_incomp_noexpr2_neg(CuTest *); void test_cil_gen_constrain_expr_stack_incomp_expr2inparens_neg(CuTest *); void test_cil_gen_constrain_expr_stack_incomp_extraexpr_neg(CuTest *); void test_cil_gen_constrain_expr_stack_currnull_neg(CuTest *); void test_cil_gen_constrain_expr_stack_stacknull_neg(CuTest *); void test_cil_gen_constrain_expr_stack_operatorinparens_neg(CuTest *); void test_cil_gen_constrain_expr_stack_incorrectcall_neg(CuTest *); void test_cil_gen_roleallow(CuTest *); void test_cil_gen_roleallow_dbnull_neg(CuTest *); void test_cil_gen_roleallow_currnull_neg(CuTest *); void test_cil_gen_roleallow_astnull_neg(CuTest *); void test_cil_gen_roleallow_srcnull_neg(CuTest *); void test_cil_gen_roleallow_tgtnull_neg(CuTest *); void test_cil_gen_roleallow_extra_neg(CuTest *); void test_cil_gen_rolebounds(CuTest *); void test_cil_gen_rolebounds_norole1_neg(CuTest *); void test_cil_gen_rolebounds_role1_inparens_neg(CuTest *); void test_cil_gen_rolebounds_norole2_neg(CuTest *); void test_cil_gen_rolebounds_role2_inparens_neg(CuTest *); void test_cil_gen_rolebounds_extra_neg(CuTest *); void test_cil_gen_rolebounds_dbnull_neg(CuTest *); void test_cil_gen_rolebounds_currnull_neg(CuTest *); void test_cil_gen_rolebounds_astnull_neg(CuTest *); void test_cil_gen_avrule(CuTest *); void test_cil_gen_avrule_permset(CuTest *); void test_cil_gen_avrule_permset_anon(CuTest *); void test_cil_gen_avrule_extra_neg(CuTest *); void test_cil_gen_avrule_sourceparens(CuTest *); void test_cil_gen_avrule_sourceemptyparen_neg(CuTest *); void test_cil_gen_avrule_targetparens(CuTest *); void test_cil_gen_avrule_targetemptyparen_neg(CuTest *); void test_cil_gen_avrule_currnull_neg(CuTest *tc); void test_cil_gen_avrule_astnull_neg(CuTest *tc); void test_cil_gen_avrule_sourcedomainnull_neg(CuTest *tc); void test_cil_gen_avrule_targetdomainnull_neg(CuTest *tc); void test_cil_gen_avrule_objectclassnull_neg(CuTest *tc); void test_cil_gen_avrule_permsnull_neg(CuTest *tc); void test_cil_gen_avrule_twolists_neg(CuTest *); //TODO: add cases to cover parse_current->next->cl_head != NULL || parse_current->next->next->cl_head != NULL // || parse_current->next->next->next->cl_head != NULL void test_cil_gen_type_rule_transition(CuTest *); void test_cil_gen_type_rule_transition_currnull_neg(CuTest *); void test_cil_gen_type_rule_transition_astnull_neg(CuTest *); void test_cil_gen_type_rule_transition_srcnull_neg(CuTest *); void test_cil_gen_type_rule_transition_tgtnull_neg(CuTest *); void test_cil_gen_type_rule_transition_objnull_neg(CuTest *); void test_cil_gen_type_rule_transition_resultnull_neg(CuTest *); void test_cil_gen_type_rule_transition_extra_neg(CuTest *); void test_cil_gen_type_rule_change(CuTest *); void test_cil_gen_type_rule_change_currnull_neg(CuTest *); void test_cil_gen_type_rule_change_astnull_neg(CuTest *); void test_cil_gen_type_rule_change_srcnull_neg(CuTest *); void test_cil_gen_type_rule_change_tgtnull_neg(CuTest *); void test_cil_gen_type_rule_change_objnull_neg(CuTest *); void test_cil_gen_type_rule_change_resultnull_neg(CuTest *); void test_cil_gen_type_rule_change_extra_neg(CuTest *); void test_cil_gen_type_rule_member(CuTest *); void test_cil_gen_type_rule_member_currnull_neg(CuTest *); void test_cil_gen_type_rule_member_astnull_neg(CuTest *); void test_cil_gen_type_rule_member_srcnull_neg(CuTest *); void test_cil_gen_type_rule_member_tgtnull_neg(CuTest *); void test_cil_gen_type_rule_member_objnull_neg(CuTest *); void test_cil_gen_type_rule_member_resultnull_neg(CuTest *); void test_cil_gen_type_rule_member_extra_neg(CuTest *); void test_cil_gen_user(CuTest *); void test_cil_gen_user_dbnull_neg(CuTest *); void test_cil_gen_user_currnull_neg(CuTest *); void test_cil_gen_user_astnull_neg(CuTest *); void test_cil_gen_user_nouser_neg(CuTest *); void test_cil_gen_user_xsinfo_neg(CuTest *); void test_cil_gen_userlevel(CuTest *); void test_cil_gen_userlevel_anon_level(CuTest *); void test_cil_gen_userlevel_anon_level_neg(CuTest *); void test_cil_gen_userlevel_usernull_neg(CuTest *); void test_cil_gen_userlevel_userrange_neg(CuTest *); void test_cil_gen_userlevel_levelnull_neg(CuTest *); void test_cil_gen_userlevel_levelrangeempty_neg(CuTest *); void test_cil_gen_userlevel_extra_neg(CuTest *); void test_cil_gen_userlevel_dbnull_neg(CuTest *); void test_cil_gen_userlevel_currnull_neg(CuTest *); void test_cil_gen_userlevel_astnull_neg(CuTest *); void test_cil_gen_userrange_named(CuTest *); void test_cil_gen_userrange_anon(CuTest *); void test_cil_gen_userrange_usernull_neg(CuTest *); void test_cil_gen_userrange_anonuser_neg(CuTest *); void test_cil_gen_userrange_rangenamenull_neg(CuTest *); void test_cil_gen_userrange_anonrangeinvalid_neg(CuTest *); void test_cil_gen_userrange_anonrangeempty_neg(CuTest *); void test_cil_gen_userrange_extra_neg(CuTest *); void test_cil_gen_userrange_dbnull_neg(CuTest *); void test_cil_gen_userrange_currnull_neg(CuTest *); void test_cil_gen_userrange_astnull_neg(CuTest *); void test_cil_gen_sensitivity(CuTest *); void test_cil_gen_sensitivity_dbnull_neg(CuTest *); void test_cil_gen_sensitivity_currnull_neg(CuTest *); void test_cil_gen_sensitivity_astnull_neg(CuTest *); void test_cil_gen_sensitivity_sensnull_neg(CuTest *); void test_cil_gen_sensitivity_senslist_neg(CuTest *); void test_cil_gen_sensitivity_extra_neg(CuTest *); void test_cil_gen_sensalias(CuTest *); void test_cil_gen_sensalias_dbnull_neg(CuTest *); void test_cil_gen_sensalias_currnull_neg(CuTest *); void test_cil_gen_sensalias_astnull_neg(CuTest *); void test_cil_gen_sensalias_sensnull_neg(CuTest *); void test_cil_gen_sensalias_senslist_neg(CuTest *); void test_cil_gen_sensalias_aliasnull_neg(CuTest *); void test_cil_gen_sensalias_aliaslist_neg(CuTest *); void test_cil_gen_sensalias_extra_neg(CuTest *); void test_cil_gen_category(CuTest *); void test_cil_gen_category_dbnull_neg(CuTest *); void test_cil_gen_category_astnull_neg(CuTest *); void test_cil_gen_category_currnull_neg(CuTest *); void test_cil_gen_category_catnull_neg(CuTest *); void test_cil_gen_category_catlist_neg(CuTest *); void test_cil_gen_category_extra_neg(CuTest *); void test_cil_gen_catset(CuTest *); void test_cil_gen_catset_dbnull_neg(CuTest *); void test_cil_gen_catset_currnull_neg(CuTest *); void test_cil_gen_catset_astnull_neg(CuTest *); void test_cil_gen_catset_namenull_neg(CuTest *); void test_cil_gen_catset_setnull_neg(CuTest *); void test_cil_gen_catset_namelist_neg(CuTest *); void test_cil_gen_catset_extra_neg(CuTest *); void test_cil_gen_catset_nodefail_neg(CuTest *); void test_cil_gen_catset_notset_neg(CuTest *); void test_cil_gen_catset_settolistfail_neg(CuTest *); void test_cil_gen_catalias(CuTest *); void test_cil_gen_catalias_dbnull_neg(CuTest *); void test_cil_gen_catalias_currnull_neg(CuTest *); void test_cil_gen_catalias_astnull_neg(CuTest *); void test_cil_gen_catalias_catnull_neg(CuTest *); void test_cil_gen_catalias_aliasnull_neg(CuTest *); void test_cil_gen_catalias_extra_neg(CuTest *); void test_cil_gen_catrange(CuTest *); void test_cil_gen_catrange_noname_neg(CuTest *); void test_cil_gen_catrange_norange_neg(CuTest *); void test_cil_gen_catrange_emptyrange_neg(CuTest *); void test_cil_gen_catrange_extrarange_neg(CuTest *); void test_cil_gen_catrange_dbnull_neg(CuTest *); void test_cil_gen_catrange_currnull_neg(CuTest *); void test_cil_gen_catrange_astnull_neg(CuTest *); void test_cil_gen_catrange_extra_neg(CuTest *); void test_cil_gen_roletype(CuTest *tc); void test_cil_gen_roletype_currnull_neg(CuTest *tc); void test_cil_gen_roletype_dbnull_neg(CuTest *tc); void test_cil_gen_roletype_astnull_neg(CuTest *tc); void test_cil_gen_roletype_empty_neg(CuTest *tc); void test_cil_gen_roletype_rolelist_neg(CuTest *tc); void test_cil_gen_roletype_roletype_sublist_neg(CuTest *tc); void test_cil_gen_roletype_typelist_neg(CuTest *tc); void test_cil_gen_userrole(CuTest *tc); void test_cil_gen_userrole_currnull_neg(CuTest *tc); void test_cil_gen_userrole_dbnull_neg(CuTest *tc); void test_cil_gen_userrole_astnull_neg(CuTest *tc); void test_cil_gen_userrole_empty_neg(CuTest *tc); void test_cil_gen_userrole_userlist_neg(CuTest *tc); void test_cil_gen_userrole_userrole_sublist_neg(CuTest *tc); void test_cil_gen_userrole_rolelist_neg(CuTest *tc); void test_cil_gen_classcommon(CuTest *tc); void test_cil_gen_classcommon_dbnull_neg(CuTest *tc); void test_cil_gen_classcommon_currnull_neg(CuTest *tc); void test_cil_gen_classcommon_astnull_neg(CuTest *tc); void test_cil_gen_classcommon_missingclassname_neg(CuTest *tc); void test_cil_gen_classcommon_noperms_neg(CuTest *tc); void test_cil_gen_classcommon_extraperms_neg(CuTest *tc); void test_cil_gen_catorder(CuTest *tc); void test_cil_gen_catorder_dbnull_neg(CuTest *tc); void test_cil_gen_catorder_currnull_neg(CuTest *tc); void test_cil_gen_catorder_astnull_neg(CuTest *tc); void test_cil_gen_catorder_missingcats_neg(CuTest *tc); void test_cil_gen_catorder_nosublist_neg(CuTest *tc); void test_cil_gen_catorder_nestedcat_neg(CuTest *tc); void test_cil_gen_dominance(CuTest *tc); void test_cil_gen_dominance_dbnull_neg(CuTest *tc); void test_cil_gen_dominance_currnull_neg(CuTest *tc); void test_cil_gen_dominance_astnull_neg(CuTest *tc); void test_cil_gen_dominance_nosensitivities_neg(CuTest *tc); void test_cil_gen_dominance_nosublist_neg(CuTest *tc); void test_cil_gen_senscat(CuTest *tc); void test_cil_gen_senscat_nosublist(CuTest *); void test_cil_gen_senscat_dbnull_neg(CuTest *tc); void test_cil_gen_senscat_currnull_neg(CuTest *tc); void test_cil_gen_senscat_astnull_neg(CuTest *tc); void test_cil_gen_senscat_nosensitivities_neg(CuTest *tc); void test_cil_gen_senscat_sublist_neg(CuTest *); void test_cil_gen_senscat_nocat_neg(CuTest *); void test_cil_fill_level(CuTest *tc); void test_cil_fill_level_sensnull_neg(CuTest *tc); void test_cil_fill_level_levelnull_neg(CuTest *tc); void test_cil_fill_level_nocat(CuTest *tc); void test_cil_fill_level_emptycat_neg(CuTest *tc); void test_cil_gen_level(CuTest *tc); void test_cil_gen_level_nameinparens_neg(CuTest *tc); void test_cil_gen_level_emptysensparens_neg(CuTest *tc); void test_cil_gen_level_extra_neg(CuTest *tc); void test_cil_gen_level_emptycat_neg(CuTest *tc); void test_cil_gen_level_noname_neg(CuTest *tc); void test_cil_gen_level_nosens_neg(CuTest *tc); void test_cil_gen_level_dbnull_neg(CuTest *tc); void test_cil_gen_level_currnull_neg(CuTest *tc); void test_cil_gen_level_astnull_neg(CuTest *tc); void test_cil_gen_levelrange(CuTest *tc); void test_cil_gen_levelrange_rangeinvalid_neg(CuTest *tc); void test_cil_gen_levelrange_namenull_neg(CuTest *tc); void test_cil_gen_levelrange_rangenull_neg(CuTest *tc); void test_cil_gen_levelrange_rangeempty_neg(CuTest *tc); void test_cil_gen_levelrange_extra_neg(CuTest *tc); void test_cil_gen_levelrange_dbnull_neg(CuTest *tc); void test_cil_gen_levelrange_currnull_neg(CuTest *tc); void test_cil_gen_levelrange_astnull_neg(CuTest *tc); void test_cil_gen_constrain(CuTest *tc); void test_cil_gen_constrain_neg(CuTest *tc); void test_cil_gen_constrain_classset_neg(CuTest *tc); void test_cil_gen_constrain_classset_noclass_neg(CuTest *tc); void test_cil_gen_constrain_classset_noperm_neg(CuTest *tc); void test_cil_gen_constrain_permset_neg(CuTest *tc); void test_cil_gen_constrain_permset_noclass_neg(CuTest *tc); void test_cil_gen_constrain_permset_noperm_neg(CuTest *tc); void test_cil_gen_constrain_expression_neg(CuTest *tc); void test_cil_gen_constrain_dbnull_neg(CuTest *tc); void test_cil_gen_constrain_currnull_neg(CuTest *tc); void test_cil_gen_constrain_astnull_neg(CuTest *tc); void test_cil_fill_context(CuTest *tc); void test_cil_fill_context_unnamedlvl(CuTest *tc); void test_cil_fill_context_nocontext_neg(CuTest *tc); void test_cil_fill_context_nouser_neg(CuTest *tc); void test_cil_fill_context_norole_neg(CuTest *tc); void test_cil_fill_context_notype_neg(CuTest *tc); void test_cil_fill_context_nolowlvl_neg(CuTest *tc); void test_cil_fill_context_nohighlvl_neg(CuTest *tc); void test_cil_fill_context_unnamedlvl_nocontextlow_neg(CuTest *tc); void test_cil_fill_context_unnamedlvl_nocontexthigh_neg(CuTest *tc); void test_cil_gen_context(CuTest *tc); void test_cil_gen_context_notinparens_neg(CuTest *tc); void test_cil_gen_context_extralevel_neg(CuTest *tc); void test_cil_gen_context_emptycontext_neg(CuTest *tc); void test_cil_gen_context_extra_neg(CuTest *tc); void test_cil_gen_context_doubleparen_neg(CuTest *tc); void test_cil_gen_context_norole_neg(CuTest *tc); void test_cil_gen_context_roleinparens_neg(CuTest *tc); void test_cil_gen_context_notype_neg(CuTest *tc); void test_cil_gen_context_typeinparens_neg(CuTest *tc); void test_cil_gen_context_nolevels_neg(CuTest *tc); void test_cil_gen_context_nosecondlevel_neg(CuTest *tc); void test_cil_gen_context_noname_neg(CuTest *tc); void test_cil_gen_context_nouser_neg(CuTest *tc); void test_cil_gen_context_dbnull_neg(CuTest *tc); void test_cil_gen_context_currnull_neg(CuTest *tc); void test_cil_gen_context_astnull_neg(CuTest *tc); void test_cil_gen_filecon_file(CuTest *tc); void test_cil_gen_filecon_dir(CuTest *tc); void test_cil_gen_filecon_char(CuTest *tc); void test_cil_gen_filecon_block(CuTest *tc); void test_cil_gen_filecon_socket(CuTest *tc); void test_cil_gen_filecon_pipe(CuTest *tc); void test_cil_gen_filecon_symlink(CuTest *tc); void test_cil_gen_filecon_any(CuTest *tc); void test_cil_gen_filecon_neg(CuTest *tc); void test_cil_gen_filecon_anon_context(CuTest *tc); void test_cil_gen_filecon_dbnull_neg(CuTest *tc); void test_cil_gen_filecon_currnull_neg(CuTest *tc); void test_cil_gen_filecon_astnull_neg(CuTest *tc); void test_cil_gen_filecon_str1null_neg(CuTest *tc); void test_cil_gen_filecon_str1_inparens_neg(CuTest *tc); void test_cil_gen_filecon_str2null_neg(CuTest *tc); void test_cil_gen_filecon_str2_inparens_neg(CuTest *tc); void test_cil_gen_filecon_classnull_neg(CuTest *tc); void test_cil_gen_filecon_class_inparens_neg(CuTest *tc); void test_cil_gen_filecon_contextnull_neg(CuTest *tc); void test_cil_gen_filecon_context_neg(CuTest *tc); void test_cil_gen_filecon_extra_neg(CuTest *tc); void test_cil_gen_portcon_udp(CuTest *tc); void test_cil_gen_portcon_tcp(CuTest *tc); void test_cil_gen_portcon_unknownprotocol_neg(CuTest *tc); void test_cil_gen_portcon_anon_context(CuTest *tc); void test_cil_gen_portcon_portrange(CuTest *tc); void test_cil_gen_portcon_portrange_one_neg(CuTest *tc); void test_cil_gen_portcon_portrange_morethanone_neg(CuTest *tc); void test_cil_gen_portcon_singleport_neg(CuTest *tc); void test_cil_gen_portcon_lowport_neg(CuTest *tc); void test_cil_gen_portcon_highport_neg(CuTest *tc); void test_cil_gen_portcon_dbnull_neg(CuTest *tc); void test_cil_gen_portcon_currnull_neg(CuTest *tc); void test_cil_gen_portcon_astnull_neg(CuTest *tc); void test_cil_gen_portcon_str1null_neg(CuTest *tc); void test_cil_gen_portcon_str1parens_neg(CuTest *tc); void test_cil_gen_portcon_portnull_neg(CuTest *tc); void test_cil_gen_portcon_contextnull_neg(CuTest *tc); void test_cil_gen_portcon_context_neg(CuTest *tc); void test_cil_gen_portcon_extra_neg(CuTest *tc); void test_cil_fill_ipaddr(CuTest *tc); void test_cil_fill_ipaddr_addrnodenull_neg(CuTest *tc); void test_cil_fill_ipaddr_addrnull_neg(CuTest *tc); void test_cil_fill_ipaddr_addrinparens_neg(CuTest *tc); void test_cil_fill_ipaddr_extra_neg(CuTest *tc); void test_cil_gen_nodecon(CuTest *tc); void test_cil_gen_nodecon_anon_context(CuTest *tc); void test_cil_gen_nodecon_dbnull_neg(CuTest *tc); void test_cil_gen_nodecon_currnull_neg(CuTest *tc); void test_cil_gen_nodecon_astnull_neg(CuTest *tc); void test_cil_gen_nodecon_ipnull_neg(CuTest *tc); void test_cil_gen_nodecon_ipanon(CuTest *tc); void test_cil_gen_nodecon_ipanon_neg(CuTest *tc); void test_cil_gen_nodecon_netmasknull_neg(CuTest *tc); void test_cil_gen_nodecon_netmaskanon(CuTest *tc); void test_cil_gen_nodecon_netmaskanon_neg(CuTest *tc); void test_cil_gen_nodecon_contextnull_neg(CuTest *tc); void test_cil_gen_nodecon_context_neg(CuTest *tc); void test_cil_gen_nodecon_extra_neg(CuTest *tc); void test_cil_gen_genfscon(CuTest *tc); void test_cil_gen_genfscon_anon_context(CuTest *tc); void test_cil_gen_genfscon_dbnull_neg(CuTest *tc); void test_cil_gen_genfscon_currnull_neg(CuTest *tc); void test_cil_gen_genfscon_astnull_neg(CuTest *tc); void test_cil_gen_genfscon_typenull_neg(CuTest *tc); void test_cil_gen_genfscon_typeparens_neg(CuTest *tc); void test_cil_gen_genfscon_pathnull_neg(CuTest *tc); void test_cil_gen_genfscon_pathparens_neg(CuTest *tc); void test_cil_gen_genfscon_contextnull_neg(CuTest *tc); void test_cil_gen_genfscon_context_neg(CuTest *tc); void test_cil_gen_genfscon_extra_neg(CuTest *tc); void test_cil_gen_netifcon(CuTest *tc); void test_cil_gen_netifcon_nested(CuTest *tc); void test_cil_gen_netifcon_nested_neg(CuTest *tc); void test_cil_gen_netifcon_nested_emptysecondlist_neg(CuTest *tc); void test_cil_gen_netifcon_extra_nested_secondlist_neg(CuTest *tc); void test_cil_gen_netifcon_nested_missingobjects_neg(CuTest *tc); void test_cil_gen_netifcon_nested_secondnested_missingobjects_neg(CuTest *tc); void test_cil_gen_netifcon_dbnull_neg(CuTest *tc); void test_cil_gen_netifcon_currnull_neg(CuTest *tc); void test_cil_gen_netifcon_astnull_neg(CuTest *tc); void test_cil_gen_netifcon_ethmissing_neg(CuTest *tc); void test_cil_gen_netifcon_interfacemissing_neg(CuTest *tc); void test_cil_gen_netifcon_packetmissing_neg(CuTest *tc); void test_cil_gen_pirqcon(CuTest *tc); void test_cil_gen_pirqcon_pirqnotint_neg(CuTest *tc); void test_cil_gen_pirqcon_nopirq_neg(CuTest *tc); void test_cil_gen_pirqcon_pirqrange_neg(CuTest *tc); void test_cil_gen_pirqcon_nocontext_neg(CuTest *tc); void test_cil_gen_pirqcon_anoncontext_neg(CuTest *tc); void test_cil_gen_pirqcon_extra_neg(CuTest *tc); void test_cil_gen_pirqcon_dbnull_neg(CuTest *tc); void test_cil_gen_pirqcon_currnull_neg(CuTest *tc); void test_cil_gen_pirqcon_astnull_neg(CuTest *tc); void test_cil_gen_iomemcon(CuTest *tc); void test_cil_gen_iomemcon_iomemrange(CuTest *tc); void test_cil_gen_iomemcon_iomemrange_firstnotint_neg(CuTest *tc); void test_cil_gen_iomemcon_iomemrange_secondnotint_neg(CuTest *tc); void test_cil_gen_iomemcon_iomemrange_empty_neg(CuTest *tc); void test_cil_gen_iomemcon_iomemrange_singleiomem_neg(CuTest *tc); void test_cil_gen_iomemcon_iomemrange_morethantwoiomem_neg(CuTest *tc); void test_cil_gen_iomemcon_iomemnotint_neg(CuTest *tc); void test_cil_gen_iomemcon_noiomem_neg(CuTest *tc); void test_cil_gen_iomemcon_nocontext_neg(CuTest *tc); void test_cil_gen_iomemcon_anoncontext_neg(CuTest *tc); void test_cil_gen_iomemcon_extra_neg(CuTest *tc); void test_cil_gen_iomemcon_dbnull_neg(CuTest *tc); void test_cil_gen_iomemcon_currnull_neg(CuTest *tc); void test_cil_gen_iomemcon_astnull_neg(CuTest *tc); void test_cil_gen_ioportcon(CuTest *tc); void test_cil_gen_ioportcon_ioportrange(CuTest *tc); void test_cil_gen_ioportcon_ioportrange_firstnotint_neg(CuTest *tc); void test_cil_gen_ioportcon_ioportrange_secondnotint_neg(CuTest *tc); void test_cil_gen_ioportcon_ioportrange_empty_neg(CuTest *tc); void test_cil_gen_ioportcon_ioportrange_singleioport_neg(CuTest *tc); void test_cil_gen_ioportcon_ioportrange_morethantwoioport_neg(CuTest *tc); void test_cil_gen_ioportcon_ioportnotint_neg(CuTest *tc); void test_cil_gen_ioportcon_noioport_neg(CuTest *tc); void test_cil_gen_ioportcon_nocontext_neg(CuTest *tc); void test_cil_gen_ioportcon_anoncontext_neg(CuTest *tc); void test_cil_gen_ioportcon_extra_neg(CuTest *tc); void test_cil_gen_ioportcon_dbnull_neg(CuTest *tc); void test_cil_gen_ioportcon_currnull_neg(CuTest *tc); void test_cil_gen_ioportcon_astnull_neg(CuTest *tc); void test_cil_gen_pcidevicecon(CuTest *tc); void test_cil_gen_pcidevicecon_pcidevicenotint_neg(CuTest *tc); void test_cil_gen_pcidevicecon_nopcidevice_neg(CuTest *tc); void test_cil_gen_pcidevicecon_pcidevicerange_neg(CuTest *tc); void test_cil_gen_pcidevicecon_nocontext_neg(CuTest *tc); void test_cil_gen_pcidevicecon_anoncontext_neg(CuTest *tc); void test_cil_gen_pcidevicecon_extra_neg(CuTest *tc); void test_cil_gen_pcidevicecon_dbnull_neg(CuTest *tc); void test_cil_gen_pcidevicecon_currnull_neg(CuTest *tc); void test_cil_gen_pcidevicecon_astnull_neg(CuTest *tc); void test_cil_gen_fsuse_anoncontext(CuTest *tc); void test_cil_gen_fsuse_anoncontext_neg(CuTest *tc); void test_cil_gen_fsuse_xattr(CuTest *tc); void test_cil_gen_fsuse_task(CuTest *tc); void test_cil_gen_fsuse_transition(CuTest *tc); void test_cil_gen_fsuse_invalidtype_neg(CuTest *tc); void test_cil_gen_fsuse_notype_neg(CuTest *tc); void test_cil_gen_fsuse_typeinparens_neg(CuTest *tc); void test_cil_gen_fsuse_nofilesystem_neg(CuTest *tc); void test_cil_gen_fsuse_filesysteminparens_neg(CuTest *tc); void test_cil_gen_fsuse_nocontext_neg(CuTest *tc); void test_cil_gen_fsuse_emptyconparens_neg(CuTest *tc); void test_cil_gen_fsuse_extra_neg(CuTest *tc); void test_cil_gen_fsuse_dbnull_neg(CuTest *tc); void test_cil_gen_fsuse_currnull_neg(CuTest *tc); void test_cil_gen_fsuse_astnull_neg(CuTest *tc); void test_cil_gen_macro_noparams(CuTest *tc); void test_cil_gen_macro_type(CuTest *tc); void test_cil_gen_macro_role(CuTest *tc); void test_cil_gen_macro_user(CuTest *tc); void test_cil_gen_macro_sensitivity(CuTest *tc); void test_cil_gen_macro_category(CuTest *tc); void test_cil_gen_macro_catset(CuTest *tc); void test_cil_gen_macro_level(CuTest *tc); void test_cil_gen_macro_class(CuTest *tc); void test_cil_gen_macro_classmap(CuTest *tc); void test_cil_gen_macro_permset(CuTest *tc); void test_cil_gen_macro_duplicate(CuTest *tc); void test_cil_gen_macro_duplicate_neg(CuTest *tc); void test_cil_gen_macro_unknown_neg(CuTest *tc); void test_cil_gen_macro_dbnull_neg(CuTest *tc); void test_cil_gen_macro_currnull_neg(CuTest *tc); void test_cil_gen_macro_astnull_neg(CuTest *tc); void test_cil_gen_macro_unnamed_neg(CuTest *tc); void test_cil_gen_macro_noparam_name_neg(CuTest *tc); void test_cil_gen_macro_noparam_neg(CuTest *tc); void test_cil_gen_macro_nosecondparam_neg(CuTest *tc); void test_cil_gen_macro_emptyparam_neg(CuTest *tc); void test_cil_gen_macro_paramcontainsperiod_neg(CuTest *tc); void test_cil_gen_call(CuTest *tc); void test_cil_gen_call_noargs(CuTest *tc); void test_cil_gen_call_anon(CuTest *tc); void test_cil_gen_call_empty_call_neg(CuTest *tc); void test_cil_gen_call_dbnull_neg(CuTest *tc); void test_cil_gen_call_currnull_neg(CuTest *tc); void test_cil_gen_call_astnull_neg(CuTest *tc); void test_cil_gen_call_name_inparens_neg(CuTest *tc); void test_cil_gen_call_noname_neg(CuTest *tc); void test_cil_gen_optional(CuTest *tc); void test_cil_gen_optional_emptyoptional(CuTest *tc); void test_cil_gen_optional_dbnull_neg(CuTest *tc); void test_cil_gen_optional_currnull_neg(CuTest *tc); void test_cil_gen_optional_astnull_neg(CuTest *tc); void test_cil_gen_optional_unnamed_neg(CuTest *tc); void test_cil_gen_optional_extra_neg(CuTest *tc); void test_cil_gen_optional_nameinparens_neg(CuTest *tc); void test_cil_gen_optional_norule_neg(CuTest *tc); void test_cil_gen_policycap(CuTest *tc); void test_cil_gen_policycap_noname_neg(CuTest *tc); void test_cil_gen_policycap_nameinparens_neg(CuTest *tc); void test_cil_gen_policycap_extra_neg(CuTest *tc); void test_cil_gen_policycap_dbnull_neg(CuTest *tc); void test_cil_gen_policycap_currnull_neg(CuTest *tc); void test_cil_gen_policycap_astnull_neg(CuTest *tc); void test_cil_gen_ipaddr_ipv4(CuTest *tc); void test_cil_gen_ipaddr_ipv4_neg(CuTest *tc); void test_cil_gen_ipaddr_ipv6(CuTest *tc); void test_cil_gen_ipaddr_ipv6_neg(CuTest *tc); void test_cil_gen_ipaddr_noname_neg(CuTest *tc); void test_cil_gen_ipaddr_nameinparens_neg(CuTest *tc); void test_cil_gen_ipaddr_noip_neg(CuTest *tc); void test_cil_gen_ipaddr_ipinparens_neg(CuTest *tc); void test_cil_gen_ipaddr_extra_neg(CuTest *tc); void test_cil_gen_ipaddr_dbnull_neg(CuTest *tc); void test_cil_gen_ipaddr_currnull_neg(CuTest *tc); void test_cil_gen_ipaddr_astnull_neg(CuTest *tc); /* cil_build_ast test cases */ void test_cil_build_ast(CuTest *); void test_cil_build_ast_dbnull_neg(CuTest *); void test_cil_build_ast_astnull_neg(CuTest *); void test_cil_build_ast_suberr_neg(CuTest *); void test_cil_build_ast_treenull_neg(CuTest *); void test_cil_build_ast_node_helper_block(CuTest *); void test_cil_build_ast_node_helper_block_neg(CuTest *); void test_cil_build_ast_node_helper_blockinherit(CuTest *); void test_cil_build_ast_node_helper_blockinherit_neg(CuTest *); void test_cil_build_ast_node_helper_permset(CuTest *); void test_cil_build_ast_node_helper_permset_neg(CuTest *); void test_cil_build_ast_node_helper_in(CuTest *); void test_cil_build_ast_node_helper_in_neg(CuTest *); void test_cil_build_ast_node_helper_class(CuTest *); void test_cil_build_ast_node_helper_class_neg(CuTest *); void test_cil_build_ast_node_helper_classpermset(CuTest *); void test_cil_build_ast_node_helper_classpermset_neg(CuTest *); void test_cil_build_ast_node_helper_classmap(CuTest *); void test_cil_build_ast_node_helper_classmap_neg(CuTest *); void test_cil_build_ast_node_helper_classmapping(CuTest *); void test_cil_build_ast_node_helper_classmapping_neg(CuTest *); void test_cil_build_ast_node_helper_common(CuTest *); void test_cil_build_ast_node_helper_common_neg(CuTest *); void test_cil_build_ast_node_helper_sid(CuTest *); void test_cil_build_ast_node_helper_sid_neg(CuTest *); void test_cil_build_ast_node_helper_sidcontext(CuTest *); void test_cil_build_ast_node_helper_sidcontext_neg(CuTest *); void test_cil_build_ast_node_helper_user(CuTest *); void test_cil_build_ast_node_helper_user_neg(CuTest *); void test_cil_build_ast_node_helper_userlevel(CuTest *); void test_cil_build_ast_node_helper_userlevel_neg(CuTest *); void test_cil_build_ast_node_helper_userrange(CuTest *); void test_cil_build_ast_node_helper_userrange_neg(CuTest *); void test_cil_build_ast_node_helper_type(CuTest *); void test_cil_build_ast_node_helper_type_neg(CuTest *); void test_cil_build_ast_node_helper_typeattribute(CuTest *); void test_cil_build_ast_node_helper_typeattribute_neg(CuTest *); void test_cil_build_ast_node_helper_boolif(CuTest *); void test_cil_build_ast_node_helper_boolif_neg(CuTest *); void test_cil_build_ast_node_helper_tunif(CuTest *); void test_cil_build_ast_node_helper_tunif_neg(CuTest *); void test_cil_build_ast_node_helper_condblock_true(CuTest *); void test_cil_build_ast_node_helper_condblock_true_neg(CuTest *); void test_cil_build_ast_node_helper_condblock_false(CuTest *); void test_cil_build_ast_node_helper_condblock_false_neg(CuTest *); void test_cil_build_ast_node_helper_typealias(CuTest *); void test_cil_build_ast_node_helper_typealias_notype_neg(CuTest *); void test_cil_build_ast_node_helper_typebounds(CuTest *); void test_cil_build_ast_node_helper_typebounds_neg(CuTest *); void test_cil_build_ast_node_helper_typepermissive(CuTest *); void test_cil_build_ast_node_helper_typepermissive_neg(CuTest *); void test_cil_build_ast_node_helper_nametypetransition(CuTest *); void test_cil_build_ast_node_helper_nametypetransition_neg(CuTest *); void test_cil_build_ast_node_helper_rangetransition(CuTest *); void test_cil_build_ast_node_helper_rangetransition_neg(CuTest *); void test_cil_build_ast_node_helper_typeattributeset(CuTest *); void test_cil_build_ast_node_helper_typeattributeset_neg(CuTest *); void test_cil_build_ast_node_helper_userbounds(CuTest *); void test_cil_build_ast_node_helper_userbounds_neg(CuTest *); void test_cil_build_ast_node_helper_role(CuTest *); void test_cil_build_ast_node_helper_role_neg(CuTest *); void test_cil_build_ast_node_helper_roletransition(CuTest *); void test_cil_build_ast_node_helper_roletransition_neg(CuTest *); void test_cil_build_ast_node_helper_roleallow(CuTest *); void test_cil_build_ast_node_helper_roleallow_neg(CuTest *); void test_cil_build_ast_node_helper_rolebounds(CuTest *); void test_cil_build_ast_node_helper_rolebounds_neg(CuTest *); void test_cil_build_ast_node_helper_avrule_allow(CuTest *); void test_cil_build_ast_node_helper_avrule_allow_neg(CuTest *); void test_cil_build_ast_node_helper_avrule_auditallow(CuTest *); void test_cil_build_ast_node_helper_avrule_auditallow_neg(CuTest *); void test_cil_build_ast_node_helper_avrule_dontaudit(CuTest *); void test_cil_build_ast_node_helper_avrule_dontaudit_neg(CuTest *); void test_cil_build_ast_node_helper_avrule_neverallow(CuTest *); void test_cil_build_ast_node_helper_avrule_neverallow_neg(CuTest *); void test_cil_build_ast_node_helper_type_rule_transition(CuTest *); void test_cil_build_ast_node_helper_type_rule_transition_neg(CuTest *); void test_cil_build_ast_node_helper_type_rule_change(CuTest *); void test_cil_build_ast_node_helper_type_rule_change_neg(CuTest *); void test_cil_build_ast_node_helper_type_rule_member(CuTest *); void test_cil_build_ast_node_helper_type_rule_member_neg(CuTest *); void test_cil_build_ast_node_helper_bool(CuTest *); void test_cil_build_ast_node_helper_bool_neg(CuTest *); void test_cil_build_ast_node_helper_bool_tunable(CuTest *); void test_cil_build_ast_node_helper_bool_tunable_neg(CuTest *); void test_cil_build_ast_node_helper_else(CuTest *); void test_cil_build_ast_node_helper_else_neg(CuTest *); void test_cil_build_ast_node_helper_sensitivity(CuTest *); void test_cil_build_ast_node_helper_sensitivity_neg(CuTest *); void test_cil_build_ast_node_helper_sensalias(CuTest *); void test_cil_build_ast_node_helper_sensalias_neg(CuTest *); void test_cil_build_ast_node_helper_category(CuTest *); void test_cil_build_ast_node_helper_category_neg(CuTest *); void test_cil_build_ast_node_helper_catset(CuTest *tc); void test_cil_build_ast_node_helper_catset_neg(CuTest *tc); void test_cil_build_ast_node_helper_catorder(CuTest *tc); void test_cil_build_ast_node_helper_catorder_neg(CuTest *tc); void test_cil_build_ast_node_helper_catalias(CuTest *tc); void test_cil_build_ast_node_helper_catalias_neg(CuTest *tc); void test_cil_build_ast_node_helper_catrange(CuTest *tc); void test_cil_build_ast_node_helper_catrange_neg(CuTest *tc); void test_cil_build_ast_node_helper_roletype(CuTest *tc); void test_cil_build_ast_node_helper_roletype_neg(CuTest *tc); void test_cil_build_ast_node_helper_userrole(CuTest *tc); void test_cil_build_ast_node_helper_userrole_neg(CuTest *tc); void test_cil_build_ast_node_helper_gen_classcommon(CuTest *tc); void test_cil_build_ast_node_helper_gen_classcommon_neg(CuTest *tc); void test_cil_build_ast_node_helper_gen_dominance(CuTest *tc); void test_cil_build_ast_node_helper_gen_dominance_neg(CuTest *tc); void test_cil_build_ast_node_helper_gen_senscat(CuTest *tc); void test_cil_build_ast_node_helper_gen_senscat_neg(CuTest *tc); void test_cil_build_ast_node_helper_gen_level(CuTest *tc); void test_cil_build_ast_node_helper_gen_level_neg(CuTest *tc); void test_cil_build_ast_node_helper_gen_levelrange(CuTest *tc); void test_cil_build_ast_node_helper_gen_levelrange_neg(CuTest *tc); void test_cil_build_ast_node_helper_gen_constrain(CuTest *tc); void test_cil_build_ast_node_helper_gen_constrain_neg(CuTest *tc); void test_cil_build_ast_node_helper_gen_mlsconstrain(CuTest *tc); void test_cil_build_ast_node_helper_gen_mlsconstrain_neg(CuTest *tc); void test_cil_build_ast_node_helper_gen_context(CuTest *tc); void test_cil_build_ast_node_helper_gen_context_neg(CuTest *tc); void test_cil_build_ast_node_helper_gen_filecon(CuTest *tc); void test_cil_build_ast_node_helper_gen_filecon_neg(CuTest *tc); void test_cil_build_ast_node_helper_gen_portcon(CuTest *tc); void test_cil_build_ast_node_helper_gen_portcon_neg(CuTest *tc); void test_cil_build_ast_node_helper_gen_nodecon(CuTest *tc); void test_cil_build_ast_node_helper_gen_nodecon_neg(CuTest *tc); void test_cil_build_ast_node_helper_gen_genfscon(CuTest *tc); void test_cil_build_ast_node_helper_gen_genfscon_neg(CuTest *tc); void test_cil_build_ast_node_helper_gen_netifcon(CuTest *tc); void test_cil_build_ast_node_helper_gen_netifcon_neg(CuTest *tc); void test_cil_build_ast_node_helper_gen_pirqcon(CuTest *tc); void test_cil_build_ast_node_helper_gen_pirqcon_neg(CuTest *tc); void test_cil_build_ast_node_helper_gen_iomemcon(CuTest *tc); void test_cil_build_ast_node_helper_gen_iomemcon_neg(CuTest *tc); void test_cil_build_ast_node_helper_gen_ioportcon(CuTest *tc); void test_cil_build_ast_node_helper_gen_ioportcon_neg(CuTest *tc); void test_cil_build_ast_node_helper_gen_pcidevicecon(CuTest *tc); void test_cil_build_ast_node_helper_gen_pcidevicecon_neg(CuTest *tc); void test_cil_build_ast_node_helper_gen_fsuse(CuTest *tc); void test_cil_build_ast_node_helper_gen_fsuse_neg(CuTest *tc); void test_cil_build_ast_node_helper_gen_macro(CuTest *tc); void test_cil_build_ast_node_helper_gen_macro_neg(CuTest *tc); void test_cil_build_ast_node_helper_gen_macro_nested_macro_neg(CuTest *tc); void test_cil_build_ast_node_helper_gen_macro_nested_tunif_neg(CuTest *tc); void test_cil_build_ast_node_helper_gen_call(CuTest *tc); void test_cil_build_ast_node_helper_gen_call_neg(CuTest *tc); void test_cil_build_ast_node_helper_gen_optional(CuTest *tc); void test_cil_build_ast_node_helper_gen_optional_neg(CuTest *tc); void test_cil_build_ast_node_helper_gen_policycap(CuTest *tc); void test_cil_build_ast_node_helper_gen_policycap_neg(CuTest *tc); void test_cil_build_ast_node_helper_gen_ipaddr(CuTest *tc); void test_cil_build_ast_node_helper_gen_ipaddr_neg(CuTest *tc); void test_cil_build_ast_node_helper_extraargsnull_neg(CuTest *); void test_cil_build_ast_last_child_helper(CuTest *); void test_cil_build_ast_last_child_helper_extraargsnull_neg(CuTest *); #endif libsepol-3.8.1/cil/test/unit/test_cil_copy_ast.c000066400000000000000000002323711476211737200217360ustar00rootroot00000000000000/* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #include "CuTest.h" #include "CilTest.h" #include "../../src/cil_internal.h" #include "../../src/cil_copy_ast.h" #include "../../src/cil_build_ast.h" #include "../../src/cil_resolve_ast.h" #define CIL_TEST_SYM_SIZE 1 int __cil_copy_node_helper(struct cil_tree_node *orig, uint32_t *finished, void *extra_args); struct cil_args_copy { struct cil_tree_node *dest; struct cil_db *db; }; struct cil_args_copy *gen_copy_args(struct cil_tree_node *node, struct cil_db *db) { struct cil_args_copy *args = cil_malloc(sizeof(*args)); args->dest = node; args->db = db; return args; } void test_cil_copy_list(CuTest *tc) { char *line[] = {"(", "foo1", "foo2", ")", NULL}; struct cil_tree *test_tree; struct cil_list *cil_l; gen_test_tree(&test_tree, line); cil_list_init(&cil_l); cil_set_to_list(test_tree->root->cl_head, cil_l, 1); struct cil_list *copy_list; cil_list_init(©_list); int rc =cil_copy_list(cil_l, ©_list); CuAssertIntEquals(tc, rc, SEPOL_OK); CuAssertStrEquals(tc, copy_list->head->data, cil_l->head->data); CuAssertStrEquals(tc, copy_list->head->next->data, cil_l->head->next->data); CuAssertIntEquals(tc, copy_list->head->flavor, cil_l->head->flavor); CuAssertIntEquals(tc, copy_list->head->next->flavor, cil_l->head->next->flavor); } void test_cil_copy_list_sublist(CuTest *tc) { char *line[] = {"(", "foo1", "foo2", "(", "foo3", ")", ")", NULL}; struct cil_tree *test_tree; struct cil_list *cil_l; gen_test_tree(&test_tree, line); cil_list_init(&cil_l); cil_set_to_list(test_tree->root->cl_head, cil_l, 1); struct cil_list *copy_list; cil_list_init(©_list); int rc = cil_copy_list(cil_l, ©_list); CuAssertIntEquals(tc, rc, SEPOL_OK); CuAssertStrEquals(tc, copy_list->head->data, cil_l->head->data); CuAssertStrEquals(tc, copy_list->head->next->data, cil_l->head->next->data); CuAssertStrEquals(tc, ((struct cil_list *)copy_list->head->next->next->data)->head->data, ((struct cil_list *)cil_l->head->next->next->data)->head->data); CuAssertIntEquals(tc, copy_list->head->flavor, cil_l->head->flavor); CuAssertIntEquals(tc, copy_list->head->next->flavor, cil_l->head->next->flavor); CuAssertIntEquals(tc, ((struct cil_list *)copy_list->head->next->next->data)->head->flavor, ((struct cil_list *)cil_l->head->next->next->data)->head->flavor); } void test_cil_copy_list_sublist_extra(CuTest *tc) { char *line[] = {"(", "foo1", "foo2", "(", "foo3", ")", "foo4", ")", NULL}; struct cil_tree *test_tree; struct cil_list *cil_l; gen_test_tree(&test_tree, line); cil_list_init(&cil_l); cil_set_to_list(test_tree->root->cl_head, cil_l, 1); struct cil_list *copy_list; cil_list_init(©_list); int rc = cil_copy_list(cil_l, ©_list); CuAssertIntEquals(tc, rc, SEPOL_OK); CuAssertStrEquals(tc, copy_list->head->data, cil_l->head->data); CuAssertStrEquals(tc, copy_list->head->next->data, cil_l->head->next->data); CuAssertStrEquals(tc, ((struct cil_list *)copy_list->head->next->next->data)->head->data, ((struct cil_list *)cil_l->head->next->next->data)->head->data); CuAssertStrEquals(tc, copy_list->head->next->next->next->data, cil_l->head->next->next->next->data); CuAssertIntEquals(tc, copy_list->head->flavor, cil_l->head->flavor); CuAssertIntEquals(tc, copy_list->head->next->flavor, cil_l->head->next->flavor); CuAssertIntEquals(tc, ((struct cil_list *)copy_list->head->next->next->data)->head->flavor, ((struct cil_list *)cil_l->head->next->next->data)->head->flavor); CuAssertIntEquals(tc, copy_list->head->next->next->next->flavor, cil_l->head->next->next->next->flavor); } void test_cil_copy_list_orignull_neg(CuTest *tc) { char *line[] = {"(", "foo1", "foo2", ")", NULL}; struct cil_tree *test_tree; struct cil_list *cil_l = NULL; gen_test_tree(&test_tree, line); struct cil_list *copy_list; cil_list_init(©_list); int rc = cil_copy_list(cil_l, ©_list); CuAssertIntEquals(tc, rc, SEPOL_ERR); CuAssertPtrEquals(tc, copy_list->head, NULL); } void test_cil_copy_block(CuTest *tc) { char *line[] = {"(", "block", "a", "(", "type", "log", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_block(test_db, test_tree->root->cl_head->cl_head, test_ast_node, 0); struct cil_tree_node *test_copy; cil_tree_node_init(&test_copy); symtab_t sym; symtab_init(&sym, cil_sym_sizes[CIL_SYM_ARRAY_BLOCK][CIL_SYM_BLOCKS]); int rc = cil_copy_block(test_db, test_ast_node->data, &test_copy->data, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); } void test_cil_copy_perm(CuTest *tc) { char *line[] = {"(", "class", "foo", "(", "read", "write", "open", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); struct cil_class *new_node; cil_class_init(&new_node); struct cil_tree_node *new_tree_node; cil_tree_node_init(&new_tree_node); new_tree_node->data = new_node; new_tree_node->flavor = CIL_CLASS; test_ast_node->parent = new_tree_node; test_ast_node->line = 1; struct cil_tree_node *test_copy; cil_tree_node_init(&test_copy); symtab_t sym; symtab_init(&sym, CIL_CLASS_SYM_SIZE); cil_gen_perm(test_db, test_tree->root->cl_head->cl_head->next->next->cl_head, test_ast_node); int rc = cil_copy_perm(test_db, test_ast_node->data, &test_copy->data, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); cil_gen_perm(test_db, test_tree->root->cl_head->cl_head->next->next->cl_head->next, test_ast_node); rc = cil_copy_perm(test_db, test_ast_node->data, &test_copy->data, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); cil_gen_perm(test_db, test_tree->root->cl_head->cl_head->next->next->cl_head->next->next, test_ast_node); rc = cil_copy_perm(test_db, test_ast_node->data, &test_copy->data, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); } void test_cil_copy_class(CuTest *tc) { char *line[] = {"(", "class", "file", "(", "read", "write", "open", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_class(test_db, test_tree->root->cl_head->cl_head, test_ast_node); struct cil_tree_node *test_copy; cil_tree_node_init(&test_copy); symtab_t sym; symtab_init(&sym, CIL_CLASS_SYM_SIZE); int rc = cil_copy_class(test_db, test_ast_node->data, &test_copy->data, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); } void test_cil_copy_common(CuTest *tc) { char *line[] = {"(", "common", "test", "(", "read", "write", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_common(test_db, test_tree->root->cl_head->cl_head, test_ast_node); struct cil_tree_node *test_copy; cil_tree_node_init(&test_copy); symtab_t sym; symtab_init(&sym, CIL_CLASS_SYM_SIZE); int rc = cil_copy_common(test_db, test_ast_node->data, &test_copy->data, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); } void test_cil_copy_classcommon(CuTest *tc) { char *line[] = {"(", "classcommon", "file", "file", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); char *test_key = test_tree->root->cl_head->cl_head->next->data; struct cil_class *test_cls; cil_class_init(&test_cls); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_symtab_insert(&test_db->symtab[CIL_SYM_CLASSES], (hashtab_key_t)test_key, (struct cil_symtab_datum*)test_cls, test_ast_node); test_ast_node->data = test_cls; test_ast_node->flavor = CIL_CLASS; cil_gen_classcommon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); struct cil_classcommon *test_copy; cil_classcommon_init(&test_copy); symtab_t sym; symtab_init(&sym, CIL_CLASS_SYM_SIZE); int rc = cil_copy_classcommon(test_db, test_ast_node->data, (void**)&test_copy, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); CuAssertStrEquals(tc, ((struct cil_classcommon *)test_ast_node->data)->class_str, test_copy->class_str); CuAssertStrEquals(tc, ((struct cil_classcommon *)test_ast_node->data)->common_str, test_copy->common_str); } void test_cil_copy_sid(CuTest *tc) { char *line[] = {"(", "sid", "test", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_sid(test_db, test_tree->root->cl_head->cl_head, test_ast_node); struct cil_tree_node *test_copy; cil_tree_node_init(&test_copy); symtab_t sym; symtab_init(&sym, CIL_TEST_SYM_SIZE); int rc = cil_copy_sid(test_db, test_ast_node->data, &test_copy->data, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); } void test_cil_copy_sidcontext(CuTest *tc) { char *line[] = {"(", "sidcontext", "test", "(", "blah_u", "blah_r", "blah_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_sidcontext(test_db, test_tree->root->cl_head->cl_head, test_ast_node); struct cil_tree_node *test_copy; cil_tree_node_init(&test_copy); symtab_t sym; symtab_init(&sym, CIL_TEST_SYM_SIZE); int rc = cil_copy_sidcontext(test_db, test_ast_node->data, &test_copy->data, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); CuAssertStrEquals(tc, ((struct cil_user *)test_copy->data)->datum.name, ((struct cil_user *)test_ast_node->data)->datum.name); } void test_cil_copy_user(CuTest *tc) { char *line[] = {"(", "user", "sysadm", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_user(test_db, test_tree->root->cl_head->cl_head, test_ast_node); struct cil_tree_node *test_copy; cil_tree_node_init(&test_copy); symtab_t sym; symtab_init(&sym, CIL_TEST_SYM_SIZE); int rc = cil_copy_user(test_db, test_ast_node->data, &test_copy->data, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); } void test_cil_copy_role(CuTest *tc) { char *line[] = {"(", "role", "role_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_role(test_db, test_tree->root->cl_head->cl_head, test_ast_node); struct cil_tree_node *test_copy; cil_tree_node_init(&test_copy); symtab_t sym; symtab_init(&sym, CIL_TEST_SYM_SIZE); int rc = cil_copy_role(test_db, test_ast_node->data, &test_copy->data, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); } void test_cil_copy_userrole(CuTest *tc) { char *line[] = {"(", "userrole", "staff_u", "staff_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_userrole(test_db, test_tree->root->cl_head->cl_head, test_ast_node); struct cil_userrole *test_copy; cil_userrole_init(&test_copy); symtab_t sym; symtab_init(&sym, CIL_TEST_SYM_SIZE); int rc = cil_copy_userrole(test_db, test_ast_node->data, (void**)&test_copy, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); CuAssertStrEquals(tc, ((struct cil_userrole *)test_ast_node->data)->user_str, test_copy->user_str); CuAssertStrEquals(tc, ((struct cil_userrole *)test_ast_node->data)->role_str, test_copy->role_str); } void test_cil_copy_type(CuTest *tc) { char *line[] = {"(", "type", "test", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_type(test_db, test_tree->root->cl_head->cl_head, test_ast_node); struct cil_tree_node *test_copy; cil_tree_node_init(&test_copy); symtab_t sym; symtab_init(&sym, CIL_TEST_SYM_SIZE); int rc = cil_copy_type(test_db, test_ast_node->data, &test_copy->data, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); } void test_cil_copy_typealias(CuTest *tc) { char *line[] = {"(", "typealias", ".test.type", "type_t", ")", "(", "type", "test", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_typealias(test_db, test_tree->root->cl_head->cl_head, test_ast_node); struct cil_tree_node *test_copy; cil_tree_node_init(&test_copy); symtab_t sym; symtab_init(&sym, CIL_TEST_SYM_SIZE); int rc = cil_copy_typealias(test_db, test_ast_node->data, &test_copy->data, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); } void test_cil_copy_typeattribute(CuTest *tc) { char *line[] = {"(", "typettribute", "type_t", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_typeattribute(test_db, test_tree->root->cl_head->cl_head, test_ast_node); struct cil_tree_node *test_copy; cil_tree_node_init(&test_copy); symtab_t sym; symtab_init(&sym, CIL_TEST_SYM_SIZE); int rc = cil_copy_typeattribute(test_db, test_ast_node->data, &test_copy->data, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); } void test_cil_copy_bool(CuTest *tc) { char *line[] = {"(", "boolean", "foo", "true", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_bool(test_db, test_tree->root->cl_head->cl_head, test_ast_node, CIL_BOOL); struct cil_tree_node *test_copy; cil_tree_node_init(&test_copy); symtab_t sym; symtab_init(&sym, CIL_TEST_SYM_SIZE); int rc = cil_copy_bool(test_db, test_ast_node->data, &test_copy->data, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); CuAssertIntEquals(tc, ((struct cil_bool *)test_copy->data)->value, ((struct cil_bool *)test_ast_node->data)->value); } void test_cil_copy_type_rule(CuTest *tc) { char *line[] = {"(", "typetransition", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_type_rule(test_tree->root->cl_head->cl_head, test_ast_node, CIL_TYPE_TRANSITION); struct cil_type_rule *test_copy; cil_type_rule_init(&test_copy); symtab_t sym; symtab_init(&sym, CIL_TEST_SYM_SIZE); int rc = cil_copy_type_rule(test_db, test_ast_node->data, (void**)&test_copy, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); CuAssertIntEquals(tc, ((struct cil_type_rule *)test_ast_node->data)->rule_kind, test_copy->rule_kind); CuAssertStrEquals(tc, ((struct cil_type_rule *)test_ast_node->data)->src_str, test_copy->src_str); CuAssertStrEquals(tc, ((struct cil_type_rule *)test_ast_node->data)->tgt_str, test_copy->tgt_str); CuAssertStrEquals(tc, ((struct cil_type_rule *)test_ast_node->data)->obj_str, test_copy->obj_str); } void test_cil_copy_avrule(CuTest *tc) { char *line[] = {"(", "allow", "test", "foo", "(", "bar", "(", "read", "write", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_tree_node *test_current; test_current = test_tree->root->cl_head->cl_head; cil_gen_avrule(test_current, test_ast_node, CIL_AVRULE_ALLOWED); struct cil_avrule *test_copy; cil_avrule_init(&test_copy); symtab_t sym; symtab_init(&sym, CIL_TEST_SYM_SIZE); int rc = cil_copy_avrule(test_db, test_ast_node->data, (void**)&test_copy, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); CuAssertIntEquals(tc, ((struct cil_avrule *)test_ast_node->data)->rule_kind, test_copy->rule_kind); CuAssertStrEquals(tc, ((struct cil_avrule *)test_ast_node->data)->src_str, test_copy->src_str); CuAssertStrEquals(tc, ((struct cil_avrule *)test_ast_node->data)->tgt_str, test_copy->tgt_str); CuAssertStrEquals(tc, ((struct cil_avrule *)test_ast_node->data)->classpermset->class_str, test_copy->classpermset->class_str); CuAssertIntEquals(tc, ((struct cil_avrule *)test_ast_node->data)->classpermset->permset->perms_list_str->head->flavor, test_copy->classpermset->permset->perms_list_str->head->flavor); CuAssertStrEquals(tc, (char*)((struct cil_avrule *)test_ast_node->data)->classpermset->permset->perms_list_str->head->data, (char*)test_copy->classpermset->permset->perms_list_str->head->data); CuAssertIntEquals(tc, ((struct cil_avrule *)test_ast_node->data)->classpermset->permset->perms_list_str->head->next->flavor, test_copy->classpermset->permset->perms_list_str->head->next->flavor); CuAssertStrEquals(tc, (char*)((struct cil_avrule *)test_ast_node->data)->classpermset->permset->perms_list_str->head->next->data, (char*)test_copy->classpermset->permset->perms_list_str->head->next->data); } void test_cil_copy_sens(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_sensitivity(test_db, test_tree->root->cl_head->cl_head, test_ast_node); struct cil_tree_node *test_copy; cil_tree_node_init(&test_copy); symtab_t sym; symtab_init(&sym, CIL_TEST_SYM_SIZE); int rc = cil_copy_sens(test_db, test_ast_node->data, &test_copy->data, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); } void test_cil_copy_sensalias(CuTest *tc) { char *line[] = {"(", "sensitivityalias", "s0", "alias", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_sensalias(test_db, test_tree->root->cl_head->cl_head, test_ast_node); struct cil_tree_node *test_copy; cil_tree_node_init(&test_copy); symtab_t sym; symtab_init(&sym, CIL_TEST_SYM_SIZE); int rc = cil_copy_sensalias(test_db, test_ast_node->data, &test_copy->data, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); CuAssertStrEquals(tc, ((struct cil_sensalias *)test_copy->data)->sens_str, ((struct cil_sensalias *)test_ast_node->data)->sens_str); } void test_cil_copy_cat(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_category(test_db, test_tree->root->cl_head->cl_head, test_ast_node); struct cil_tree_node *test_copy; cil_tree_node_init(&test_copy); symtab_t sym; symtab_init(&sym, CIL_TEST_SYM_SIZE); int rc = cil_copy_cat(test_db, test_ast_node->data, &test_copy->data, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); } void test_cil_copy_catalias(CuTest *tc) { char *line[] = {"(", "categoryalias", "c0", "red", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_catalias(test_db, test_tree->root->cl_head->cl_head, test_ast_node); struct cil_tree_node *test_copy; cil_tree_node_init(&test_copy); symtab_t sym; symtab_init(&sym, CIL_TEST_SYM_SIZE); int rc = cil_copy_catalias(test_db, test_ast_node->data, &test_copy->data, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); CuAssertStrEquals(tc, ((struct cil_catalias *)test_copy->data)->cat_str, ((struct cil_catalias *)test_ast_node->data)->cat_str); } void test_cil_copy_senscat(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "sensitivity", "s1", ")", "(", "dominance", "(", "s0", "s1", ")", ")", "(", "category", "c0", ")", "(", "category", "c255", ")", "(", "categoryorder", "(", "c0", "c255", ")", ")", "(", "sensitivitycategory", "s1", "(", "c0", "c255", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_senscat(test_db, test_tree->root->cl_head->next->next->next->next->next->next->cl_head, test_ast_node); struct cil_senscat *test_copy; cil_senscat_init(&test_copy); symtab_t sym; symtab_init(&sym, CIL_TEST_SYM_SIZE); int rc = cil_copy_senscat(test_db, test_ast_node->data, (void**)&test_copy, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); CuAssertStrEquals(tc, ((struct cil_senscat *)test_ast_node->data)->sens_str, test_copy->sens_str); CuAssertStrEquals(tc, (char*)((struct cil_senscat *)test_ast_node->data)->catset->cat_list_str->head->data, (char*)test_copy->catset->cat_list_str->head->data); CuAssertStrEquals(tc, (char*)((struct cil_senscat *)test_ast_node->data)->catset->cat_list_str->head->next->data, (char*)test_copy->catset->cat_list_str->head->next->data); } void test_cil_copy_catorder(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c255", ")", "(", "categoryorder", "(", "c0", "c255", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_catorder(test_db, test_tree->root->cl_head->next->next->cl_head, test_ast_node); struct cil_catorder *test_copy; cil_catorder_init(&test_copy); symtab_t sym; symtab_init(&sym, CIL_TEST_SYM_SIZE); int rc = cil_copy_catorder(test_db, test_ast_node->data, (void**)&test_copy, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); CuAssertStrEquals(tc, (char*)((struct cil_catorder *)test_ast_node->data)->cat_list_str->head->data, (char*)test_copy->cat_list_str->head->data); CuAssertStrEquals(tc, (char*)((struct cil_catorder *)test_ast_node->data)->cat_list_str->head->next->data, (char*)test_copy->cat_list_str->head->next->data); } void test_cil_copy_dominance(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "sensitivity", "s1", ")", "(", "sensitivity", "s2", ")", "(", "dominance", "(", "s0", "s1", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_dominance(test_db, test_tree->root->cl_head->next->next->next->cl_head, test_ast_node); struct cil_sens_dominates *test_copy; cil_sens_dominates_init(&test_copy); symtab_t sym; symtab_init(&sym, CIL_TEST_SYM_SIZE); int rc = cil_copy_dominance(test_db, test_ast_node->data, (void**)&test_copy, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); CuAssertStrEquals(tc, (char*)((struct cil_sens_dominates *)test_ast_node->data)->sens_list_str->head->data, (char*)test_copy->sens_list_str->head->data); CuAssertStrEquals(tc, (char*)((struct cil_sens_dominates *)test_ast_node->data)->sens_list_str->head->next->data, (char*)test_copy->sens_list_str->head->next->data); } void test_cil_copy_level(CuTest *tc) { char *line[] = {"(", "level", "low", "(", "s0", "(", "c1", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_level(test_db, test_tree->root->cl_head->cl_head, test_ast_node); struct cil_tree_node *test_copy; cil_tree_node_init(&test_copy); symtab_t sym; symtab_init(&sym, CIL_TEST_SYM_SIZE); int rc = cil_copy_level(test_db, test_ast_node->data, &test_copy->data, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); } void test_cil_copy_fill_level(CuTest *tc) { char *line[] = {"(", "level", "low", "(", "s0", "(", "c1", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_level(test_db, test_tree->root->cl_head->cl_head, test_ast_node); struct cil_tree_node *test_copy; cil_tree_node_init(&test_copy); cil_level_init((struct cil_level**)&test_copy->data); symtab_t sym; symtab_init(&sym, CIL_TEST_SYM_SIZE); int rc = cil_copy_fill_level((struct cil_level*)test_ast_node->data, (struct cil_level*)test_copy->data); CuAssertIntEquals(tc, rc, SEPOL_OK); CuAssertStrEquals(tc, ((struct cil_level *)test_copy->data)->sens_str, ((struct cil_level *)test_ast_node->data)->sens_str); } void test_cil_copy_context(CuTest *tc) { char *line[] = {"(", "context", "packet_default", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_context(test_db, test_tree->root->cl_head->cl_head, test_ast_node); struct cil_tree_node *test_copy; cil_tree_node_init(&test_copy); symtab_t sym; symtab_init(&sym, CIL_TEST_SYM_SIZE); int rc = cil_copy_context(test_db, test_ast_node->data, &test_copy->data, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); } void test_cil_copy_netifcon(CuTest *tc) { char *line[] = {"(", "netifcon", "eth0", "if_default", "packet_default", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_netifcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); struct cil_netifcon *test_copy; symtab_t sym; symtab_init(&sym, CIL_TEST_SYM_SIZE); int rc = cil_copy_netifcon(test_db, test_ast_node->data, (void**)&test_copy, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); CuAssertStrEquals(tc, test_copy->interface_str, ((struct cil_netifcon *)test_ast_node->data)->interface_str); CuAssertStrEquals(tc, test_copy->if_context_str, ((struct cil_netifcon *)test_ast_node->data)->if_context_str); CuAssertStrEquals(tc, test_copy->packet_context_str, ((struct cil_netifcon *)test_ast_node->data)->packet_context_str); } void test_cil_copy_netifcon_nested(CuTest *tc) { char *line[] = {"(", "netifcon", "eth1", "(", "system_u", "object_r", "netif_t", "(", "low", "high", ")", ")", "(", "system_u", "object_r", "netif_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_netifcon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); struct cil_netifcon *test_copy; symtab_t sym; symtab_init(&sym, CIL_TEST_SYM_SIZE); int rc = cil_copy_netifcon(test_db, test_ast_node->data, (void**)&test_copy, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); CuAssertStrEquals(tc, test_copy->interface_str, ((struct cil_netifcon *)test_ast_node->data)->interface_str); CuAssertStrEquals(tc, test_copy->if_context_str, ((struct cil_netifcon *)test_ast_node->data)->if_context_str); CuAssertStrEquals(tc, test_copy->packet_context_str, ((struct cil_netifcon *)test_ast_node->data)->packet_context_str); CuAssertStrEquals(tc, test_copy->packet_context->user_str, ((struct cil_netifcon *)test_ast_node->data)->packet_context->user_str); CuAssertStrEquals(tc, test_copy->packet_context->role_str, ((struct cil_netifcon *)test_ast_node->data)->packet_context->role_str); CuAssertStrEquals(tc, test_copy->packet_context->type_str, ((struct cil_netifcon *)test_ast_node->data)->packet_context->type_str); CuAssertStrEquals(tc, test_copy->packet_context->range_str, ((struct cil_netifcon *)test_ast_node->data)->packet_context->range_str); } void test_cil_copy_fill_context(CuTest *tc) { char *line[] = {"(", "context", "packet_default", "(", "system_u", "object_r", "etc_t", "range", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_context(test_db, test_tree->root->cl_head->cl_head, test_ast_node); struct cil_tree_node *test_copy; cil_tree_node_init(&test_copy); cil_context_init((struct cil_context**)&test_copy->data); symtab_t sym; symtab_init(&sym, CIL_TEST_SYM_SIZE); int rc = cil_copy_fill_context((struct cil_context*)test_ast_node->data, (struct cil_context*)test_copy->data); CuAssertIntEquals(tc, rc, SEPOL_OK); CuAssertStrEquals(tc, ((struct cil_context *)test_copy->data)->user_str, ((struct cil_context *)test_ast_node->data)->user_str); CuAssertStrEquals(tc, ((struct cil_context *)test_copy->data)->role_str, ((struct cil_context *)test_ast_node->data)->role_str); CuAssertStrEquals(tc, ((struct cil_context *)test_copy->data)->type_str, ((struct cil_context *)test_ast_node->data)->type_str); CuAssertStrEquals(tc, ((struct cil_context *)test_copy->data)->range_str, ((struct cil_context *)test_ast_node->data)->range_str); } void test_cil_copy_fill_context_anonrange(CuTest *tc) { char *line[] = {"(", "context", "packet_default", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_context(test_db, test_tree->root->cl_head->cl_head, test_ast_node); struct cil_tree_node *test_copy; cil_tree_node_init(&test_copy); cil_context_init((struct cil_context**)&test_copy->data); symtab_t sym; symtab_init(&sym, CIL_TEST_SYM_SIZE); int rc = cil_copy_fill_context((struct cil_context*)test_ast_node->data, (struct cil_context*)test_copy->data); CuAssertIntEquals(tc, rc, SEPOL_OK); CuAssertStrEquals(tc, ((struct cil_context *)test_copy->data)->user_str, ((struct cil_context *)test_ast_node->data)->user_str); CuAssertStrEquals(tc, ((struct cil_context *)test_copy->data)->role_str, ((struct cil_context *)test_ast_node->data)->role_str); CuAssertStrEquals(tc, ((struct cil_context *)test_copy->data)->type_str, ((struct cil_context *)test_ast_node->data)->type_str); CuAssertStrEquals(tc, ((struct cil_context *)test_copy->data)->range_str, ((struct cil_context *)test_ast_node->data)->range_str); } void test_cil_copy_call(CuTest *tc) { char *line[] = {"(", "call", "mm", "(", "foo", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_call(test_db, test_tree->root->cl_head->cl_head, test_ast_node); struct cil_call *test_copy; symtab_t sym; symtab_init(&sym, CIL_TEST_SYM_SIZE); int rc = cil_copy_call(test_db, test_ast_node->data, (void**)&test_copy, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); CuAssertStrEquals(tc, test_copy->macro_str, ((struct cil_call *)test_ast_node->data)->macro_str); } void test_cil_copy_optional(CuTest *tc) { char *line[] = {"(", "optional", "opt", "(", "allow", "foo", "bar", "(", "file", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_optional(test_db, test_tree->root->cl_head->cl_head, test_ast_node); struct cil_tree_node *test_copy; cil_tree_node_init(&test_copy); symtab_t sym; symtab_init(&sym, CIL_TEST_SYM_SIZE); int rc = cil_copy_optional(test_db, test_ast_node->data, &test_copy->data, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); } void test_cil_copy_nodecon(CuTest *tc) { char *line[] = {"(", "nodecon", "ipaddr", "ipaddr", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_nodecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); struct cil_nodecon *test_copy; symtab_t sym; symtab_init(&sym, CIL_TEST_SYM_SIZE); int rc = cil_copy_nodecon(test_db, test_ast_node->data, (void**)&test_copy, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); CuAssertStrEquals(tc, test_copy->addr_str, ((struct cil_nodecon *)test_ast_node->data)->addr_str); CuAssertStrEquals(tc, test_copy->mask_str, ((struct cil_nodecon *)test_ast_node->data)->mask_str); CuAssertStrEquals(tc, test_copy->context_str, ((struct cil_nodecon *)test_ast_node->data)->context_str); } void test_cil_copy_nodecon_anon(CuTest *tc) { char *line[] = {"(", "nodecon", "(", "192.168.1.1", ")", "(", "192.168.1.1", ")", "(", "user", "role", "type", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_nodecon(test_db, test_tree->root->cl_head->cl_head, test_ast_node); struct cil_nodecon *test_copy; symtab_t sym; symtab_init(&sym, CIL_TEST_SYM_SIZE); int rc = cil_copy_nodecon(test_db, test_ast_node->data, (void**)&test_copy, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); CuAssertStrEquals(tc, test_copy->addr_str, ((struct cil_nodecon *)test_ast_node->data)->addr_str); CuAssertStrEquals(tc, test_copy->mask_str, ((struct cil_nodecon *)test_ast_node->data)->mask_str); CuAssertStrEquals(tc, test_copy->context_str, ((struct cil_nodecon *)test_ast_node->data)->context_str); } void test_cil_copy_fill_ipaddr(CuTest *tc) { char *line[] = {"(", "ipaddr", "ip", "192.168.1.1", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_ipaddr(test_db, test_tree->root->cl_head->cl_head, test_ast_node); symtab_t sym; symtab_init(&sym, CIL_TEST_SYM_SIZE); struct cil_ipaddr *new; cil_ipaddr_init(&new); struct cil_ipaddr *old; cil_ipaddr_init(&new); old = (struct cil_ipaddr*)test_ast_node->data; int rc = cil_copy_fill_ipaddr(old, new); CuAssertIntEquals(tc, rc, SEPOL_OK); CuAssertIntEquals(tc, old->family, new->family); } void test_cil_copy_ipaddr(CuTest *tc) { char *line[] = {"(", "ipaddr", "ip", "192.168.1.1", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_ipaddr(test_db, test_tree->root->cl_head->cl_head, test_ast_node); struct cil_tree_node *test_copy; cil_tree_node_init(&test_copy); symtab_t sym; symtab_init(&sym, CIL_TEST_SYM_SIZE); int rc = cil_copy_ipaddr(test_db, test_ast_node->data, &test_copy->data, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); } void test_cil_copy_conditional(CuTest *tc) { char *line[] = {"(", "booleanif", "(", "and", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "(", "file", "(", "read", ")", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_boolif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); struct cil_list_item *curr_old; curr_old = ((struct cil_booleanif*)test_ast_node->data)->expr_stack->head; struct cil_conditional *cond_new; symtab_t sym; symtab_init(&sym, CIL_TEST_SYM_SIZE); int rc = cil_copy_conditional(test_db, curr_old->data, (void**)&cond_new, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); CuAssertStrEquals(tc, ((struct cil_conditional*)curr_old->data)->str, cond_new->str); CuAssertIntEquals(tc, ((struct cil_conditional*)curr_old->data)->flavor, cond_new->flavor); } void test_cil_copy_boolif(CuTest *tc) { char *line[] = {"(", "booleanif", "(", "and", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "(", "file", "(", "read", ")", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_boolif(test_db, test_tree->root->cl_head->cl_head, test_ast_node); struct cil_booleanif *test_copy; symtab_t sym; symtab_init(&sym, CIL_TEST_SYM_SIZE); int rc = cil_copy_boolif(test_db, test_ast_node->data, (void**)&test_copy, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); } void test_cil_copy_constrain(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "l2", "h2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_constrain(test_db, test_tree->root->cl_head->cl_head, test_ast_node, CIL_MLSCONSTRAIN); struct cil_constrain *test_copy; symtab_t sym; symtab_init(&sym, CIL_TEST_SYM_SIZE); int rc = cil_copy_constrain(test_db, test_ast_node->data, (void**)&test_copy, &sym); CuAssertIntEquals(tc, rc, SEPOL_OK); CuAssertStrEquals(tc, ((struct cil_constrain*)test_copy)->classpermset->class_str, ((struct cil_constrain *)test_ast_node->data)->classpermset->class_str); } /* void test_cil_copy_ast(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "dir", ")", "(", "create", "relabelto", ")", "(", "eq", "l2", "h2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_constrain(test_db, test_tree->root->cl_head->cl_head, test_ast_node, CIL_MLSCONSTRAIN); struct cil_tree_node *test_current; test_current = test_tree->root->cl_head->cl_head; struct cil_constrain *test_copy; cil_constrain_init(&test_copy); cil_list_init(&test_copy->expr); int rc = cil_copy_ast(((struct cil_constrain *)test_ast_node->data)->expr, test_copy->expr); CuAssertIntEquals(tc, rc, SEPOL_OK); } void test_cil_copy_ast_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_gen_constrain(test_db, test_tree->root->cl_head->cl_head, test_ast_node, CIL_MLSCONSTRAIN); struct cil_tree_node *test_current; test_current = test_tree->root->cl_head->cl_head; struct cil_constrain *test_copy; cil_constrain_init(&test_copy); cil_list_init(&test_copy->expr); int rc = cil_copy_ast(((struct cil_constrain *)test_ast_node->data)->expr, test_copy->expr); CuAssertIntEquals(tc, rc, SEPOL_ERR); } */ /* node_helper functions */ void test_cil_copy_node_helper_block(CuTest *tc) { char *line[] = {"(", "block", "a", "(", "type", "log", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_db *test_db2; cil_db_init(&test_db2); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db2->ast->root, test_db2); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_block_merge(CuTest *tc) { char *line[] = {"(", "block", "a", "(", "type", "log", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db->ast->root, test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_perm(CuTest *tc) { char *line[] = {"(", "class", "foo", "(", "read", "write", "open", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_db *test_db2; cil_db_init(&test_db2); uint32_t finished = 0; struct cil_class *test_class; cil_class_init(&test_class); struct cil_tree_node *parent_node; cil_tree_node_init(&parent_node); parent_node->flavor = CIL_CLASS; parent_node->data = test_class; struct cil_tree_node *root; cil_tree_node_init(&root); root->flavor = CIL_ROOT; parent_node->parent = root; struct cil_args_copy *extra_args = gen_copy_args(parent_node, test_db2); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_perm_neg(CuTest *tc) { char *line[] = {"(", "class", "foo", "(", "read", "write", "open", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db->ast->root, test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_copy_node_helper_class(CuTest *tc) { char *line[] = {"(", "class", "file", "(", "read", "write", "open", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_db *test_db2; cil_db_init(&test_db2); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db2->ast->root, test_db2); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_class_dup_neg(CuTest *tc) { char *line[] = {"(", "class", "test", "(", "read", "write", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db->ast->root, test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_copy_node_helper_common(CuTest *tc) { char *line[] = {"(", "common", "test", "(", "read", "write", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_db *test_db2; cil_db_init(&test_db2); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db2->ast->root, test_db2); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_common_dup_neg(CuTest *tc) { char *line[] = {"(", "class", "file", "(", "read", "write", "open", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db->ast->root, test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_copy_node_helper_classcommon(CuTest *tc) { char *line[] = {"(", "classcommon", "file", "file", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_db *test_db2; cil_db_init(&test_db2); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db2->ast->root, test_db2); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_sid(CuTest *tc) { char *line[] = {"(", "sid", "test", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_db *test_db2; cil_db_init(&test_db2); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db2->ast->root, test_db2); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_sid_merge(CuTest *tc) { char *line[] = {"(", "sid", "test", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db->ast->root, test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_sidcontext(CuTest *tc) { char *line[] = {"(", "sidcontext", "test", "(", "blah_u", "blah_r", "blah_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_db *test_db2; cil_db_init(&test_db2); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db2->ast->root, test_db2); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_user(CuTest *tc) { char *line[] = {"(", "user", "sysadm", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_db *test_db2; cil_db_init(&test_db2); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db2->ast->root, test_db2); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_user_merge(CuTest *tc) { char *line[] = {"(", "user", "sysadm", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db->ast->root, test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_role(CuTest *tc) { char *line[] = {"(", "role", "role_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_db *test_db2; cil_db_init(&test_db2); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db2->ast->root, test_db2); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_role_merge(CuTest *tc) { char *line[] = {"(", "role", "role_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db->ast->root, test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_userrole(CuTest *tc) { char *line[] = {"(", "userrole", "staff_u", "staff_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_db *test_db2; cil_db_init(&test_db2); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db2->ast->root, test_db2); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_type(CuTest *tc) { char *line[] = {"(", "type", "type_t", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_db *test_db2; cil_db_init(&test_db2); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db2->ast->root, test_db2); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_type_merge(CuTest *tc) { char *line[] = {"(", "type", "type_t", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db->ast->root, test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_typeattribute(CuTest *tc) { char *line[] = {"(", "typeattribute", "bar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_db *test_db2; cil_db_init(&test_db2); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db2->ast->root, test_db2); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_typeattribute_merge(CuTest *tc) { char *line[] = {"(", "typeattribute", "bar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db->ast->root, test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_typealias(CuTest *tc) { char *line[] = {"(", "typealias", ".test.type", "type_t", ")", "(", "type", "test", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_db *test_db2; cil_db_init(&test_db2); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db2->ast->root, test_db2); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_typealias_dup_neg(CuTest *tc) { char *line[] = {"(", "typealias", ".test.type", "type_t", ")", "(", "type", "test", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db->ast->root, test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_copy_node_helper_bool(CuTest *tc) { char *line[] = {"(", "boolean", "foo", "true", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_db *test_db2; cil_db_init(&test_db2); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db2->ast->root, test_db2); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_bool_dup_neg(CuTest *tc) { char *line[] = {"(", "boolean", "foo", "true", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db->ast->root, test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_copy_node_helper_avrule(CuTest *tc) { char *line[] = {"(", "allow", "test", "foo", "(", "file", "(", "read", "write", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_db *test_db2; cil_db_init(&test_db2); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db2->ast->root, test_db2); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_type_rule(CuTest *tc) { char *line[] = {"(", "typetransition", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_db *test_db2; cil_db_init(&test_db2); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db2->ast->root, test_db2); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_sens(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_db *test_db2; cil_db_init(&test_db2); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db2->ast->root, test_db2); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_sens_merge(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db->ast->root, test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_sensalias(CuTest *tc) { char *line[] = {"(", "sensitivityalias", "s0", "alias", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_db *test_db2; cil_db_init(&test_db2); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db2->ast->root, test_db2); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_sensalias_dup_neg(CuTest *tc) { char *line[] = {"(", "sensitivityalias", "s0", "alias", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db->ast->root, test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_copy_node_helper_cat(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_db *test_db2; cil_db_init(&test_db2); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db2->ast->root, test_db2); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_cat_merge(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db->ast->root, test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_catalias(CuTest *tc) { char *line[] = {"(", "categoryalias", "c0", "red", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_db *test_db2; cil_db_init(&test_db2); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db2->ast->root, test_db2); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_catalias_dup_neg(CuTest *tc) { char *line[] = {"(", "categoryalias", "c0", "red", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db->ast->root, test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_copy_node_helper_senscat(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "sensitivity", "s1", ")", "(", "dominance", "(", "s0", "s1", ")", ")", "(", "category", "c0", ")", "(", "category", "c255", ")", "(", "categoryorder", "(", "c0", "c255", ")", ")", "(", "sensitivitycategory", "s1", "(", "c0", "c255", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_db *test_db2; cil_db_init(&test_db2); uint32_t finished = 0; struct cil_senscat *test_senscat; cil_senscat_init(&test_senscat); struct cil_tree_node *parent_node; cil_tree_node_init(&parent_node); parent_node->flavor = CIL_SENSCAT; parent_node->data = test_senscat; struct cil_args_copy *extra_args = gen_copy_args(parent_node, test_db2); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head->next->next->next->next->next->next, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_catorder(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c255", ")", "(", "categoryorder", "(", "c0", "c255", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_db *test_db2; cil_db_init(&test_db2); uint32_t finished = 0; struct cil_catorder *test_catorder; cil_catorder_init(&test_catorder); struct cil_tree_node *parent_node; cil_tree_node_init(&parent_node); parent_node->flavor = CIL_CATORDER; parent_node->data = test_catorder; struct cil_args_copy *extra_args = gen_copy_args(parent_node, test_db2); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head->next->next, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_dominance(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "sensitivity", "s1", ")", "(", "sensitivity", "s2", ")", "(", "dominance", "(", "s0", "s1", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_db *test_db2; cil_db_init(&test_db2); uint32_t finished = 0; struct cil_sens *test_sens; cil_sens_init(&test_sens); struct cil_tree_node *parent_node; cil_tree_node_init(&parent_node); parent_node->flavor = CIL_SENS; parent_node->data = test_sens; struct cil_args_copy *extra_args = gen_copy_args(parent_node, test_db2); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head->next->next->next, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_level(CuTest *tc) { char *line[] = {"(", "level", "low", "(", "s0", "(", "c1", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_db *test_db2; cil_db_init(&test_db2); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db2->ast->root, test_db2); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_level_dup_neg(CuTest *tc) { char *line[] = {"(", "level", "low", "(", "s0", "(", "c1", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db->ast->root, test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_copy_node_helper_context(CuTest *tc) { char *line[] = {"(", "context", "packet_default", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_db *test_db2; cil_db_init(&test_db2); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db2->ast->root, test_db2); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_context_dup_neg(CuTest *tc) { char *line[] = {"(", "context", "packet_default", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db->ast->root, test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_copy_node_helper_netifcon(CuTest *tc) { char *line[] = {"(", "netifcon", "eth0", "if_default", "packet_default", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_db *test_db2; cil_db_init(&test_db2); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db2->ast->root, test_db2); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_call(CuTest *tc) { char *line[] = {"(", "call", "mm", "(", "foo", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_db *test_db2; cil_db_init(&test_db2); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db2->ast->root, test_db2); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_optional(CuTest *tc) { char *line[] = {"(", "optional", "opt", "(", "allow", "foo", "bar", "(", "file", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_db *test_db2; cil_db_init(&test_db2); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db2->ast->root, test_db2); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_optional_merge(CuTest *tc) { char *line[] = {"(", "optional", "opt", "(", "allow", "foo", "bar", "(", "file", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db->ast->root, test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_ipaddr(CuTest *tc) { char *line[] = {"(", "ipaddr", "ip", "192.168.1.1", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_db *test_db2; cil_db_init(&test_db2); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db2->ast->root, test_db2); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_ipaddr_dup_neg(CuTest *tc) { char *line[] = {"(", "ipaddr", "ip", "192.168.1.1", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db->ast->root, test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_copy_node_helper_boolif(CuTest *tc) { char *line[] = {"(", "booleanif", "(", "and", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "(", "file", "(", "read", ")", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_db *test_db2; cil_db_init(&test_db2); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db2->ast->root, test_db2); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_mlsconstrain(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "l1", "l2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_db *test_db2; cil_db_init(&test_db2); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db2->ast->root, test_db2); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, finished, 0); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_copy_node_helper_orignull_neg(CuTest *tc) { char *line[] = {"(", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_db *test_db2; cil_db_init(&test_db2); uint32_t finished = 0; struct cil_args_copy *extra_args = gen_copy_args(test_db2->ast->root, test_db2); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_copy_node_helper_extraargsnull_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "dir", ")", "(", "create", "relabelto", ")", "(", "eq", "l1", "l2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_db *test_db2; cil_db_init(&test_db2); struct cil_args_copy *extra_args = NULL; uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_copy_node_helper(test_db->ast->root->cl_head, &finished, extra_args); CuAssertIntEquals(tc, SEPOL_ERR, rc); } libsepol-3.8.1/cil/test/unit/test_cil_copy_ast.h000066400000000000000000000147131476211737200217410ustar00rootroot00000000000000/* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #ifndef TEST_CIL_COPY_AST_H_ #define TEST_CIL_COPY_AST_H_ #include "CuTest.h" void test_cil_copy_list(CuTest *); void test_cil_copy_list_sublist(CuTest *); void test_cil_copy_list_sublist_extra(CuTest *); void test_cil_copy_list_orignull_neg(CuTest *); void test_cil_copy_block(CuTest *); void test_cil_copy_node_helper_block(CuTest *tc); void test_cil_copy_node_helper_block_merge(CuTest *tc); void test_cil_copy_perm(CuTest *); void test_cil_copy_node_helper_perm(CuTest *tc); void test_cil_copy_node_helper_perm_neg(CuTest *tc); void test_cil_copy_class(CuTest *); void test_cil_copy_node_helper_class(CuTest *tc); void test_cil_copy_node_helper_class_dup_neg(CuTest *tc); void test_cil_copy_common(CuTest *); void test_cil_copy_node_helper_common(CuTest *tc); void test_cil_copy_node_helper_common_dup_neg(CuTest *tc); void test_cil_copy_classcommon(CuTest *); void test_cil_copy_node_helper_classcommon(CuTest *tc); void test_cil_copy_sid(CuTest *); void test_cil_copy_node_helper_sid(CuTest *tc); void test_cil_copy_node_helper_sid_merge(CuTest *tc); void test_cil_copy_sidcontext(CuTest *); void test_cil_copy_node_helper_sidcontext(CuTest *tc); void test_cil_copy_user(CuTest *); void test_cil_copy_node_helper_user(CuTest *tc); void test_cil_copy_node_helper_user_merge(CuTest *tc); void test_cil_copy_role(CuTest *); void test_cil_copy_node_helper_role(CuTest *tc); void test_cil_copy_node_helper_role_merge(CuTest *tc); void test_cil_copy_userrole(CuTest *); void test_cil_copy_node_helper_userrole(CuTest *tc); void test_cil_copy_type(CuTest *); void test_cil_copy_node_helper_type(CuTest *tc); void test_cil_copy_node_helper_type_merge(CuTest *tc); void test_cil_copy_typeattribute(CuTest *); void test_cil_copy_node_helper_typeattribute(CuTest *tc); void test_cil_copy_node_helper_typeattribute_merge(CuTest *tc); void test_cil_copy_typealias(CuTest *); void test_cil_copy_node_helper_typealias(CuTest *tc); void test_cil_copy_node_helper_typealias_dup_neg(CuTest *tc); void test_cil_copy_bool(CuTest *); void test_cil_copy_node_helper_bool(CuTest *tc); void test_cil_copy_node_helper_bool_dup_neg(CuTest *tc); void test_cil_copy_avrule(CuTest *); void test_cil_copy_node_helper_avrule(CuTest *tc); void test_cil_copy_type_rule(CuTest *); void test_cil_copy_node_helper_type_rule(CuTest *tc); void test_cil_copy_sens(CuTest *); void test_cil_copy_node_helper_sens(CuTest *tc); void test_cil_copy_node_helper_sens_merge(CuTest *tc); void test_cil_copy_sensalias(CuTest *); void test_cil_copy_node_helper_sensalias(CuTest *tc); void test_cil_copy_node_helper_sensalias_dup_neg(CuTest *tc); void test_cil_copy_cat(CuTest *); void test_cil_copy_node_helper_cat(CuTest *tc); void test_cil_copy_node_helper_cat_merge(CuTest *tc); void test_cil_copy_catalias(CuTest *); void test_cil_copy_node_helper_catalias(CuTest *tc); void test_cil_copy_node_helper_catalias_dup_neg(CuTest *tc); void test_cil_copy_senscat(CuTest *); void test_cil_copy_node_helper_senscat(CuTest *tc); void test_cil_copy_catorder(CuTest *); void test_cil_copy_node_helper_catorder(CuTest *tc); void test_cil_copy_dominance(CuTest *); void test_cil_copy_node_helper_dominance(CuTest *tc); void test_cil_copy_level(CuTest *); void test_cil_copy_node_helper_level(CuTest *tc); void test_cil_copy_node_helper_level_dup_neg(CuTest *tc); void test_cil_copy_fill_level(CuTest *); void test_cil_copy_context(CuTest *); void test_cil_copy_node_helper_context(CuTest *tc); void test_cil_copy_node_helper_context_dup_neg(CuTest *tc); void test_cil_copy_netifcon(CuTest *); void test_cil_copy_netifcon_nested(CuTest *); void test_cil_copy_node_helper_netifcon(CuTest *tc); void test_cil_copy_node_helper_netifcon_merge(CuTest *tc); void test_cil_copy_fill_context(CuTest *); void test_cil_copy_fill_context_anonrange(CuTest *); void test_cil_copy_call(CuTest *); void test_cil_copy_node_helper_call(CuTest *tc); void test_cil_copy_optional(CuTest *); void test_cil_copy_node_helper_optional(CuTest *tc); void test_cil_copy_node_helper_optional_merge(CuTest *tc); void test_cil_copy_nodecon(CuTest *); void test_cil_copy_nodecon_anon(CuTest *); void test_cil_copy_fill_ipaddr(CuTest *); void test_cil_copy_ipaddr(CuTest *); void test_cil_copy_node_helper_ipaddr(CuTest *tc); void test_cil_copy_node_helper_ipaddr_dup_neg(CuTest *tc); void test_cil_copy_conditional(CuTest *); void test_cil_copy_boolif(CuTest *); void test_cil_copy_node_helper_boolif(CuTest *tc); void test_cil_copy_constrain(CuTest *); void test_cil_copy_node_helper_mlsconstrain(CuTest *tc); void test_cil_copy_ast(CuTest *); void test_cil_copy_ast_neg(CuTest *); void test_cil_copy_node_helper_orignull_neg(CuTest *tc); void test_cil_copy_node_helper_extraargsnull_neg(CuTest *tc); void test_cil_copy_data_helper(CuTest *tc); void test_cil_copy_data_helper_getparentsymtab_neg(CuTest *tc); void test_cil_copy_data_helper_duplicatedb_neg(CuTest *tc); #endif libsepol-3.8.1/cil/test/unit/test_cil_fqn.c000066400000000000000000000055201476211737200206730ustar00rootroot00000000000000/* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #include #include "CuTest.h" #include "CilTest.h" #include "../../src/cil_fqn.h" #include "../../src/cil_build_ast.h" void test_cil_qualify_name(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "categoryorder", "(", "c0", ")", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "type", "blah_t", ")", "(", "role", "blah_r", ")", "(", "user", "blah_u", ")", "(", "context", "con", "(", "blah_u", "blah_r", "blah_t", "(", "s0", "(", "c0", ")", ")", "(", "s0", "(", "c0", ")", ")", ")", ")", "(", "sid", "test", "con", NULL}; struct cil_tree *tree; gen_test_tree(&tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, tree->root, test_db->ast->root); int rc = cil_fqn_qualify(test_db->ast->root); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_qualify_name_cil_flavor(CuTest *tc) { char *line[] = {"(", "class", "file", "inherits", "file", "(", "open", ")", ")", NULL}; struct cil_tree *tree; gen_test_tree(&tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, tree->root, test_db->ast->root); int rc = cil_fqn_qualify(test_db->ast->root); CuAssertIntEquals(tc, SEPOL_OK, rc); } libsepol-3.8.1/cil/test/unit/test_cil_fqn.h000066400000000000000000000033621476211737200207020ustar00rootroot00000000000000/* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #ifndef TEST_CIL_FQN_H_ #define TEST_CIL_FQN_H_ #include "CuTest.h" void test_cil_qualify_name(CuTest *); void test_cil_qualify_name_cil_flavor(CuTest *tc); #endif libsepol-3.8.1/cil/test/unit/test_cil_lexer.c000066400000000000000000000067321476211737200212340ustar00rootroot00000000000000/* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #include #include "CuTest.h" #include "test_cil_lexer.h" #include "../../src/cil_lexer.h" void test_cil_lexer_setup(CuTest *tc) { char *test_str = "(test \"qstring\");comment\n"; uint32_t str_size = strlen(test_str); char *buffer = malloc(str_size + 2); memset(buffer+str_size, 0, 2); strncpy(buffer, test_str, str_size); int rc = cil_lexer_setup(buffer, str_size + 2); CuAssertIntEquals(tc, SEPOL_OK, rc); free(buffer); } void test_cil_lexer_next(CuTest *tc) { char *test_str = "(test \"qstring\") ;comment\n"; uint32_t str_size = strlen(test_str); char *buffer = malloc(str_size + 2); memset(buffer+str_size, 0, 2); strcpy(buffer, test_str); cil_lexer_setup(buffer, str_size + 2); struct token test_tok; int rc = cil_lexer_next(&test_tok); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, OPAREN, test_tok.type); CuAssertStrEquals(tc, "(", test_tok.value); CuAssertIntEquals(tc, 1, test_tok.line); rc = cil_lexer_next(&test_tok); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, SYMBOL, test_tok.type); CuAssertStrEquals(tc, "test", test_tok.value); CuAssertIntEquals(tc, 1, test_tok.line); rc = cil_lexer_next(&test_tok); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, QSTRING, test_tok.type); CuAssertStrEquals(tc, "\"qstring\"", test_tok.value); CuAssertIntEquals(tc, 1, test_tok.line); rc = cil_lexer_next(&test_tok); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, CPAREN, test_tok.type); CuAssertStrEquals(tc, ")", test_tok.value); CuAssertIntEquals(tc, 1, test_tok.line); rc = cil_lexer_next(&test_tok); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, COMMENT, test_tok.type); CuAssertStrEquals(tc, ";comment", test_tok.value); CuAssertIntEquals(tc, 1, test_tok.line); free(buffer); } libsepol-3.8.1/cil/test/unit/test_cil_lexer.h000066400000000000000000000033471476211737200212400ustar00rootroot00000000000000/* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #ifndef TEST_CIL_LEXER_H_ #define TEST_CIL_LEXER_H_ #include "CuTest.h" void test_cil_lexer_setup(CuTest *); void test_cil_lexer_next(CuTest *); #endif libsepol-3.8.1/cil/test/unit/test_cil_list.c000066400000000000000000000256071476211737200210720ustar00rootroot00000000000000/* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #include "CuTest.h" #include "CilTest.h" #include "../../src/cil_internal.h" #include "../../src/cil_build_ast.h" void test_cil_list_init(CuTest *tc) { struct cil_avrule *test_avrule = malloc(sizeof(*test_avrule)); cil_classpermset_init(&test_avrule->classpermset); cil_permset_init(&test_avrule->classpermset->permset); cil_list_init(&test_avrule->classpermset->permset->perms_list_str); CuAssertPtrNotNull(tc, test_avrule->classpermset->permset->perms_list_str); cil_destroy_avrule(test_avrule); } void test_cil_list_append_item(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "dir", ")", "(", "create", "relabelto", ")", "(", "eq", "12", "h2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_list *test_class_list; cil_list_init(&test_class_list); struct cil_list_item *test_new_item; cil_list_item_init(&test_new_item); test_new_item->flavor = CIL_CLASS; test_new_item->data = test_tree->root->cl_head->cl_head->next->cl_head; int rc = cil_list_append_item(test_class_list, test_new_item); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_list_append_item_append(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "dir", ")", "(", "create", "relabelto", ")", "(", "eq", "12", "h2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_list *test_class_list; cil_list_init(&test_class_list); struct cil_list_item *test_new_item; cil_list_item_init(&test_new_item); test_new_item->flavor = CIL_CLASS; test_new_item->data = test_tree->root->cl_head->cl_head->next->cl_head; int rc = cil_list_append_item(test_class_list, test_new_item); cil_list_item_init(&test_new_item); test_new_item->flavor = CIL_CLASS; test_new_item->data = test_tree->root->cl_head->cl_head->next->cl_head->next; int rc2 = cil_list_append_item(test_class_list, test_new_item); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, SEPOL_OK, rc2); } void test_cil_list_append_item_append_extra(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "dir", "process", ")", "(", "create", "relabelto", ")", "(", "eq", "12", "h2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_list *test_class_list; cil_list_init(&test_class_list); struct cil_list_item *test_new_item; cil_list_item_init(&test_new_item); test_new_item->flavor = CIL_CLASS; test_new_item->data = test_tree->root->cl_head->cl_head->next->cl_head; int rc = cil_list_append_item(test_class_list, test_new_item); cil_list_item_init(&test_new_item); test_new_item->flavor = CIL_CLASS; test_new_item->data = test_tree->root->cl_head->cl_head->next->cl_head->next; int rc2 = cil_list_append_item(test_class_list, test_new_item); cil_list_item_init(&test_new_item); test_new_item->flavor = CIL_CLASS; test_new_item->data = test_tree->root->cl_head->cl_head->next->cl_head->next->next; int rc3 = cil_list_append_item(test_class_list, test_new_item); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, SEPOL_OK, rc2); CuAssertIntEquals(tc, SEPOL_OK, rc3); } void test_cil_list_append_item_listnull_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "dir", ")", "(", "create", "relabelto", ")", "(", "eq", "12", "h2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_list *test_class_list = NULL; struct cil_list_item *test_new_item; cil_list_item_init(&test_new_item); test_new_item->flavor = CIL_CLASS; test_new_item->data = test_tree->root->cl_head->cl_head->next->cl_head; int rc = cil_list_append_item(test_class_list, test_new_item); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_list_append_item_itemnull_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "dir", ")", "(", "create", "relabelto", ")", "(", "eq", "12", "h2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_list *test_class_list; cil_list_init(&test_class_list); struct cil_list_item *test_new_item = NULL; int rc = cil_list_append_item(test_class_list, test_new_item); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_list_prepend_item(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "dir", ")", "(", "create", "relabelto", ")", "(", "eq", "12", "h2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_list *test_class_list; cil_list_init(&test_class_list); struct cil_list_item *test_new_item; cil_list_item_init(&test_new_item); test_new_item->flavor = CIL_CLASS; test_new_item->data = test_tree->root->cl_head->cl_head->next->cl_head; int rc = cil_list_prepend_item(test_class_list, test_new_item); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_list_prepend_item_prepend(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "dir", ")", "(", "create", "relabelto", ")", "(", "eq", "12", "h2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_list *test_class_list; cil_list_init(&test_class_list); struct cil_list_item *test_new_item; cil_list_item_init(&test_new_item); test_new_item->flavor = CIL_CLASS; test_new_item->data = test_tree->root->cl_head->cl_head->next->cl_head; int rc = cil_list_prepend_item(test_class_list, test_new_item); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_list_prepend_item_prepend_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "dir", "process", ")", "(", "create", "relabelto", ")", "(", "eq", "12", "h2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_list *test_class_list; cil_list_init(&test_class_list); struct cil_list_item *test_new_item; cil_list_item_init(&test_new_item); test_new_item->flavor = CIL_CLASS; test_new_item->data = test_tree->root->cl_head->cl_head->next->cl_head; struct cil_list_item *test_new_item_next; cil_list_item_init(&test_new_item_next); test_new_item->flavor = CIL_CLASS; test_new_item->data = test_tree->root->cl_head->cl_head->next->cl_head->next; test_new_item->next = test_new_item_next; int rc = cil_list_prepend_item(test_class_list, test_new_item); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_list_prepend_item_listnull_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "dir", ")", "(", "create", "relabelto", ")", "(", "eq", "12", "h2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_list *test_class_list = NULL; struct cil_list_item *test_new_item; cil_list_item_init(&test_new_item); test_new_item->flavor = CIL_CLASS; test_new_item->data = test_tree->root->cl_head->cl_head->next->cl_head; int rc = cil_list_prepend_item(test_class_list, test_new_item); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_list_prepend_item_itemnull_neg(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "dir", ")", "(", "create", "relabelto", ")", "(", "eq", "12", "h2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; struct cil_list *test_class_list; cil_list_init(&test_class_list); struct cil_list_item *test_new_item = NULL; int rc = cil_list_prepend_item(test_class_list, test_new_item); CuAssertIntEquals(tc, SEPOL_ERR, rc); } libsepol-3.8.1/cil/test/unit/test_cil_list.h000066400000000000000000000042361476211737200210720ustar00rootroot00000000000000/* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #ifndef TEST_CIL_LIST_H_ #define TEST_CIL_LIST_H_ #include "CuTest.h" void test_cil_list_item_init(CuTest *); void test_cil_list_append_item(CuTest *); void test_cil_list_append_item_append(CuTest *); void test_cil_list_append_item_append_extra(CuTest *); void test_cil_list_append_item_listnull_neg(CuTest *); void test_cil_list_append_item_itemnull_neg(CuTest *); void test_cil_list_prepend_item_prepend(CuTest *); void test_cil_list_prepend_item_prepend_neg(CuTest *); void test_cil_list_prepend_item_listnull_neg(CuTest *); void test_cil_list_prepend_item_itemnull_neg(CuTest *); #endif libsepol-3.8.1/cil/test/unit/test_cil_parser.c000066400000000000000000000043601476211737200214040ustar00rootroot00000000000000/* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #include #include "CuTest.h" #include "CilTest.h" #include "test_cil_parser.h" #include "../../src/cil_parser.h" #include "../../src/cil_internal.h" // TODO rewrite to use the gen_tree function void test_cil_parser(CuTest *tc) { int rc = 0; struct cil_file_data *data; struct cil_tree *test_parse_root; cil_tree_init(&test_parse_root); struct cil_db *test_db; cil_db_init(&test_db); set_cil_file_data(&data); rc = cil_parser("policy.cil", data->buffer, data->file_size + 2, &test_parse_root); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertPtrNotNull(tc, test_parse_root); // TODO add checking of the parse tree that is returned } libsepol-3.8.1/cil/test/unit/test_cil_parser.h000066400000000000000000000033001476211737200214020ustar00rootroot00000000000000/* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #ifndef TEST_CIL_PARSER_H_ #define TEST_CIL_PARSER_H_ #include "CuTest.h" void test_cil_parser(CuTest *); #endif libsepol-3.8.1/cil/test/unit/test_cil_post.c000066400000000000000000000506661476211737200211070ustar00rootroot00000000000000/* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #include #include "CuTest.h" #include "CilTest.h" #include "test_cil_post.h" #include "../../src/cil_post.h" #include "../../src/cil_internal.h" void test_cil_post_filecon_compare_meta_a_not_b(CuTest *tc) { struct cil_filecon *afilecon; cil_filecon_init(&afilecon); struct cil_filecon *bfilecon; cil_filecon_init(&bfilecon); afilecon->root_str = "ba.r"; afilecon->path_str = "foo"; bfilecon->root_str = "barr"; bfilecon->path_str = "foo"; int rc = cil_post_filecon_compare(&afilecon, &bfilecon); CuAssertTrue(tc, rc < 0); } void test_cil_post_filecon_compare_meta_b_not_a(CuTest *tc) { struct cil_filecon *afilecon; cil_filecon_init(&afilecon); struct cil_filecon *bfilecon; cil_filecon_init(&bfilecon); afilecon->root_str = "bar"; afilecon->path_str = "foo"; bfilecon->root_str = "ba.rr"; bfilecon->path_str = "foo"; int rc = cil_post_filecon_compare(&afilecon, &bfilecon); CuAssertTrue(tc, rc > 0); } void test_cil_post_filecon_compare_meta_a_and_b_strlen_a_greater_b(CuTest *tc) { struct cil_filecon *afilecon; cil_filecon_init(&afilecon); struct cil_filecon *bfilecon; cil_filecon_init(&bfilecon); afilecon->root_str = ".\\$"; afilecon->path_str = ".$({"; bfilecon->root_str = ".?"; bfilecon->path_str = "."; int rc = cil_post_filecon_compare(&afilecon, &bfilecon); CuAssertTrue(tc, rc > 0); } void test_cil_post_filecon_compare_type_atype_greater_btype(CuTest *tc) { struct cil_filecon *afilecon; cil_filecon_init(&afilecon); struct cil_filecon *bfilecon; cil_filecon_init(&bfilecon); afilecon->root_str = ".\\$"; afilecon->path_str = ".$({"; afilecon->type = CIL_FILECON_CHAR; bfilecon->root_str = ".\\$"; bfilecon->path_str = ".$({"; bfilecon->type = CIL_FILECON_DIR; int rc = cil_post_filecon_compare(&afilecon, &bfilecon); CuAssertTrue(tc, rc > 0); } void test_cil_post_filecon_compare_type_btype_greater_atype(CuTest *tc) { struct cil_filecon *afilecon; cil_filecon_init(&afilecon); struct cil_filecon *bfilecon; cil_filecon_init(&bfilecon); afilecon->root_str = ".\\$"; afilecon->path_str = ".$({"; afilecon->type = CIL_FILECON_DIR; bfilecon->root_str = ".\\$"; bfilecon->path_str = ".$({"; bfilecon->type = CIL_FILECON_CHAR; int rc = cil_post_filecon_compare(&afilecon, &bfilecon); CuAssertTrue(tc, rc < 0); } void test_cil_post_filecon_compare_meta_a_and_b_strlen_b_greater_a(CuTest *tc) { struct cil_filecon *afilecon; cil_filecon_init(&afilecon); struct cil_filecon *bfilecon; cil_filecon_init(&bfilecon); afilecon->root_str = "."; afilecon->path_str = "."; bfilecon->root_str = ".*+|[({"; bfilecon->path_str = "."; int rc = cil_post_filecon_compare(&afilecon, &bfilecon); CuAssertTrue(tc, rc < 0); } void test_cil_post_filecon_compare_stemlen_a_greater_b(CuTest *tc) { struct cil_filecon *afilecon; cil_filecon_init(&afilecon); struct cil_filecon *bfilecon; cil_filecon_init(&bfilecon); afilecon->root_str = "bar"; afilecon->path_str = "foo"; bfilecon->root_str = "barr"; bfilecon->path_str = "foo"; int rc = cil_post_filecon_compare(&afilecon, &bfilecon); CuAssertTrue(tc, rc < 0); } void test_cil_post_filecon_compare_stemlen_b_greater_a(CuTest *tc) { struct cil_filecon *afilecon; cil_filecon_init(&afilecon); struct cil_filecon *bfilecon; cil_filecon_init(&bfilecon); afilecon->root_str = "barre"; afilecon->path_str = "foo"; bfilecon->root_str = "barr"; bfilecon->path_str = "foo"; int rc = cil_post_filecon_compare(&afilecon, &bfilecon); CuAssertTrue(tc, rc > 0); } void test_cil_post_filecon_compare_equal(CuTest *tc) { struct cil_filecon *afilecon; cil_filecon_init(&afilecon); struct cil_filecon *bfilecon; cil_filecon_init(&bfilecon); afilecon->root_str = ".\\$"; afilecon->path_str = ".$({"; afilecon->type = CIL_FILECON_DIR; bfilecon->root_str = ".\\$"; bfilecon->path_str = ".$({"; bfilecon->type = CIL_FILECON_DIR; int rc = cil_post_filecon_compare(&afilecon, &bfilecon); CuAssertIntEquals(tc, 0, rc); } void test_cil_post_portcon_compare_atotal_greater_btotal(CuTest *tc) { struct cil_portcon *aportcon; cil_portcon_init(&aportcon); struct cil_portcon *bportcon; cil_portcon_init(&bportcon); aportcon->port_low = 15; aportcon->port_high = 30; bportcon->port_low = 10; bportcon->port_high = 11; int rc = cil_post_portcon_compare(&aportcon, &bportcon); CuAssertTrue(tc, rc > 0); } void test_cil_post_portcon_compare_btotal_greater_atotal(CuTest *tc) { struct cil_portcon *aportcon; cil_portcon_init(&aportcon); struct cil_portcon *bportcon; cil_portcon_init(&bportcon); aportcon->port_low = 5; aportcon->port_high = 5; bportcon->port_low = 11; bportcon->port_high = 20; int rc = cil_post_portcon_compare(&aportcon, &bportcon); CuAssertTrue(tc, rc < 0); } void test_cil_post_portcon_compare_aportlow_greater_bportlow(CuTest *tc) { struct cil_portcon *aportcon; cil_portcon_init(&aportcon); struct cil_portcon *bportcon; cil_portcon_init(&bportcon); aportcon->port_low = 30; aportcon->port_high = 33; bportcon->port_low = 17; bportcon->port_high = 20; int rc = cil_post_portcon_compare(&aportcon, &bportcon); CuAssertTrue(tc, rc > 0); } void test_cil_post_portcon_compare_bportlow_greater_aportlow(CuTest *tc) { struct cil_portcon *aportcon; cil_portcon_init(&aportcon); struct cil_portcon *bportcon; cil_portcon_init(&bportcon); aportcon->port_low = 5; aportcon->port_high = 8; bportcon->port_low = 17; bportcon->port_high = 20; int rc = cil_post_portcon_compare(&aportcon, &bportcon); CuAssertTrue(tc, rc < 0); } void test_cil_post_portcon_compare_equal(CuTest *tc) { struct cil_portcon *aportcon; cil_portcon_init(&aportcon); struct cil_portcon *bportcon; cil_portcon_init(&bportcon); aportcon->port_low = 17; aportcon->port_high = 20; bportcon->port_low = 17; bportcon->port_high = 20; int rc = cil_post_portcon_compare(&aportcon, &bportcon); CuAssertTrue(tc, rc == 0); } void test_cil_post_genfscon_compare_atypestr_greater_btypestr(CuTest *tc) { struct cil_genfscon *agenfscon; cil_genfscon_init(&agenfscon); agenfscon->fs_str = "aaaa"; struct cil_genfscon *bgenfscon; cil_genfscon_init(&bgenfscon); bgenfscon->fs_str = "bbbb"; int rc = cil_post_genfscon_compare(&agenfscon, &bgenfscon); CuAssertTrue(tc, rc < 0); } void test_cil_post_genfscon_compare_btypestr_greater_atypestr(CuTest *tc) { struct cil_genfscon *agenfscon; cil_genfscon_init(&agenfscon); agenfscon->fs_str = "bbbb"; struct cil_genfscon *bgenfscon; cil_genfscon_init(&bgenfscon); bgenfscon->fs_str = "aaaa"; int rc = cil_post_genfscon_compare(&agenfscon, &bgenfscon); CuAssertTrue(tc, rc > 0); } void test_cil_post_genfscon_compare_apathstr_greater_bpathstr(CuTest *tc) { struct cil_genfscon *agenfscon; cil_genfscon_init(&agenfscon); agenfscon->fs_str = "aaaa"; agenfscon->path_str = "ff"; struct cil_genfscon *bgenfscon; cil_genfscon_init(&bgenfscon); bgenfscon->fs_str = "aaaa"; bgenfscon->path_str = "gg"; int rc = cil_post_genfscon_compare(&agenfscon, &bgenfscon); CuAssertTrue(tc, rc < 0); } void test_cil_post_genfscon_compare_bpathstr_greater_apathstr(CuTest *tc) { struct cil_genfscon *agenfscon; cil_genfscon_init(&agenfscon); agenfscon->fs_str = "bbbb"; agenfscon->path_str = "cccc"; struct cil_genfscon *bgenfscon; cil_genfscon_init(&bgenfscon); bgenfscon->fs_str = "bbbb"; bgenfscon->path_str = "aaaa"; int rc = cil_post_genfscon_compare(&agenfscon, &bgenfscon); CuAssertTrue(tc, rc > 0); } void test_cil_post_genfscon_compare_equal(CuTest *tc) { struct cil_genfscon *agenfscon; cil_genfscon_init(&agenfscon); agenfscon->fs_str = "bbbb"; agenfscon->path_str = "cccc"; struct cil_genfscon *bgenfscon; cil_genfscon_init(&bgenfscon); bgenfscon->fs_str = "bbbb"; bgenfscon->path_str = "cccc"; int rc = cil_post_genfscon_compare(&agenfscon, &bgenfscon); CuAssertIntEquals(tc, 0, rc); } void test_cil_post_netifcon_compare_a_greater_b(CuTest *tc) { struct cil_netifcon *anetifcon; cil_netifcon_init(&anetifcon); anetifcon->interface_str = "aaa"; struct cil_netifcon *bnetifcon; cil_netifcon_init(&bnetifcon); bnetifcon->interface_str = "bbb"; int rc = cil_post_netifcon_compare(&anetifcon, &bnetifcon); CuAssertTrue(tc, rc < 0); } void test_cil_post_netifcon_compare_b_greater_a(CuTest *tc) { struct cil_netifcon *anetifcon; cil_netifcon_init(&anetifcon); anetifcon->interface_str = "bbb"; struct cil_netifcon *bnetifcon; cil_netifcon_init(&bnetifcon); bnetifcon->interface_str = "aaa"; int rc = cil_post_netifcon_compare(&anetifcon, &bnetifcon); CuAssertTrue(tc, rc > 0); } void test_cil_post_netifcon_compare_equal(CuTest *tc) { struct cil_netifcon *anetifcon; cil_netifcon_init(&anetifcon); anetifcon->interface_str = "aaa"; struct cil_netifcon *bnetifcon; cil_netifcon_init(&bnetifcon); bnetifcon->interface_str = "aaa"; int rc = cil_post_netifcon_compare(&anetifcon, &bnetifcon); CuAssertTrue(tc, rc == 0); } void test_cil_post_nodecon_compare_aipv4_bipv6(CuTest *tc) { struct cil_nodecon *anodecon; cil_nodecon_init(&anodecon); cil_ipaddr_init(&anodecon->addr); cil_ipaddr_init(&anodecon->mask); struct cil_nodecon *bnodecon; cil_nodecon_init(&bnodecon); cil_ipaddr_init(&bnodecon->addr); cil_ipaddr_init(&bnodecon->mask); anodecon->addr->ip.v4.s_addr = 103; anodecon->mask->ip.v4.s_addr = 100; anodecon->addr->family = AF_INET; bnodecon->addr->ip.v4.s_addr = 100; bnodecon->mask->ip.v4.s_addr = 100; bnodecon->addr->family = AF_INET6; int rc = cil_post_nodecon_compare(&anodecon, &bnodecon); CuAssertTrue(tc, rc < 0); } void test_cil_post_nodecon_compare_aipv6_bipv4(CuTest *tc) { struct cil_nodecon *anodecon; cil_nodecon_init(&anodecon); cil_ipaddr_init(&anodecon->addr); cil_ipaddr_init(&anodecon->mask); struct cil_nodecon *bnodecon; cil_nodecon_init(&bnodecon); cil_ipaddr_init(&bnodecon->addr); cil_ipaddr_init(&bnodecon->mask); anodecon->addr->ip.v4.s_addr = 103; anodecon->mask->ip.v4.s_addr = 100; anodecon->addr->family = AF_INET6; bnodecon->addr->ip.v4.s_addr = 100; bnodecon->mask->ip.v4.s_addr = 100; bnodecon->addr->family = AF_INET; int rc = cil_post_nodecon_compare(&anodecon, &bnodecon); CuAssertTrue(tc, rc > 0); } void test_cil_post_nodecon_compare_aipv4_greaterthan_bipv4(CuTest *tc) { struct cil_nodecon *anodecon; cil_nodecon_init(&anodecon); cil_ipaddr_init(&anodecon->addr); cil_ipaddr_init(&anodecon->mask); struct cil_nodecon *bnodecon; cil_nodecon_init(&bnodecon); cil_ipaddr_init(&bnodecon->addr); cil_ipaddr_init(&bnodecon->mask); anodecon->addr->ip.v4.s_addr = 103; anodecon->mask->ip.v4.s_addr = 100; anodecon->addr->family = AF_INET; bnodecon->addr->ip.v4.s_addr = 100; bnodecon->mask->ip.v4.s_addr = 100; bnodecon->addr->family = AF_INET; int rc = cil_post_nodecon_compare(&anodecon, &bnodecon); CuAssertTrue(tc, rc > 0); } void test_cil_post_nodecon_compare_aipv4_lessthan_bipv4(CuTest *tc) { struct cil_nodecon *anodecon; cil_nodecon_init(&anodecon); cil_ipaddr_init(&anodecon->addr); cil_ipaddr_init(&anodecon->mask); struct cil_nodecon *bnodecon; cil_nodecon_init(&bnodecon); cil_ipaddr_init(&bnodecon->addr); cil_ipaddr_init(&bnodecon->mask); anodecon->addr->ip.v4.s_addr = 99; anodecon->mask->ip.v4.s_addr = 100; anodecon->addr->family = AF_INET; bnodecon->addr->ip.v4.s_addr = 100; bnodecon->mask->ip.v4.s_addr = 100; bnodecon->addr->family = AF_INET; int rc = cil_post_nodecon_compare(&anodecon, &bnodecon); CuAssertTrue(tc, rc < 0); } void test_cil_post_nodecon_compare_amaskipv4_greaterthan_bmaskipv4(CuTest *tc) { struct cil_nodecon *anodecon; cil_nodecon_init(&anodecon); cil_ipaddr_init(&anodecon->addr); cil_ipaddr_init(&anodecon->mask); struct cil_nodecon *bnodecon; cil_nodecon_init(&bnodecon); cil_ipaddr_init(&bnodecon->addr); cil_ipaddr_init(&bnodecon->mask); anodecon->addr->ip.v4.s_addr = 103; anodecon->mask->ip.v4.s_addr = 101; anodecon->addr->family = AF_INET; bnodecon->addr->ip.v4.s_addr = 100; bnodecon->mask->ip.v4.s_addr = 100; bnodecon->addr->family = AF_INET; int rc = cil_post_nodecon_compare(&anodecon, &bnodecon); CuAssertTrue(tc, rc < 0); } void test_cil_post_nodecon_compare_amaskipv4_lessthan_bmaskipv4(CuTest *tc) { struct cil_nodecon *anodecon; cil_nodecon_init(&anodecon); cil_ipaddr_init(&anodecon->addr); cil_ipaddr_init(&anodecon->mask); struct cil_nodecon *bnodecon; cil_nodecon_init(&bnodecon); cil_ipaddr_init(&bnodecon->addr); cil_ipaddr_init(&bnodecon->mask); anodecon->addr->ip.v4.s_addr = 99; anodecon->mask->ip.v4.s_addr = 99; anodecon->addr->family = AF_INET; bnodecon->addr->ip.v4.s_addr = 100; bnodecon->mask->ip.v4.s_addr = 100; bnodecon->addr->family = AF_INET; int rc = cil_post_nodecon_compare(&anodecon, &bnodecon); CuAssertTrue(tc, rc > 0); } void test_cil_post_nodecon_compare_aipv6_greaterthan_bipv6(CuTest *tc) { struct cil_nodecon *anodecon; cil_nodecon_init(&anodecon); cil_ipaddr_init(&anodecon->addr); cil_ipaddr_init(&anodecon->mask); struct cil_nodecon *bnodecon; cil_nodecon_init(&bnodecon); cil_ipaddr_init(&bnodecon->addr); cil_ipaddr_init(&bnodecon->mask); anodecon->addr->ip.v6.s6_addr[0] = '5'; anodecon->mask->ip.v6.s6_addr[0] = '9'; anodecon->addr->family = AF_INET6; bnodecon->addr->ip.v6.s6_addr[0] = '3'; bnodecon->mask->ip.v6.s6_addr[0] = '9'; bnodecon->addr->family = AF_INET6; int rc = cil_post_nodecon_compare(&anodecon, &bnodecon); CuAssertTrue(tc, rc > 0); } void test_cil_post_nodecon_compare_aipv6_lessthan_bipv6(CuTest *tc) { struct cil_nodecon *anodecon; cil_nodecon_init(&anodecon); cil_ipaddr_init(&anodecon->addr); cil_ipaddr_init(&anodecon->mask); struct cil_nodecon *bnodecon; cil_nodecon_init(&bnodecon); cil_ipaddr_init(&bnodecon->addr); cil_ipaddr_init(&bnodecon->mask); anodecon->addr->ip.v6.s6_addr[0] = '3'; anodecon->mask->ip.v6.s6_addr[0] = '1'; anodecon->addr->family = AF_INET6; bnodecon->addr->ip.v6.s6_addr[0] = '5'; bnodecon->mask->ip.v6.s6_addr[0] = '1'; bnodecon->addr->family = AF_INET6; int rc = cil_post_nodecon_compare(&anodecon, &bnodecon); CuAssertTrue(tc, rc < 0); } void test_cil_post_nodecon_compare_amaskipv6_greaterthan_bmaskipv6(CuTest *tc) { struct cil_nodecon *anodecon; cil_nodecon_init(&anodecon); cil_ipaddr_init(&anodecon->addr); cil_ipaddr_init(&anodecon->mask); struct cil_nodecon *bnodecon; cil_nodecon_init(&bnodecon); cil_ipaddr_init(&bnodecon->addr); cil_ipaddr_init(&bnodecon->mask); anodecon->addr->ip.v6.s6_addr[0] = '1'; anodecon->mask->ip.v6.s6_addr[0] = '4'; anodecon->addr->family = AF_INET6; bnodecon->addr->ip.v6.s6_addr[0] = '1'; bnodecon->mask->ip.v6.s6_addr[0] = '3'; bnodecon->addr->family = AF_INET6; int rc = cil_post_nodecon_compare(&anodecon, &bnodecon); CuAssertTrue(tc, rc < 0); } void test_cil_post_nodecon_compare_amaskipv6_lessthan_bmaskipv6(CuTest *tc) { struct cil_nodecon *anodecon; cil_nodecon_init(&anodecon); cil_ipaddr_init(&anodecon->addr); cil_ipaddr_init(&anodecon->mask); struct cil_nodecon *bnodecon; cil_nodecon_init(&bnodecon); cil_ipaddr_init(&bnodecon->addr); cil_ipaddr_init(&bnodecon->mask); anodecon->addr->ip.v6.s6_addr[0] = '5'; anodecon->mask->ip.v6.s6_addr[0] = '1'; anodecon->addr->family = AF_INET6; bnodecon->addr->ip.v6.s6_addr[0] = '5'; bnodecon->mask->ip.v6.s6_addr[0] = '6'; bnodecon->addr->family = AF_INET6; int rc = cil_post_nodecon_compare(&anodecon, &bnodecon); CuAssertTrue(tc, rc > 0); } void test_cil_post_fsuse_compare_type_a_greater_b(CuTest *tc) { struct cil_fsuse *afsuse; cil_fsuse_init(&afsuse); afsuse->type = CIL_FSUSE_XATTR; struct cil_fsuse *bfsuse; cil_fsuse_init(&bfsuse); bfsuse->type = CIL_FSUSE_TASK; int rc = cil_post_fsuse_compare(&afsuse, &bfsuse); CuAssertTrue(tc, rc < 0); } void test_cil_post_fsuse_compare_type_b_greater_a(CuTest *tc) { struct cil_fsuse *afsuse; cil_fsuse_init(&afsuse); afsuse->type = CIL_FSUSE_TASK; struct cil_fsuse *bfsuse; cil_fsuse_init(&bfsuse); bfsuse->type = CIL_FSUSE_XATTR; int rc = cil_post_fsuse_compare(&afsuse, &bfsuse); CuAssertTrue(tc, rc > 0); } void test_cil_post_fsuse_compare_fsstr_a_greater_b(CuTest *tc) { struct cil_fsuse *afsuse; cil_fsuse_init(&afsuse); afsuse->type = CIL_FSUSE_XATTR; afsuse->fs_str = "aaa"; struct cil_fsuse *bfsuse; cil_fsuse_init(&bfsuse); bfsuse->type = CIL_FSUSE_XATTR; bfsuse->fs_str = "bbb"; int rc = cil_post_fsuse_compare(&afsuse, &bfsuse); CuAssertTrue(tc, rc < 0); } void test_cil_post_fsuse_compare_fsstr_b_greater_a(CuTest *tc) { struct cil_fsuse *afsuse; cil_fsuse_init(&afsuse); afsuse->type = CIL_FSUSE_XATTR; afsuse->fs_str = "bbb"; struct cil_fsuse *bfsuse; cil_fsuse_init(&bfsuse); bfsuse->type = CIL_FSUSE_XATTR; bfsuse->fs_str = "aaa"; int rc = cil_post_fsuse_compare(&afsuse, &bfsuse); CuAssertTrue(tc, rc > 0); } void test_cil_post_fsuse_compare_equal(CuTest *tc) { struct cil_fsuse *afsuse; cil_fsuse_init(&afsuse); afsuse->type = CIL_FSUSE_XATTR; afsuse->fs_str = "foo"; struct cil_fsuse *bfsuse; cil_fsuse_init(&bfsuse); bfsuse->type = CIL_FSUSE_XATTR; bfsuse->fs_str = "foo"; int rc = cil_post_fsuse_compare(&afsuse, &bfsuse); CuAssertTrue(tc, rc == 0); } libsepol-3.8.1/cil/test/unit/test_cil_post.h000066400000000000000000000101701476211737200210760ustar00rootroot00000000000000/* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #ifndef TEST_CIL_POLICY_H_ #define TEST_CIL_POLICY_H_ #include "CuTest.h" void test_cil_post_filecon_compare_meta_a_not_b(CuTest *tc); void test_cil_post_filecon_compare_meta_b_not_a(CuTest *tc); void test_cil_post_filecon_compare_meta_a_and_b_strlen_a_greater_b(CuTest *tc); void test_cil_post_filecon_compare_meta_a_and_b_strlen_b_greater_a(CuTest *tc); void test_cil_post_filecon_compare_type_atype_greater_btype(CuTest *tc); void test_cil_post_filecon_compare_type_btype_greater_atype(CuTest *tc); void test_cil_post_filecon_compare_stemlen_a_greater_b(CuTest *tc); void test_cil_post_filecon_compare_stemlen_b_greater_a(CuTest *tc); void test_cil_post_filecon_compare_equal(CuTest *tc); void test_cil_post_portcon_compare_atotal_greater_btotal(CuTest *tc); void test_cil_post_portcon_compare_btotal_greater_atotal(CuTest *tc); void test_cil_post_portcon_compare_aportlow_greater_bportlow(CuTest *tc); void test_cil_post_portcon_compare_bportlow_greater_aportlow(CuTest *tc); void test_cil_post_portcon_compare_equal(CuTest *tc); void test_cil_post_genfscon_compare_atypestr_greater_btypestr(CuTest *tc); void test_cil_post_genfscon_compare_btypestr_greater_atypestr(CuTest *tc); void test_cil_post_genfscon_compare_apathstr_greater_bpathstr(CuTest *tc); void test_cil_post_genfscon_compare_bpathstr_greater_apathstr(CuTest *tc); void test_cil_post_genfscon_compare_equal(CuTest *tc); void test_cil_post_netifcon_compare_a_greater_b(CuTest *tc); void test_cil_post_netifcon_compare_b_greater_a(CuTest *tc); void test_cil_post_netifcon_compare_equal(CuTest *tc); void test_cil_post_nodecon_compare_aipv4_bipv6(CuTest *tc); void test_cil_post_nodecon_compare_aipv6_bipv4(CuTest *tc); void test_cil_post_nodecon_compare_aipv4_greaterthan_bipv4(CuTest *tc); void test_cil_post_nodecon_compare_aipv4_lessthan_bipv4(CuTest *tc); void test_cil_post_nodecon_compare_amaskipv4_greaterthan_bmaskipv4(CuTest *tc); void test_cil_post_nodecon_compare_amaskipv4_lessthan_bmaskipv4(CuTest *tc); void test_cil_post_nodecon_compare_aipv6_greaterthan_bipv6(CuTest *tc); void test_cil_post_nodecon_compare_aipv6_lessthan_bipv6(CuTest *tc); void test_cil_post_nodecon_compare_amaskipv6_greaterthan_bmaskipv6(CuTest *tc); void test_cil_post_nodecon_compare_amaskipv6_lessthan_bmaskipv6(CuTest *tc); void test_cil_post_fsuse_compare_type_a_greater_b(CuTest *tc); void test_cil_post_fsuse_compare_type_b_greater_a(CuTest *tc); void test_cil_post_fsuse_compare_fsstr_a_greater_b(CuTest *tc); void test_cil_post_fsuse_compare_fsstr_b_greater_a(CuTest *tc); void test_cil_post_fsuse_compare_equal(CuTest *tc); #endif libsepol-3.8.1/cil/test/unit/test_cil_resolve_ast.c000066400000000000000000014225521476211737200224460ustar00rootroot00000000000000/* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #include #include "CuTest.h" #include "CilTest.h" #include "../../src/cil_build_ast.h" #include "../../src/cil_resolve_ast.h" #include "../../src/cil_verify.h" #include "../../src/cil_internal.h" /* this all needs to be moved to a private header file */ int __cil_resolve_ast_node_helper(struct cil_tree_node *, uint32_t *, void *); int __cil_disable_children_helper(struct cil_tree_node *node, __attribute__((unused)) uint32_t *finished, void *); struct cil_args_resolve { struct cil_db *db; enum cil_pass pass; uint32_t *changed; struct cil_tree_node *callstack; struct cil_tree_node *optstack; struct cil_tree_node *macro; }; struct cil_args_resolve *gen_resolve_args(struct cil_db *db, enum cil_pass pass, uint32_t *changed, struct cil_tree_node *calls, struct cil_tree_node *opts, struct cil_tree_node *macro) { struct cil_args_resolve *args = cil_malloc(sizeof(*args)); args->db = db; args->pass = pass; args->changed = changed; args->callstack = calls; args->optstack = opts; args->macro = macro; return args; } void test_cil_resolve_name(CuTest *tc) { char *line[] = { "(", "block", "foo", "(", "typealias", "test", "type_t", ")", "(", "type", "test", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_tree_node *test_curr = test_db->ast->root->cl_head->cl_head; struct cil_typealias *test_alias = (struct cil_typealias*)test_curr->data; struct cil_tree_node *type_node = NULL; int rc = cil_resolve_name(test_curr, test_alias->type_str, CIL_SYM_TYPES, args, &type_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_name_invalid_type_neg(CuTest *tc) { char *line[] = { "(", "block", "foo", "(", "typealias", "foo.test2", "type_t", ")", "(", "type", "test", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_tree_node *test_curr = test_db->ast->root->cl_head->cl_head; struct cil_typealias *test_alias = (struct cil_typealias*)test_curr->data; struct cil_tree_node *type_node = NULL; int rc = cil_resolve_name(test_curr, test_alias->type_str, CIL_SYM_TYPES, args, &type_node); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_ast_curr_null_neg(CuTest *tc) { struct cil_db *test_db; cil_db_init(&test_db); test_db->ast->root = NULL; int rc = cil_resolve_ast(test_db, test_db->ast->root); CuAssertIntEquals(tc, SEPOL_ERR, rc); } /* cil_resolve test cases */ void test_cil_resolve_roleallow(CuTest *tc) { char *line[] = {"(", "role", "foo", ")", \ "(", "role", "bar", ")", \ "(", "roleallow", "foo", "bar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_roleallow(test_db->ast->root->cl_head->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_roleallow_srcdecl_neg(CuTest *tc) { char *line[] = {"(", "role", "bar", ")", \ "(", "roleallow", "foo", "bar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); int rc1=cil_build_ast(test_db, test_tree->root, test_db->ast->root); rc1 = rc1; int rc = cil_resolve_roleallow(test_db->ast->root->cl_head->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_roleallow_tgtdecl_neg(CuTest *tc) { char *line[] = {"(", "role", "foo", ")", \ "(", "roleallow", "foo", "bar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_roleallow(test_db->ast->root->cl_head->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_classmapping_anon(CuTest *tc) { char *line[] = {"(", "class", "file", "(", "open", ")", ")", "(", "classmap", "files", "(", "read", ")", ")", "(", "classmapping", "files", "read", "(", "file", "(", "open", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_classmapping(test_db->ast->root->cl_head->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_classmapping_anon_inmacro(CuTest *tc) { char *line[] = {"(", "classmap", "files", "(", "read", ")", ")", "(", "class", "file", "(", "open", ")", ")", "(", "macro", "mm", "(", "(", "classpermissionset", "a", ")", ")", "(", "classmapping", "files", "read", "a", ")", ")", "(", "call", "mm", "(", "(", "file", "(", "open", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); args->pass = CIL_PASS_CALL1; int rc2 = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_CALL2; int rc3 = cil_resolve_call2(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_MISC3; args->callstack = test_db->ast->root->cl_head->next->next->next; int rc = cil_resolve_classmapping(test_db->ast->root->cl_head->next->next->next->cl_head, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, SEPOL_OK, rc2); CuAssertIntEquals(tc, SEPOL_OK, rc3); } void test_cil_resolve_classmapping_anon_inmacro_neg(CuTest *tc) { char *line[] = {"(", "classmap", "files", "(", "read", ")", ")", "(", "class", "file", "(", "open", ")", ")", "(", "macro", "mm", "(", "(", "classpermissionset", "a", ")", ")", "(", "classmapping", "files", "read", "a", ")", ")", "(", "call", "mm", "(", "(", "DNE", "(", "open", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); args->pass = CIL_PASS_CALL1; int rc2 = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_CALL2; int rc3 = cil_resolve_call2(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_MISC3; args->callstack = test_db->ast->root->cl_head->next->next->next; int rc = cil_resolve_classmapping(test_db->ast->root->cl_head->next->next->next->cl_head, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, SEPOL_OK, rc2); CuAssertIntEquals(tc, SEPOL_OK, rc3); } void test_cil_resolve_classmapping_named(CuTest *tc) { char *line[] = {"(", "classmap", "files", "(", "read", ")", ")", "(", "classpermissionset", "char_w", "(", "char", "(", "read", ")", ")", ")", "(", "classmapping", "files", "read", "char_w", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_classmapping(test_db->ast->root->cl_head->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_classmapping_named_classmapname_neg(CuTest *tc) { char *line[] = {"(", "classpermissionset", "char_w", "(", "char", "(", "read", ")", ")", ")", "(", "classmap", "files", "(", "read", ")", ")", "(", "classmapping", "files", "read", "foo", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_classmapping(test_db->ast->root->cl_head->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_classmapping_anon_classmapname_neg(CuTest *tc) { char *line[] = {"(", "class", "file", "(", "open", ")", ")", "(", "classmap", "files", "(", "read", ")", ")", "(", "classmapping", "dne", "read", "(", "file", "(", "open", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_classmapping(test_db->ast->root->cl_head->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_classmapping_anon_permset_neg(CuTest *tc) { char *line[] = {"(", "class", "file", "(", "open", ")", ")", "(", "classmap", "files", "(", "read", ")", ")", "(", "classmapping", "files", "read", "(", "dne", "(", "open", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_classmapping(test_db->ast->root->cl_head->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_rolebounds(CuTest *tc) { char *line[] = {"(", "role", "role1", ")", "(", "role", "role2", ")", "(", "rolebounds", "role1", "role2", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_rolebounds(test_db->ast->root->cl_head->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_rolebounds_exists_neg(CuTest *tc) { char *line[] = {"(", "role", "role1", ")", "(", "role", "role2", ")", "(", "rolebounds", "role1", "role2", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_rolebounds(test_db->ast->root->cl_head->next->next, args); int rc = cil_resolve_rolebounds(test_db->ast->root->cl_head->next->next, args); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_resolve_rolebounds_role1_neg(CuTest *tc) { char *line[] = {"(", "role", "role1", ")", "(", "role", "role2", ")", "(", "rolebounds", "role_DNE", "role2", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_rolebounds(test_db->ast->root->cl_head->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_rolebounds_role2_neg(CuTest *tc) { char *line[] = {"(", "role", "role1", ")", "(", "role", "role2", ")", "(", "rolebounds", "role1", "role_DNE", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_rolebounds(test_db->ast->root->cl_head->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_sensalias(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "sensitivityalias", "s0", "alias", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_sensalias(test_db->ast->root->cl_head->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_sensalias_sensdecl_neg(CuTest *tc) { char *line[] = {"(", "sensitivityalias", "s0", "alias", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MLS, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_sensalias(test_db->ast->root->cl_head, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_catalias(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "categoryalias", "c0", "red", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_catalias(test_db->ast->root->cl_head->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_catalias_catdecl_neg(CuTest *tc) { char *line[] = {"(", "categoryalias", "c0", "red", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_catalias(test_db->ast->root->cl_head, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_catorder(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c3", ")", "(", "categoryorder", "(", "c0", "c3", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC1, &changed, NULL, NULL, NULL); int rc = cil_resolve_catorder(test_db->ast->root->cl_head->next->next, args); int rc2 = cil_resolve_catorder(test_db->ast->root->cl_head->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, SEPOL_OK, rc2); } void test_cil_resolve_catorder_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c3", ")", "(", "categoryorder", "(", "c5", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_catorder(test_db->ast->root->cl_head->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_dominance(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "sensitivity", "s1", ")", "(", "sensitivity", "s2", ")", "(", "dominance", "(", "s0", "s1", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC1, &changed, NULL, NULL, NULL); int rc = cil_resolve_dominance(test_db->ast->root->cl_head->next->next->next, args); int rc2 = cil_resolve_dominance(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, SEPOL_OK, rc2); } void test_cil_resolve_dominance_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "sensitivity", "s1", ")", "(", "sensitivity", "s2", ")", "(", "dominance", "(", "s6", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_dominance(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_cat_list(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c1", ")", "(", "category", "c2", ")", "(", "categoryset", "somecats", "(", "c0", "c1", "c2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MLS, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_list *test_cat_list; cil_list_init(&test_cat_list); struct cil_catset *test_catset = (struct cil_catset*)test_db->ast->root->cl_head->next->next->next->data; int rc = cil_resolve_cat_list(test_db->ast->root->cl_head->next->next->next, test_catset->cat_list_str, test_cat_list, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_cat_list_catlistnull_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c1", ")", "(", "category", "c2", ")", "(", "categoryset", "somecats", "(", "c0", "c1", "c2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MLS, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_list *test_cat_list; cil_list_init(&test_cat_list); struct cil_catset *test_catset = (struct cil_catset*)test_db->ast->root->cl_head->next->next->next->data; test_catset->cat_list_str = NULL; int rc = cil_resolve_cat_list(test_db->ast->root->cl_head->next->next->next, test_catset->cat_list_str, test_cat_list, args); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_resolve_cat_list_rescatlistnull_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c1", ")", "(", "category", "c2", ")", "(", "categoryset", "somecats", "(", "c0", "c1", "c2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MLS, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_list *test_cat_list = NULL; struct cil_catset *test_catset = (struct cil_catset*)test_db->ast->root->cl_head->next->next->next->data; int rc = cil_resolve_cat_list(test_db->ast->root->cl_head->next->next->next, test_catset->cat_list_str, test_cat_list, args); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_resolve_cat_list_catrange(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c1", ")", "(", "category", "c2", ")", "(", "categoryorder", "(", "c0", "c1", "c2", ")", ")", "(", "categoryset", "somecats", "(", "c0", "(", "c1", "c2", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC1, &changed, NULL, NULL, NULL); cil_tree_walk(test_db->ast->root, __cil_resolve_ast_node_helper, NULL, NULL, args); __cil_verify_order(test_db->catorder, test_db->ast->root, CIL_CAT); struct cil_list *test_cat_list; cil_list_init(&test_cat_list); struct cil_catset *test_catset = (struct cil_catset*)test_db->ast->root->cl_head->next->next->next->next->data; int rc = cil_resolve_cat_list(test_db->ast->root->cl_head->next->next->next->next, test_catset->cat_list_str, test_cat_list, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_cat_list_catrange_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c1", ")", "(", "category", "c2", ")", "(", "categoryorder", "(", "c0", "c1", "c2", ")", ")", "(", "categoryset", "somecats", "(", "c0", "(", "c2", "c1", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_list *test_cat_list; cil_list_init(&test_cat_list); cil_resolve_catorder(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_MLS; struct cil_catset *test_catset = (struct cil_catset*)test_db->ast->root->cl_head->next->next->next->next->data; int rc = cil_resolve_cat_list(test_db->ast->root->cl_head->next->next->next->next, test_catset->cat_list_str, test_cat_list, args); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_resolve_cat_list_catname_neg(CuTest *tc) { char *line[] = {"(", "category", "c5", ")", "(", "category", "c6", ")", "(", "category", "c7", ")", "(", "categoryorder", "(", "c0", "c1", "c2", ")", ")", "(", "categoryset", "somecats", "(", "c0", "(", "c1", "c2", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_catorder(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_MLS; struct cil_list *test_cat_list; cil_list_init(&test_cat_list); struct cil_catset *test_catset = (struct cil_catset*)test_db->ast->root->cl_head->next->next->next->next->data; int rc = cil_resolve_cat_list(test_db->ast->root->cl_head->next->next->next->next, test_catset->cat_list_str, test_cat_list, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_catset(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c1", ")", "(", "category", "c2", ")", "(", "categoryset", "somecats", "(", "c0", "c1", "c2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MLS, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_catset *test_catset = (struct cil_catset *)test_db->ast->root->cl_head->next->next->next->data; int rc = cil_resolve_catset(test_db->ast->root->cl_head->next->next->next, test_catset, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_catset_catlist_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c1", ")", "(", "category", "c2", ")", "(", "categoryset", "somecats", "(", "c0", "c1", "c2", "c4", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MLS, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_catset *test_catset = (struct cil_catset *)test_db->ast->root->cl_head->next->next->next->data; int rc = cil_resolve_catset(test_db->ast->root->cl_head->next->next->next, test_catset, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_catrange(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c255", ")", "(", "categoryorder", "(", "c0", "c255", ")", ")", "(", "categoryrange", "range", "(", "c0", "c255", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_catorder(test_db->ast->root->cl_head->next->next, args); __cil_verify_order(test_db->catorder, test_db->ast->root, CIL_CAT); args->pass = CIL_PASS_MLS; int rc = cil_resolve_catrange(test_db->ast->root->cl_head->next->next->next, (struct cil_catrange*)test_db->ast->root->cl_head->next->next->next->data, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_catrange_catloworder_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c255", ")", "(", "categoryorder", "(", "c0", "c255", ")", ")", "(", "categoryrange", "range", "(", "c0", "c255", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_catorder(test_db->ast->root->cl_head->next->next, args); __cil_verify_order(test_db->catorder, test_db->ast->root, CIL_CAT); test_db->catorder->head = test_db->catorder->head->next; test_db->catorder->head->next = NULL; args->pass = CIL_PASS_MLS; int rc = cil_resolve_catrange(test_db->ast->root->cl_head->next->next->next, (struct cil_catrange*)test_db->ast->root->cl_head->next->next->next->data, args); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_resolve_catrange_cathighorder_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c255", ")", "(", "categoryorder", "(", "c0", "c255", ")", ")", "(", "categoryrange", "range", "(", "c255", "c0", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_catorder(test_db->ast->root->cl_head->next->next, args); __cil_verify_order(test_db->catorder, test_db->ast->root, CIL_CAT); args->pass = CIL_PASS_MLS; int rc = cil_resolve_catrange(test_db->ast->root->cl_head->next->next->next, (struct cil_catrange*)test_db->ast->root->cl_head->next->next->next->data, args); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_resolve_catrange_cat1_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c255", ")", "(", "categoryorder", "(", "c0", "c255", ")", ")", "(", "categoryrange", "range", "(", "c12", "c255", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_catorder(test_db->ast->root->cl_head->next->next, args); __cil_verify_order(test_db->catorder, test_db->ast->root, CIL_CAT); args->pass = CIL_PASS_MLS; int rc = cil_resolve_catrange(test_db->ast->root->cl_head->next->next->next, (struct cil_catrange*)test_db->ast->root->cl_head->next->next->next->data, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_catrange_cat2_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c255", ")", "(", "categoryorder", "(", "c0", "c255", ")", ")", "(", "categoryrange", "range", "(", "c0", "c23", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_catorder(test_db->ast->root->cl_head->next->next, args); __cil_verify_order(test_db->catorder, test_db->ast->root, CIL_CAT); args->pass = CIL_PASS_MLS; int rc = cil_resolve_catrange(test_db->ast->root->cl_head->next->next->next, (struct cil_catrange*)test_db->ast->root->cl_head->next->next->next->data, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_senscat(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "sensitivity", "s1", ")", "(", "dominance", "(", "s0", "s1", ")", ")", "(", "category", "c0", ")", "(", "category", "c255", ")", "(", "categoryorder", "(", "c0", "c255", ")", ")", "(", "sensitivitycategory", "s1", "(", "c0", "c255", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MLS, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_senscat_catrange_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "sensitivity", "s1", ")", "(", "dominance", "(", "s0", "s1", ")", ")", "(", "category", "c0", ")", "(", "category", "c255", ")", "(", "category", "c500", ")", "(", "categoryorder", "(", "c0", "c255", "c500", ")", ")", "(", "sensitivitycategory", "s1", "(", "c0", "(", "c255", "c5", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_catorder(test_db->ast->root->cl_head->next->next->next->next->next->next, args); args->pass = CIL_PASS_MLS; int rc = cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_resolve_senscat_catsetname(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "sensitivity", "s1", ")", "(", "category", "c0", ")", "(", "category", "c255", ")", "(", "category", "c500", ")", "(", "categoryset", "foo", "(", "c0", "c255", "c500", ")", ")", "(", "categoryorder", "(", "c0", "c255", "c500", ")", ")", "(", "sensitivitycategory", "s1", "foo", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MLS, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_catset *test_catset = (struct cil_catset *)test_db->ast->root->cl_head->next->next->next->next->next->data; cil_resolve_catset(test_db->ast->root->cl_head->next->next->next->next->next, test_catset, args); args->pass = CIL_PASS_MISC2; int rc = cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_senscat_catsetname_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "sensitivity", "s1", ")", "(", "category", "c0", ")", "(", "category", "c255", ")", "(", "category", "c500", ")", "(", "sensitivitycategory", "s1", "foo", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_senscat_sublist(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "sensitivity", "s1", ")", "(", "dominance", "(", "s0", "s1", ")", ")", "(", "category", "c0", ")", "(", "category", "c1", ")", "(", "category", "c255", ")", "(", "categoryorder", "(", "c0", "c1", "c255", ")", ")", "(", "sensitivitycategory", "s1", "(", "c0", "(", "c1", "c255", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC1, &changed, NULL, NULL, NULL); cil_tree_walk(test_db->ast->root, __cil_resolve_ast_node_helper, NULL, NULL, args); __cil_verify_order(test_db->catorder, test_db->ast->root, CIL_CAT); int rc = cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_senscat_missingsens_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "dominance", "(", "s0", "s1", ")", ")", "(", "category", "c0", ")", "(", "category", "c255", ")", "(", "categoryorder", "(", "c0", "c255", ")", ")", "(", "sensitivitycategory", "s1", "(", "c0", "c255", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MLS, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_senscat_category_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "sensitivity", "s1", ")", "(", "dominance", "(", "s0", "s1", ")", ")", "(", "category", "c0", ")", "(", "category", "c255", ")", "(", "categoryorder", "(", "c0", "c255", ")", ")", "(", "sensitivitycategory", "s1", "(", "c5", "c255", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MLS, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_senscat_currrangecat(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "sensitivity", "s1", ")", "(", "dominance", "(", "s0", "s1", ")", ")", "(", "category", "c0", ")", "(", "category", "c1", ")", "(", "category", "c255", ")", "(", "categoryorder", "(", "c0", "c1", "c255", ")", ")", "(", "sensitivitycategory", "s1", "(", "c0", "(", "c1", "c255", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC1, &changed, NULL, NULL, NULL); cil_tree_walk(test_db->ast->root, __cil_resolve_ast_node_helper, NULL, NULL, args); __cil_verify_order(test_db->catorder, test_db->ast->root, CIL_CAT); __cil_verify_order(test_db->dominance, test_db->ast->root, CIL_SENS); args->pass = CIL_PASS_MISC2; int rc = cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_level(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "categoryorder", "(", "c0", ")", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "type", "blah_t", ")", "(", "role", "blah_r", ")", "(", "user", "blah_u", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "sidcontext", "test", "(", "blah_u", "blah_r", "blah_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_MISC3; struct cil_tree_node *level = test_db->ast->root->cl_head->next->next->next->next->next->next->next; int rc = cil_resolve_level(level, (struct cil_level*)level->data, args); int rc2 = cil_resolve_level(level->next, (struct cil_level*)level->next->data, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, SEPOL_OK, rc2); } void test_cil_resolve_level_catlist(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c1", ")", "(", "categoryorder", "(", "c0", "c1", ")", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", "c1", ")", ")", "(", "type", "blah_t", ")", "(", "role", "blah_r", ")", "(", "user", "blah_u", ")", "(", "level", "low", "(", "s0", "(", "c0", "c1", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", "c1", ")", ")", ")", "(", "sidcontext", "test", "(", "blah_u", "blah_r", "blah_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next->next, args); args->pass = CIL_PASS_MISC3; struct cil_tree_node *level = test_db->ast->root->cl_head->next->next->next->next->next->next->next->next; int rc = cil_resolve_level(level, (struct cil_level*)level->data, args); CuAssertIntEquals(tc, SEPOL_OK, rc); rc = cil_resolve_level(level, (struct cil_level*)level->data, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_level_catset(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c1", ")", "(", "category", "c2", ")", "(", "categoryset", "cats", "(", "c0", "c1", "c2", ")", ")", "(", "categoryorder", "(", "c0", "c1", "c2", ")", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "cats", ")", "(", "type", "blah_t", ")", "(", "role", "blah_r", ")", "(", "user", "blah_u", ")", "(", "level", "low", "(", "s0", "cats", ")", ")", "(", "level", "high", "(", "s0", "(", "cats", ")", ")", ")", "(", "sidcontext", "test", "(", "blah_u", "blah_r", "blah_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC1, &changed, NULL, NULL, NULL); struct cil_catset *cs = (struct cil_catset *)test_db->ast->root->cl_head->next->next->next->data; cil_resolve_catorder(test_db->ast->root->cl_head->next->next->next->next, args); args->pass = CIL_PASS_MLS; cil_resolve_catset(test_db->ast->root->cl_head->next->next->next, cs, args); args->pass = CIL_PASS_MISC2; cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next->next->next->next, args); args->pass = CIL_PASS_MISC3; struct cil_tree_node *level = test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next->next; int rc = cil_resolve_level(level, (struct cil_level*)level->data, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_level_catset_name_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c1", ")", "(", "category", "c2", ")", "(", "categoryset", "cats", "(", "c0", "c1", "c2", ")", ")", "(", "categoryorder", "(", "c0", "c1", "c2", ")", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "cats", ")", "(", "type", "blah_t", ")", "(", "role", "blah_r", ")", "(", "user", "blah_u", ")", "(", "level", "low", "(", "s0", "dne", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "sidcontext", "test", "(", "blah_u", "blah_r", "blah_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_MISC3; struct cil_tree_node *level = test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next->next; int rc = cil_resolve_level(level, (struct cil_level*)level->data, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_level_sens_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "categoryorder", "(", "c0", ")", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "type", "blah_t", ")", "(", "role", "blah_r", ")", "(", "user", "blah_u", ")", "(", "level", "low", "(", "s1", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s1", "(", "c0", ")", ")", ")", "(", "sid", "test", "(", "blah_u", "blah_r", "blah_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next, args); struct cil_tree_node *level = test_db->ast->root->cl_head->next->next->next->next->next->next->next; args->pass = CIL_PASS_MISC3; int rc = cil_resolve_level(level, (struct cil_level*)level->data, args); int rc2 = cil_resolve_level(level->next, (struct cil_level*)level->next->data, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, SEPOL_ENOENT, rc2); } void test_cil_resolve_level_cat_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "categoryorder", "(", "c0", ")", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "type", "blah_t", ")", "(", "role", "blah_r", ")", "(", "user", "blah_u", ")", "(", "level", "low", "(", "s0", "(", "c1", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c1", ")", ")", ")", "(", "sid", "test", "(", "blah_u", "blah_r", "blah_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next, args); struct cil_tree_node *level = test_db->ast->root->cl_head->next->next->next->next->next->next->next; args->pass = CIL_PASS_MISC3; int rc = cil_resolve_level(level, (struct cil_level*)level->data, args); int rc2 = cil_resolve_level(level->next, (struct cil_level*)level->next->data, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, SEPOL_ENOENT, rc2); } void test_cil_resolve_level_senscat_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "categoryorder", "(", "c0", ")", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s1", "(", "c0", ")", ")", "(", "type", "blah_t", ")", "(", "role", "blah_r", ")", "(", "user", "blah_u", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "sid", "test", "(", "blah_u", "blah_r", "blah_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next, args); struct cil_tree_node *level = test_db->ast->root->cl_head->next->next->next->next->next->next->next; args->pass = CIL_PASS_MISC3; int rc = cil_resolve_level(level, (struct cil_level*)level->data, args); int rc2 = cil_resolve_level(level->next, (struct cil_level*)level->next->data, args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, SEPOL_ERR, rc2); } void test_cil_resolve_levelrange_namedlvl(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "levelrange", "range", "(", "low", "high", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_resolve_senscat(test_db->ast->root->cl_head->next->next, args); args->pass = CIL_PASS_MISC3; struct cil_levelrange *lvlrange = (struct cil_levelrange *)test_db->ast->root->cl_head->next->next->next->next->next->data; int rc = cil_resolve_levelrange(test_db->ast->root->cl_head->next->next->next->next->next, lvlrange, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_levelrange_namedlvl_low_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "levelrange", "range", "(", "DNE", "high", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_resolve_senscat(test_db->ast->root->cl_head->next->next, args); args->pass = CIL_PASS_MISC3; struct cil_levelrange *lvlrange = (struct cil_levelrange *)test_db->ast->root->cl_head->next->next->next->next->next->data; int rc = cil_resolve_levelrange(test_db->ast->root->cl_head->next->next->next->next->next, lvlrange, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_levelrange_namedlvl_high_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "levelrange", "range", "(", "low", "DNE", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_resolve_senscat(test_db->ast->root->cl_head->next->next, args); args->pass = CIL_PASS_MISC3; struct cil_levelrange *lvlrange = (struct cil_levelrange *)test_db->ast->root->cl_head->next->next->next->next->next->data; int rc = cil_resolve_levelrange(test_db->ast->root->cl_head->next->next->next->next->next, lvlrange, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_levelrange_anonlvl(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "levelrange", "range", "(", "(", "s0", "(", "c0", ")", ")", "(", "s0", "(", "c0", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_resolve_senscat(test_db->ast->root->cl_head->next->next, args); args->pass = CIL_PASS_MISC3; struct cil_levelrange *lvlrange = (struct cil_levelrange *)test_db->ast->root->cl_head->next->next->next->data; int rc = cil_resolve_levelrange(test_db->ast->root->cl_head->next->next->next, lvlrange, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_levelrange_anonlvl_low_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "levelrange", "range", "(", "(", "DNE", "(", "c0", ")", ")", "(", "s0", "(", "c0", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_resolve_senscat(test_db->ast->root->cl_head->next->next, args); struct cil_levelrange *lvlrange = (struct cil_levelrange *)test_db->ast->root->cl_head->next->next->next->data; args->pass = CIL_PASS_MISC3; int rc = cil_resolve_levelrange(test_db->ast->root->cl_head->next->next->next, lvlrange, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_levelrange_anonlvl_high_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "levelrange", "range", "(", "(", "s0", "(", "c0", ")", ")", "(", "dne", "(", "c0", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_resolve_senscat(test_db->ast->root->cl_head->next->next, args); struct cil_levelrange *lvlrange = (struct cil_levelrange *)test_db->ast->root->cl_head->next->next->next->data; args->pass = CIL_PASS_MISC3; int rc = cil_resolve_levelrange(test_db->ast->root->cl_head->next->next->next, lvlrange, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_constrain(CuTest *tc) { char *line[] = {"(", "class", "file", "(", "create", "relabelto", ")", ")", "(", "class", "dir", "(", "create", "relabelto", ")", ")", "(", "sensitivity", "s0", ")", "(", "category", "c1", ")", "(", "level", "l2", "(", "s0", "(", "c1", ")", ")", ")", "(", "level", "h2", "(", "s0", "(", "c1", ")", ")", ")", "(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "l2", "h2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); int rc = cil_resolve_constrain(test_db->ast->root->cl_head->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_constrain_class_neg(CuTest *tc) { char *line[] = {"(", "class", "file", "(", "create", "relabelto", ")", ")", "(", "sensitivity", "s0", ")", "(", "category", "c1", ")", "(", "level", "l2", "(", "s0", "(", "c1", ")", ")", ")", "(", "level", "h2", "(", "s0", "(", "c1", ")", ")", ")", "(", "mlsconstrain", "(", "foo", "(", "create", "relabelto", ")", ")", "(", "eq", "l2", "h2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_constrain(test_db->ast->root->cl_head->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_constrain_perm_neg(CuTest *tc) { char *line[] = {"(", "class", "file", "(", "create", ")", ")", "(", "class", "dir", "(", "create", "relabelto", ")", ")", "(", "sensitivity", "s0", ")", "(", "category", "c1", ")", "(", "level", "l2", "(", "s0", "(", "c1", ")", ")", ")", "(", "level", "h2", "(", "s0", "(", "c1", ")", ")", ")", "(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "l2", "h2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_constrain(test_db->ast->root->cl_head->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_constrain_perm_resolve_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c1", ")", "(", "level", "l2", "(", "s0", "(", "c1", ")", ")", ")", "(", "level", "h2", "(", "s0", "(", "c1", ")", ")", ")", "(", "mlsconstrain", "(", "file", "(", "foo", ")", ")", "(", "eq", "l2", "h2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_constrain(test_db->ast->root->cl_head->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_context(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "user", "system_u", ")", "(", "role", "object_r", ")", "(", "type", "netif_t", ")", "(", "context", "con", "(", "system_u", "object_r", "netif_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_context *test_context = (struct cil_context*)test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->data; int rc = cil_resolve_context(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, test_context, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_context_macro(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "user", "system_u", ")", "(", "role", "object_r", ")", "(", "type", "netif_t", ")", "(", "macro", "mm", "(", "(", "levelrange", "range", ")", ")", "(", "context", "con", "(", "system_u", "object_r", "netif_t", "range", ")", ")", ")", "(", "call", "mm", "(", "(", "(", "s0", "(", "c0", ")", ")", "(", "s0", "(", "c0", ")", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); struct cil_context *test_context = (struct cil_context*)test_db->ast->root->cl_head->next->next->next->next->next->next->next->cl_head->data; int rc2 = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); args->pass = CIL_PASS_CALL2; int rc3 = cil_resolve_call2(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); args->pass = CIL_PASS_MISC2; cil_resolve_senscat(test_db->ast->root->cl_head->next->next, args); args->pass = CIL_PASS_MISC3; args->callstack = test_db->ast->root->cl_head->next->next->next->next->next->next->next->next; int rc = cil_resolve_context(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->cl_head, test_context, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, SEPOL_OK, rc2); CuAssertIntEquals(tc, SEPOL_OK, rc3); } void test_cil_resolve_context_macro_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "user", "system_u", ")", "(", "role", "object_r", ")", "(", "type", "netif_t", ")", "(", "macro", "mm", "(", "(", "levelrange", "range", ")", ")", "(", "context", "con", "(", "system_u", "object_r", "netif_t", "range", ")", ")", ")", "(", "call", "mm", "(", "(", "(", "s0", "(", "c0", ")", ")", "(", "s0", "(", "DNE", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_context *test_context = (struct cil_context*)test_db->ast->root->cl_head->next->next->next->next->next->next->next->cl_head->data; int rc2 = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); args->pass = CIL_PASS_CALL2; int rc3 = cil_resolve_call2(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); args->pass = CIL_PASS_CALL2; cil_resolve_senscat(test_db->ast->root->cl_head->next->next, args); args->pass = CIL_PASS_MISC3; args->callstack = test_db->ast->root->cl_head->next->next->next->next->next->next->next->next; int rc = cil_resolve_context(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->cl_head, test_context, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, SEPOL_OK, rc2); CuAssertIntEquals(tc, SEPOL_OK, rc3); } void test_cil_resolve_context_namedrange(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "levelrange", "range", "(", "low", "high", ")", ")", "(", "user", "system_u", ")", "(", "role", "object_r", ")", "(", "type", "netif_t", ")", "(", "context", "con", "(", "system_u", "object_r", "netif_t", "range", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_context *test_context = (struct cil_context*)test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next->data; int rc = cil_resolve_context(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next, test_context, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_context_namedrange_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "levelrange", "range", "(", "low", "high", ")", ")", "(", "user", "system_u", ")", "(", "role", "object_r", ")", "(", "type", "netif_t", ")", "(", "context", "con", "(", "system_u", "object_r", "netif_t", "DNE", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); struct cil_context *test_context = (struct cil_context*)test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next->data; int rc = cil_resolve_context(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next, test_context, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_context_user_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "role", "object_r", ")", "(", "type", "netif_t", ")", "(", "context", "con", "(", "system_u", "object_r", "netif_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_context *test_context = (struct cil_context*)test_db->ast->root->cl_head->next->next->next->next->next->next->next->data; int rc = cil_resolve_context(test_db->ast->root->cl_head->next->next->next->next->next->next->next, test_context, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_context_role_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "user", "system_u", ")", "(", "type", "netif_t", ")", "(", "context", "con", "(", "system_u", "object_r", "netif_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_context *test_context = (struct cil_context*)test_db->ast->root->cl_head->next->next->next->next->next->next->next->data; int rc = cil_resolve_context(test_db->ast->root->cl_head->next->next->next->next->next->next->next, test_context, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_context_type_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "user", "system_u", ")", "(", "role", "object_r", ")", "(", "context", "con", "(", "system_u", "object_r", "netif_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_context *test_context = (struct cil_context*)test_db->ast->root->cl_head->next->next->next->next->next->next->next->data; int rc = cil_resolve_context(test_db->ast->root->cl_head->next->next->next->next->next->next->next, test_context, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_context_anon_level_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "user", "system_u", ")", "(", "role", "object_r", ")", "(", "type", "netif_t", ")", "(", "context", "con", "(", "system_u", "object_r", "netif_t", "(", "DNE", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_senscat(test_db->ast->root->cl_head->next->next, args); args->pass = CIL_PASS_MISC3; struct cil_context *test_context = (struct cil_context*)test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->data; int rc = cil_resolve_context(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, test_context, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_roletransition(CuTest *tc) { char *line[] = {"(", "role", "foo_r", ")", "(", "type", "bar_t", ")", "(", "role", "foobar_r", ")", "(", "class", "process", "(", "transition", ")", ")", "(", "roletransition", "foo_r", "bar_t", "process", "foobar_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_roletransition(test_db->ast->root->cl_head->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_roletransition_srcdecl_neg(CuTest *tc) { char *line[] = {"(", "type", "bar_t", ")", "(", "role", "foobar_r", ")", "(", "class", "process", "(", "transition", ")", ")", "(", "roletransition", "foo_r", "bar_t", "process", "foobar_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_roletransition(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_roletransition_tgtdecl_neg(CuTest *tc) { char *line[] = {"(", "role", "foo_r", ")", "(", "role", "foobar_r", ")", "(", "class", "process", "(", "transition", ")", ")", "(", "roletransition", "foo_r", "bar_t", "process", "foobar_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_roletransition(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_roletransition_resultdecl_neg(CuTest *tc) { char *line[] = {"(", "role", "foo_r", ")", "(", "type", "bar_t", ")", "(", "class", "process", "(", "transition", ")", ")", "(", "roletransition", "foo_r", "bar_t", "process", "foobar_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_roletransition(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_typeattributeset_type_in_multiple_attrs(CuTest *tc) { char *line[] = {"(", "typeattribute", "attrs", ")", "(", "typeattribute", "attrs2", ")", "(", "type", "type_t", ")", "(", "typeattributeset", "attrs2", "type_t", ")", "(", "typeattributeset", "attrs", "type_t", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); int rc = cil_resolve_typeattributeset(test_db->ast->root->cl_head->next->next->next->next, args); int rc2 = cil_resolve_typeattributeset(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, SEPOL_OK, rc2); } void test_cil_resolve_typeattributeset_multiple_excludes_with_not(CuTest *tc) { char *line[] = {"(", "typeattribute", "attrs", ")", "(", "typeattribute", "attrs2", ")", "(", "type", "type_t", ")", "(", "type", "type_b", ")", "(", "type", "type_a", ")", "(", "typeattributeset", "attrs", "(", "and", "type_a", "type_b", ")", ")", "(", "typeattributeset", "attrs2", "(", "not", "attrs", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_typeattributeset(test_db->ast->root->cl_head->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_typeattributeset_multiple_types_with_and(CuTest *tc) { char *line[] = {"(", "typeattribute", "attrs", ")", "(", "type", "type_t", ")", "(", "type", "type_tt", ")", "(", "typeattributeset", "attrs", "(", "and", "type_t", "type_tt", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_typeattributeset(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_typeattributeset_using_attr(CuTest *tc) { char *line[] = {"(", "typeattribute", "attrs", ")", "(", "typeattribute", "attr_a", ")", "(", "typeattributeset", "attrs", "attr_a", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_typeattributeset(test_db->ast->root->cl_head->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_typeattributeset_name_neg(CuTest *tc) { char *line[] = {"(", "type", "type_t", ")", "(", "typeattributeset", "attrs", "type_t", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_typeattributeset(test_db->ast->root->cl_head->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_typeattributeset_undef_type_neg(CuTest *tc) { char *line[] = {"(", "typeattribute", "attrs", ")", "(", "typeattributeset", "attrs", "type_t", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_typeattributeset(test_db->ast->root->cl_head->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_typeattributeset_not(CuTest *tc) { char *line[] = {"(", "typeattribute", "attrs", ")", "(", "type", "type_t", ")", "(", "type", "t_t", ")", "(", "typeattributeset", "attrs", "(", "not", "t_t", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); int rc = cil_resolve_typeattributeset(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_typeattributeset_undef_type_not_neg(CuTest *tc) { char *line[] = {"(", "typeattribute", "attrs", ")", "(", "type", "type_t", ")", "(", "typeattributeset", "attrs", "(", "not", "t_t", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); int rc = cil_resolve_typeattributeset(test_db->ast->root->cl_head->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_typealias(CuTest *tc) { char *line[] = {"(", "block", "foo", "(", "typealias", ".foo.test", "type_t", ")", "(", "type", "test", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_typealias(test_db->ast->root->cl_head->cl_head, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_typealias_neg(CuTest *tc) { char *line[] = {"(", "block", "foo", "(", "typealias", ".foo", "apache_alias", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_typealias(test_db->ast->root->cl_head->cl_head, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_typebounds(CuTest *tc) { char *line[] = {"(", "type", "type_a", ")", "(", "type", "type_b", ")", "(", "typebounds", "type_a", "type_b", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_typebounds(test_db->ast->root->cl_head->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_typebounds_repeatbind_neg(CuTest *tc) { char *line[] = {"(", "type", "type_a", ")", "(", "type", "type_b", ")", "(", "typebounds", "type_a", "type_b", ")", "(", "typebounds", "type_a", "type_b", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_typebounds(test_db->ast->root->cl_head->next->next, args); int rc2 = cil_resolve_typebounds(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, SEPOL_ERR, rc2); } void test_cil_resolve_typebounds_type1_neg(CuTest *tc) { char *line[] = {"(", "type", "type_b", ")", "(", "typebounds", "type_a", "type_b", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_typebounds(test_db->ast->root->cl_head->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_typebounds_type2_neg(CuTest *tc) { char *line[] = {"(", "type", "type_a", ")", "(", "typebounds", "type_a", "type_b", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_typebounds(test_db->ast->root->cl_head->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_typepermissive(CuTest *tc) { char *line[] = {"(", "type", "type_a", ")", "(", "typepermissive", "type_a", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_typepermissive(test_db->ast->root->cl_head->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_typepermissive_neg(CuTest *tc) { char *line[] = {"(", "type", "type_a", ")", "(", "typepermissive", "type_b", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_typepermissive(test_db->ast->root->cl_head->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_nametypetransition(CuTest *tc) { char *line[] = {"(", "type", "foo", ")", "(", "type", "bar", ")", "(", "class", "file", "(", "read", ")", ")", "(", "type", "foobar", ")", "(", "nametypetransition", "str", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_nametypetransition(test_db->ast->root->cl_head->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_nametypetransition_src_neg(CuTest *tc) { char *line[] = {"(", "type", "foo", ")", "(", "type", "bar", ")", "(", "class", "file", "(", "read", ")", ")", "(", "type", "foobar", ")", "(", "nametypetransition", "str", "wrong", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_nametypetransition(test_db->ast->root->cl_head->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_nametypetransition_tgt_neg(CuTest *tc) { char *line[] = {"(", "type", "foo", ")", "(", "type", "bar", ")", "(", "class", "file", "(", "read", ")", ")", "(", "type", "foobar", ")", "(", "nametypetransition", "str", "foo", "wrong", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_nametypetransition(test_db->ast->root->cl_head->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_nametypetransition_class_neg(CuTest *tc) { char *line[] = {"(", "type", "foo", ")", "(", "type", "bar", ")", "(", "class", "file", "(", "read", ")", ")", "(", "type", "foobar", ")", "(", "nametypetransition", "str", "foo", "bar", "wrong", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_nametypetransition(test_db->ast->root->cl_head->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_nametypetransition_dest_neg(CuTest *tc) { char *line[] = {"(", "type", "foo", ")", "(", "type", "bar", ")", "(", "class", "file", "(", "read", ")", ")", "(", "type", "foobar", ")", "(", "nametypetransition", "str", "foo", "bar", "file", "wrong", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_nametypetransition(test_db->ast->root->cl_head->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_rangetransition(CuTest *tc) { char *line[] = {"(", "class", "class_", "(", "read", ")", ")", "(", "type", "type_a", ")", "(", "type", "type_b", ")", "(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "rangetransition", "type_a", "type_b", "class_", "(", "low", "high", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_rangetransition(test_db->ast->root->cl_head->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_rangetransition_namedrange_anon(CuTest *tc) { char *line[] = {"(", "class", "class_", "(", "read", ")", ")", "(", "type", "type_a", ")", "(", "type", "type_b", ")", "(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "macro", "mm", "(", "(", "levelrange", "l", ")", ")", "(", "rangetransition", "type_a", "type_b", "class_", "l", ")", ")", "(", "call", "mm", "(", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc2 = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next, args); args->pass = CIL_PASS_CALL2; int rc3 = cil_resolve_call2(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next, args); args->pass = CIL_PASS_MISC2; cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next->next->next->next, args); args->pass = CIL_PASS_MISC3; args->callstack = test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next; int rc = cil_resolve_rangetransition(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next->cl_head, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, SEPOL_OK, rc2); CuAssertIntEquals(tc, SEPOL_OK, rc3); } void test_cil_resolve_rangetransition_namedrange_anon_neg(CuTest *tc) { char *line[] = {"(", "class", "class_", "(", "read", ")", ")", "(", "type", "type_a", ")", "(", "type", "type_b", ")", "(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "macro", "mm", "(", "(", "levelrange", "l", ")", ")", "(", "rangetransition", "type_a", "type_b", "class_", "l", ")", ")", "(", "call", "mm", "(", "(", "DNE", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc2 = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next, args); args->pass = CIL_PASS_CALL2; int rc3 = cil_resolve_call2(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next, args); args->pass = CIL_PASS_MISC2; cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next->next->next->next, args); args->pass = CIL_PASS_MISC3; args->callstack = test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next; int rc = cil_resolve_rangetransition(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next->cl_head, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, SEPOL_OK, rc2); CuAssertIntEquals(tc, SEPOL_OK, rc3); } void test_cil_resolve_rangetransition_namedrange(CuTest *tc) { char *line[] = {"(", "class", "class_", "(", "read", ")", ")", "(", "type", "type_a", ")", "(", "type", "type_b", ")", "(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "levelrange", "foo_range", "(", "low", "high", ")", ")", "(", "rangetransition", "type_a", "type_b", "class_", "foo_range", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_rangetransition(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_rangetransition_namedrange_neg(CuTest *tc) { char *line[] = {"(", "class", "class_", "(", "read", ")", ")", "(", "type", "type_a", ")", "(", "type", "type_b", ")", "(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "levelrange", "foo_range", "(", "low", "high", ")", ")", "(", "rangetransition", "type_a", "type_b", "class_", "DNE", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_rangetransition(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_rangetransition_type1_neg(CuTest *tc) { char *line[] = {"(", "class", "class_", "(", "read", ")", ")", "(", "type", "type_a", ")", "(", "type", "type_b", ")", "(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "rangetransition", "type_DNE", "type_b", "class_", "(", "low", "high", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_rangetransition(test_db->ast->root->cl_head->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_rangetransition_type2_neg(CuTest *tc) { char *line[] = {"(", "class", "class_", "(", "read", ")", ")", "(", "type", "type_a", ")", "(", "type", "type_b", ")", "(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "rangetransition", "type_a", "type_DNE", "class_", "(", "low", "high", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_rangetransition(test_db->ast->root->cl_head->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_rangetransition_class_neg(CuTest *tc) { char *line[] = {"(", "class", "class_", "(", "read", ")", ")", "(", "type", "type_a", ")", "(", "type", "type_b", ")", "(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "rangetransition", "type_a", "type_b", "class_DNE", "(", "low", "high", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_rangetransition(test_db->ast->root->cl_head->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_rangetransition_call_level_l_anon(CuTest *tc) { char *line[] = {"(", "class", "class_", "(", "read", ")", ")", "(", "type", "type_a", ")", "(", "type", "type_b", ")", "(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "macro", "mm", "(", "(", "level", "l", ")", ")", "(", "rangetransition", "type_a", "type_b", "class_", "(", "l", "high", ")", ")", ")", "(", "call", "mm", "(", "(", "s0", "(", "c0", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc2 = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); args->pass = CIL_PASS_CALL2; int rc3 = cil_resolve_call2(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); args->pass = CIL_PASS_MISC2; cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next->next->next, args); args->pass = CIL_PASS_MISC3; args->callstack = test_db->ast->root->cl_head->next->next->next->next->next->next->next->next; int rc = cil_resolve_rangetransition(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->cl_head, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, SEPOL_OK, rc2); CuAssertIntEquals(tc, SEPOL_OK, rc3); } void test_cil_resolve_rangetransition_call_level_l_anon_neg(CuTest *tc) { char *line[] = {"(", "class", "class_", "(", "read", ")", ")", "(", "type", "type_a", ")", "(", "type", "type_b", ")", "(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "macro", "mm", "(", "(", "level", "l", ")", ")", "(", "rangetransition", "type_a", "type_b", "class_", "(", "l", "high", ")", ")", ")", "(", "call", "mm", "(", "(", "s0", "(", "c4", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc2 = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); args->pass = CIL_PASS_CALL2; int rc3 = cil_resolve_call2(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); args->pass = CIL_PASS_MISC2; cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next->next->next, args); args->pass = CIL_PASS_MISC3; args->callstack = test_db->ast->root->cl_head->next->next->next->next->next->next->next->next; int rc = cil_resolve_rangetransition(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->cl_head, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, SEPOL_OK, rc2); CuAssertIntEquals(tc, SEPOL_OK, rc3); } void test_cil_resolve_rangetransition_call_level_h_anon(CuTest *tc) { char *line[] = {"(", "class", "class_", "(", "read", ")", ")", "(", "type", "type_a", ")", "(", "type", "type_b", ")", "(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "macro", "mm", "(", "(", "level", "h", ")", ")", "(", "rangetransition", "type_a", "type_b", "class_", "(", "low", "h", ")", ")", ")", "(", "call", "mm", "(", "(", "s0", "(", "c0", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc2 = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); args->pass = CIL_PASS_CALL2; int rc3 = cil_resolve_call2(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); args->pass = CIL_PASS_MISC2; cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next->next->next, args); args->pass = CIL_PASS_MISC3; args->callstack = test_db->ast->root->cl_head->next->next->next->next->next->next->next->next; int rc = cil_resolve_rangetransition(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->cl_head, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, SEPOL_OK, rc2); CuAssertIntEquals(tc, SEPOL_OK, rc3); } void test_cil_resolve_rangetransition_call_level_h_anon_neg(CuTest *tc) { char *line[] = {"(", "class", "class_", "(", "read", ")", ")", "(", "type", "type_a", ")", "(", "type", "type_b", ")", "(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "macro", "mm", "(", "(", "level", "h", ")", ")", "(", "rangetransition", "type_a", "type_b", "class_", "(", "low", "h", ")", ")", ")", "(", "call", "mm", "(", "(", "s0", "(", "c4", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc2 = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); args->pass = CIL_PASS_CALL2; int rc3 = cil_resolve_call2(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); args->pass = CIL_PASS_MISC2; cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next->next->next, args); args->pass = CIL_PASS_MISC3; args->callstack = test_db->ast->root->cl_head->next->next->next->next->next->next->next->next; int rc = cil_resolve_rangetransition(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->cl_head, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, SEPOL_OK, rc2); CuAssertIntEquals(tc, SEPOL_OK, rc3); } void test_cil_resolve_rangetransition_level_l_neg(CuTest *tc) { char *line[] = {"(", "class", "class_", "(", "read", ")", ")", "(", "type", "type_a", ")", "(", "type", "type_b", ")", "(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "rangetransition", "type_a", "type_b", "class_", "(", "low_DNE", "high", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_rangetransition(test_db->ast->root->cl_head->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_rangetransition_level_h_neg(CuTest *tc) { char *line[] = {"(", "class", "class_", "(", "read", ")", ")", "(", "type", "type_a", ")", "(", "type", "type_b", ")", "(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "rangetransition", "type_a", "type_b", "class_", "(", "low", "high_DNE", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_rangetransition(test_db->ast->root->cl_head->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_rangetransition_anon_level_l(CuTest *tc) { char *line[] = {"(", "class", "class_", "(", "read", ")", ")", "(", "type", "type_a", ")", "(", "type", "type_b", ")", "(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "rangetransition", "type_a", "type_b", "class_", "(", "(", "s0", "(", "c0", ")", ")", "high", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next->next->next, args); args->pass = CIL_PASS_MISC3; int rc = cil_resolve_rangetransition(test_db->ast->root->cl_head->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_rangetransition_anon_level_l_neg(CuTest *tc) { char *line[] = {"(", "class", "class_", "(", "read", ")", ")", "(", "type", "type_a", ")", "(", "type", "type_b", ")", "(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "rangetransition", "type_a", "type_b", "class_", "(", "(", "s0", "(", "c_DNE", ")", ")", "high", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next->next->next, args); args->pass = CIL_PASS_MISC3; int rc = cil_resolve_rangetransition(test_db->ast->root->cl_head->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_rangetransition_anon_level_h(CuTest *tc) { char *line[] = {"(", "class", "class_", "(", "read", ")", ")", "(", "type", "type_a", ")", "(", "type", "type_b", ")", "(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "rangetransition", "type_a", "type_b", "class_", "(", "low", "(", "s0", "(", "c0", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next->next->next, args); args->pass = CIL_PASS_MISC3; int rc = cil_resolve_rangetransition(test_db->ast->root->cl_head->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_rangetransition_anon_level_h_neg(CuTest *tc) { char *line[] = {"(", "class", "class_", "(", "read", ")", ")", "(", "type", "type_a", ")", "(", "type", "type_b", ")", "(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "rangetransition", "type_a", "type_b", "class_", "(", "low", "(", "s_DNE", "(", "c0", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next->next->next, args); args->pass = CIL_PASS_MISC3; int rc = cil_resolve_rangetransition(test_db->ast->root->cl_head->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_classcommon(CuTest *tc) { char *line[] = {"(", "class", "file", "(", "read", ")", ")", "(", "common", "file", "(", "write", ")", ")", "(", "classcommon", "file", "file", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_classcommon(test_db->ast->root->cl_head->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_classcommon_no_class_neg(CuTest *tc) { char *line[] = {"(", "class", "foo", "(", "read", ")", ")", "(", "classcommon", "foo", "foo", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_classcommon(test_db->ast->root->cl_head->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_classcommon_no_common_neg(CuTest *tc) { char *line[] = {"(", "common", "foo", "(", "read", ")", ")", "(", "classcommon", "foo", "foo", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_classcommon(test_db->ast->root->cl_head->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_classpermset_named(CuTest *tc) { char *line[] = {"(", "classmap", "files", "(", "read", ")", ")", "(", "class", "char", "(", "read", ")", ")", "(", "classpermissionset", "char_w", "(", "char", "(", "read", ")", ")", ")", "(", "classmapping", "files", "read", "char_w", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_classpermset *cps = test_db->ast->root->cl_head->next->next->data; int rc = cil_resolve_classpermset(test_db->ast->root->cl_head->next->next->next, cps, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_classpermset_named_namedpermlist(CuTest *tc) { char *line[] = {"(", "classmap", "files", "(", "read", ")", ")", "(", "class", "char", "(", "read", ")", ")", "(", "classpermissionset", "char_w", "(", "char", "baz", ")", ")", "(", "permissionset", "baz", "(", "read", ")", ")", "(", "classmapping", "files", "read", "char_w", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_classpermset *cps = test_db->ast->root->cl_head->next->next->data; int rc = cil_resolve_classpermset(test_db->ast->root->cl_head->next->next->next, cps, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_classpermset_named_permlist_neg(CuTest *tc) { char *line[] = {"(", "classmap", "files", "(", "read", ")", ")", "(", "class", "char", "(", "read", ")", ")", "(", "classpermissionset", "char_w", "(", "dne", "(", "read", ")", ")", ")", "(", "classmapping", "files", "read", "char_w", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_classpermset *cps = test_db->ast->root->cl_head->next->next->data; int rc = cil_resolve_classpermset(test_db->ast->root->cl_head->next->next->next, cps, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_classpermset_named_unnamedcps_neg(CuTest *tc) { char *line[] = {"(", "classmap", "files", "(", "read", ")", ")", "(", "class", "char", "(", "read", ")", ")", "(", "classpermissionset", "char_w", "(", "char", "(", "read", ")", ")", ")", "(", "classmapping", "files", "read", "char_w", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_classpermset *cps; cil_classpermset_init(&cps); int rc = cil_resolve_classpermset(test_db->ast->root->cl_head->next->next->next, cps, args); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_resolve_classpermset_anon(CuTest *tc) { char *line[] = {"(", "classmap", "files", "(", "read", ")", ")", "(", "classmapping", "files", "read", "(", "char", "(", "read", ")", ")", ")", "(", "class", "char", "(", "read", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_classpermset *cps = ((struct cil_classmapping*)test_db->ast->root->cl_head->next->data)->classpermsets_str->head->data; int rc = cil_resolve_classpermset(test_db->ast->root->cl_head->next, cps, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_classpermset_anon_namedpermlist(CuTest *tc) { char *line[] = {"(", "classmap", "files", "(", "read", ")", ")", "(", "classmapping", "files", "read", "(", "char", "baz", ")", ")", "(", "permissionset", "baz", "(", "read", ")", ")", "(", "class", "char", "(", "read", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_classpermset *cps = ((struct cil_classmapping*)test_db->ast->root->cl_head->next->data)->classpermsets_str->head->data; int rc = cil_resolve_classpermset(test_db->ast->root->cl_head->next, cps, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_classpermset_anon_permlist_neg(CuTest *tc) { char *line[] = {"(", "classmap", "files", "(", "read", ")", ")", "(", "classmapping", "files", "read", "(", "char", "(", "dne", ")", ")", ")", "(", "class", "char", "(", "read", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_classpermset *cps = ((struct cil_classmapping*)test_db->ast->root->cl_head->next->data)->classpermsets_str->head->data; int rc = cil_resolve_classpermset(test_db->ast->root->cl_head->next, cps, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_avrule(CuTest *tc) { char *line[] = {"(", "class", "bar", "(", "read", "write", "open", ")", ")", "(", "type", "test", ")", "(", "type", "foo", ")", "(", "allow", "test", "foo", "(", "bar", "(", "read", "write", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_avrule(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_avrule_permset(CuTest *tc) { char *line[] = {"(", "class", "bar", "(", "read", "write", "open", ")", ")", "(", "type", "test", ")", "(", "type", "foo", ")", "(", "permissionset", "baz", "(", "open", "write", ")", ")", "(", "allow", "test", "foo", "(", "bar", "baz", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_avrule(test_db->ast->root->cl_head->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_avrule_permset_neg(CuTest *tc) { char *line[] = {"(", "class", "bar", "(", "read", "write", "open", ")", ")", "(", "type", "test", ")", "(", "type", "foo", ")", "(", "permissionset", "baz", "(", "open", "close", ")", ")", "(", "allow", "test", "foo", "(", "bar", "dne", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_avrule(test_db->ast->root->cl_head->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_avrule_permset_permdne_neg(CuTest *tc) { char *line[] = {"(", "class", "bar", "(", "read", "write", "open", ")", ")", "(", "type", "test", ")", "(", "type", "foo", ")", "(", "permissionset", "baz", "(", "open", "dne", ")", ")", "(", "allow", "test", "foo", "(", "bar", "baz", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_avrule(test_db->ast->root->cl_head->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_avrule_firsttype_neg(CuTest *tc) { char *line[] = {"(", "class", "bar", "(", "read", "write", "open", ")", ")", "(", "type", "test", ")", "(", "type", "foo", ")", "(", "allow", "fail1", "foo", "(", "bar", "(", "read", "write", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_avrule(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_avrule_secondtype_neg(CuTest *tc) { char *line[] = {"(", "class", "bar", "(", "read", "write", "open", ")", ")", "(", "type", "test", ")", "(", "type", "foo", ")", "(", "allow", "test", "fail2", "(", "bar", "(", "read", "write", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_avrule(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_avrule_class_neg(CuTest *tc) { char *line[] = {"(", "class", "bar", "(", "read", "write", "open", ")", ")", "(", "type", "test", ")", "(", "type", "foo", ")", "(", "allow", "test", "foo", "(", "fail3", "(", "read", "write", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_avrule(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_avrule_perm_neg(CuTest *tc) { char *line[] = {"(", "class", "bar", "(", "read", "write", "open", ")", ")", "(", "type", "test", ")", "(", "type", "foo", ")", "(", "allow", "test", "foo", "(", "bar", "(", "execute", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_avrule(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_type_rule_transition(CuTest *tc) { char *line[] = {"(", "type", "foo", ")", "(", "type", "bar", ")", "(", "class", "file", "(", "write", ")", ")", "(", "type", "foobar", ")", "(", "typetransition", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_type_rule(test_db->ast->root->cl_head->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_type_rule_transition_srcdecl_neg(CuTest *tc) { char *line[] = {"(", "type", "bar", ")", "(", "class", "file", "(", "write", ")", ")", "(", "type", "foobar", ")", "(", "typetransition", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_type_rule(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_type_rule_transition_tgtdecl_neg(CuTest *tc) { char *line[] = {"(", "type", "foo", ")", "(", "class", "file", "(", "write", ")", ")", "(", "type", "foobar", ")", "(", "typetransition", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_type_rule(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_type_rule_transition_objdecl_neg(CuTest *tc) { char *line[] = {"(", "type", "foo", ")", "(", "type", "bar", ")", "(", "type", "foobar", ")", "(", "typetransition", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_type_rule(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_type_rule_transition_resultdecl_neg(CuTest *tc) { char *line[] = {"(", "type", "foo", ")", "(", "type", "bar", ")", "(", "class", "file", "(", "write", ")", ")", "(", "typetransition", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_type_rule(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_type_rule_change(CuTest *tc) { char *line[] = {"(", "type", "foo", ")", "(", "type", "bar", ")", "(", "class", "file", "(", "write", ")", ")", "(", "type", "foobar", ")", "(", "typechange", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_type_rule(test_db->ast->root->cl_head->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_type_rule_change_srcdecl_neg(CuTest *tc) { char *line[] = {"(", "type", "bar", ")", "(", "class", "file", "(", "write", ")", ")", "(", "type", "foobar", ")", "(", "typechange", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_type_rule(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_type_rule_change_tgtdecl_neg(CuTest *tc) { char *line[] = {"(", "type", "foo", ")", "(", "class", "file", "(", "write", ")", ")", "(", "type", "foobar", ")", "(", "typechange", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_type_rule(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_type_rule_change_objdecl_neg(CuTest *tc) { char *line[] = {"(", "type", "foo", ")", "(", "type", "bar", ")", "(", "type", "foobar", ")", "(", "typechange", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_type_rule(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_type_rule_change_resultdecl_neg(CuTest *tc) { char *line[] = {"(", "type", "foo", ")", "(", "type", "bar", ")", "(", "class", "file", "(", "write", ")", ")", "(", "typechange", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_type_rule(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_type_rule_member(CuTest *tc) { char *line[] = {"(", "type", "foo", ")", "(", "type", "bar", ")", "(", "class", "file", "(", "write", ")", ")", "(", "type", "foobar", ")", "(", "typemember", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_type_rule(test_db->ast->root->cl_head->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_type_rule_member_srcdecl_neg(CuTest *tc) { char *line[] = {"(", "type", "bar", ")", "(", "class", "file", "(", "write", ")", ")", "(", "type", "foobar", ")", "(", "typemember", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_type_rule(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_type_rule_member_tgtdecl_neg(CuTest *tc) { char *line[] = {"(", "type", "foo", ")", "(", "class", "file", "(", "write", ")", ")", "(", "type", "foobar", ")", "(", "typemember", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_type_rule(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_type_rule_member_objdecl_neg(CuTest *tc) { char *line[] = {"(", "type", "foo", ")", "(", "type", "bar", ")", "(", "type", "foobar", ")", "(", "typemember", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_type_rule(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_type_rule_member_resultdecl_neg(CuTest *tc) { char *line[] = {"(", "type", "foo", ")", "(", "type", "bar", ")", "(", "class", "file", "(", "write", ")", ")", "(", "typemember", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_type_rule(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_filecon(CuTest *tc) { char *line[] = {"(", "user", "user_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "context", "con", "(", "user_u", "role_r", "type_t", "(", "low", "high", ")", ")", ")", "(", "filecon", "root", "path", "file", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_filecon(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_filecon_neg(CuTest *tc) { char *line[] = {"(", "user", "user_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "context", "con", "(", "user_u", "role_r", "type_t", "(", "low", "high", ")", ")", ")", "(", "filecon", "root", "path", "file", "conn", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_filecon(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_filecon_anon_context(CuTest *tc) { char *line[] = {"(", "user", "user_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "filecon", "root", "path", "file", "(", "user_u", "role_r", "type_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_filecon(test_db->ast->root->cl_head->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_filecon_anon_context_neg(CuTest *tc) { char *line[] = {"(", "user", "system_u", ")", "(", "type", "type_t", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "filecon", "root", "path", "file", "(", "user_u", "role_r", "type_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); int rc = cil_resolve_filecon(test_db->ast->root->cl_head->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_portcon(CuTest *tc) { char *line[] = {"(", "user", "user_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "context", "con", "(", "user_u", "role_r", "type_t", "(", "low", "high", ")", ")", ")", "(", "portcon", "udp", "25", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_portcon(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_portcon_neg(CuTest *tc) { char *line[] = {"(", "user", "user_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "context", "con", "(", "user_u", "role_r", "type_t", "(", "low", "high", ")", ")", ")", "(", "portcon", "udp", "25", "conn", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_portcon(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_portcon_anon_context(CuTest *tc) { char *line[] = {"(", "user", "user_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "portcon", "udp", "25", "(", "user_u", "role_r", "type_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_portcon(test_db->ast->root->cl_head->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_portcon_anon_context_neg(CuTest *tc) { char *line[] = {"(", "user", "system_u", ")", "(", "type", "type_t", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "portcon", "udp", "25", "(", "user_u", "role_r", "type_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_portcon(test_db->ast->root->cl_head->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_genfscon(CuTest *tc) { char *line[] = {"(", "user", "user_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "context", "con", "(", "user_u", "role_r", "type_t", "(", "low", "high", ")", ")", ")", "(", "genfscon", "type", "path", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_genfscon(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_genfscon_neg(CuTest *tc) { char *line[] = {"(", "user", "user_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "context", "con", "(", "user_u", "role_r", "type_t", "(", "low", "high", ")", ")", ")", "(", "genfscon", "type", "path", "conn", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_genfscon(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_genfscon_anon_context(CuTest *tc) { char *line[] = {"(", "user", "user_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "genfscon", "type", "path", "(", "user_u", "role_r", "type_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_genfscon(test_db->ast->root->cl_head->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_genfscon_anon_context_neg(CuTest *tc) { char *line[] = {"(", "user", "system_u", ")", "(", "type", "type_t", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "genfscon", "type", "path", "(", "user_u", "role_r", "type_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_genfscon(test_db->ast->root->cl_head->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_nodecon_ipv4(CuTest *tc) { char *line[] = {"(", "user", "user_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "context", "con", "(", "user_u", "role_r", "type_t", "(", "low", "high", ")", ")", ")", "(", "ipaddr", "ip", "192.168.1.1", ")", "(", "ipaddr", "netmask", "192.168.1.1", ")", "(", "nodecon", "ip", "netmask", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_nodecon(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_nodecon_ipv6(CuTest *tc) { char *line[] = {"(", "user", "user_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "context", "con", "(", "user_u", "role_r", "type_t", "(", "low", "high", ")", ")", ")", "(", "ipaddr", "ip", "2001:0DB8:AC10:FE01::", ")", "(", "ipaddr", "netmask", "2001:0DB8:AC10:FE01::", ")", "(", "nodecon", "ip", "netmask", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_nodecon(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_nodecon_anonipaddr_ipv4(CuTest *tc) { char *line[] = {"(", "user", "user_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "context", "con", "(", "user_u", "role_r", "type_t", "(", "low", "high", ")", ")", ")", "(", "ipaddr", "netmask", "192.168.1.1", ")", "(", "nodecon", "(", "192.168.1.1", ")", "netmask", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_nodecon(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_nodecon_anonnetmask_ipv4(CuTest *tc) { char *line[] = {"(", "user", "user_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "context", "con", "(", "user_u", "role_r", "type_t", "(", "low", "high", ")", ")", ")", "(", "ipaddr", "ip", "192.168.1.1", ")", "(", "nodecon", "ip", "(", "192.168.1.1", ")", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_nodecon(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_nodecon_anonipaddr_ipv6(CuTest *tc) { char *line[] = {"(", "user", "user_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "context", "con", "(", "user_u", "role_r", "type_t", "(", "low", "high", ")", ")", ")", "(", "ipaddr", "netmask", "2001:0DB8:AC10:FE01::", ")", "(", "nodecon", "(", "2001:0DB8:AC10:FE01::", ")", "netmask", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_nodecon(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_nodecon_anonnetmask_ipv6(CuTest *tc) { char *line[] = {"(", "user", "user_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "context", "con", "(", "user_u", "role_r", "type_t", "(", "low", "high", ")", ")", ")", "(", "ipaddr", "ip", "2001:0DB8:AC10:FE01::", ")", "(", "nodecon", "ip", "(", "2001:0DB8:AC10:FE01::", ")", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_nodecon(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_nodecon_diffipfam_neg(CuTest *tc) { char *line[] = {"(", "user", "user_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "context", "con", "(", "user_u", "role_r", "type_t", "(", "low", "high", ")", ")", ")", "(", "ipaddr", "ip", "2001:0DB8:AC10:FE01::", ")", "(", "nodecon", "ip", "(", "192.168.1.1", ")", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_nodecon(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_resolve_nodecon_context_neg(CuTest *tc) { char *line[] = {"(", "user", "user_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "context", "con", "(", "user_u", "role_r", "type_t", "(", "low", "high", ")", ")", ")", "(", "ipaddr", "ip", "192.168.1.1", ")", "(", "ipaddr", "netmask", "192.168.1.1", ")", "(", "nodecon", "n", "netmask", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_nodecon(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_nodecon_ipaddr_neg(CuTest *tc) { char *line[] = {"(", "user", "user_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "context", "con", "(", "user_u", "role_r", "type_t", "(", "low", "high", ")", ")", ")", "(", "ipaddr", "ip", "192.168.1.1", ")", "(", "ipaddr", "netmask", "192.168.1.1", ")", "(", "nodecon", "ip", "n", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_nodecon(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_nodecon_netmask_neg(CuTest *tc) { char *line[] = {"(", "user", "user_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "context", "con", "(", "user_u", "role_r", "type_t", "(", "low", "high", ")", ")", ")", "(", "ipaddr", "ip", "192.168.1.1", ")", "(", "nodecon", "ip", "ip", "conn", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_nodecon(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_nodecon_anon_context(CuTest *tc) { char *line[] = {"(", "user", "user_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "ipaddr", "ip", "192.168.1.1", ")", "(", "nodecon", "ip", "ip", "(", "user_u", "role_r", "type_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_nodecon(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_nodecon_anon_context_neg(CuTest *tc) { char *line[] = {"(", "user", "system_u", ")", "(", "type", "type_t", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "ipaddr", "ip", "192.168.1.1", ")", "(", "nodecon", "ip", "ip", "(", "user_u", "role_r", "type_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_nodecon(test_db->ast->root->cl_head->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_netifcon(CuTest *tc) { char *line[] = {"(", "context", "if_default", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", "(", "context", "packet_default", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", "(", "netifcon", "eth0", "if_default", "packet_default", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_netifcon(test_db->ast->root->cl_head->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_netifcon_otf_neg(CuTest *tc) { char *line[] = {"(", "context", "if_default", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", "(", "netifcon", "eth0", "if_default", "packet_default", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_netifcon(test_db->ast->root->cl_head->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_netifcon_interface_neg(CuTest *tc) { char *line[] = {"(", "context", "packet_default", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", "(", "netifcon", "eth0", "if_default", "packet_default", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_netifcon(test_db->ast->root->cl_head->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_netifcon_unnamed(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "user", "system_u", ")", "(", "role", "object_r", ")", "(", "type", "netif_t", ")", "(", "netifcon", "eth1", "(", "system_u", "object_r", "netif_t", "(", "low", "high", ")", ")", "(", "system_u", "object_r", "netif_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_netifcon(test_db->ast->root->cl_head->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_netifcon_unnamed_packet_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "role", "object_r", ")", "(", "type", "netif_t", ")", "(", "netifcon", "eth1", "(", "system_u", "object_r", "netif_t", "(", "low", "high", ")", ")", "(", "system_u", "object_r", "netif_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_netifcon(test_db->ast->root->cl_head->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_netifcon_unnamed_otf_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "user", "system_u", ")", "(", "role", "object_r", ")", "(", "type", "netif_t", ")", "(", "netifcon", "eth1", "(", "system_u", "object_r", "netif_t", "(", "low", "high", ")", ")", "(", "system_u", "foo_r", "netif_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_netifcon(test_db->ast->root->cl_head->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_netifcon_sublist_secondlist_missing_neg(CuTest *tc) { char *line[] = {"(", "netifcon", "eth1", "(", "system_u", "object_r", "netif_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_netifcon(test_db->ast->root->cl_head, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_pirqcon(CuTest *tc) { char *line[] = {"(", "context", "con", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", "(", "pirqcon", "1", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_pirqcon(test_db->ast->root->cl_head->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_pirqcon_context_neg(CuTest *tc) { char *line[] = {"(", "context", "con", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", "(", "pirqcon", "1", "dne", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_pirqcon(test_db->ast->root->cl_head->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_pirqcon_anon_context(CuTest *tc) { char *line[] = {"(", "user", "system_u", ")", "(", "role", "object_r", ")", "(", "type", "etc_t", ")", "(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "pirqcon", "1", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next->next->next, args); args->pass = CIL_PASS_MISC3; int rc = cil_resolve_pirqcon(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_pirqcon_anon_context_neg(CuTest *tc) { char *line[] = {"(", "pirqcon", "1", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_pirqcon(test_db->ast->root->cl_head, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_iomemcon(CuTest *tc) { char *line[] = {"(", "context", "con", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", "(", "iomemcon", "1", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_iomemcon(test_db->ast->root->cl_head->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_iomemcon_context_neg(CuTest *tc) { char *line[] = {"(", "context", "con", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", "(", "iomemcon", "1", "dne", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_iomemcon(test_db->ast->root->cl_head->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_iomemcon_anon_context(CuTest *tc) { char *line[] = {"(", "user", "system_u", ")", "(", "role", "object_r", ")", "(", "type", "etc_t", ")", "(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "iomemcon", "1", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next->next->next, args); args->pass = CIL_PASS_MISC3; int rc = cil_resolve_iomemcon(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_iomemcon_anon_context_neg(CuTest *tc) { char *line[] = {"(", "iomemcon", "1", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_iomemcon(test_db->ast->root->cl_head, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_ioportcon(CuTest *tc) { char *line[] = {"(", "context", "con", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", "(", "ioportcon", "1", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_ioportcon(test_db->ast->root->cl_head->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_ioportcon_context_neg(CuTest *tc) { char *line[] = {"(", "context", "con", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", "(", "ioportcon", "1", "dne", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_ioportcon(test_db->ast->root->cl_head->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_ioportcon_anon_context(CuTest *tc) { char *line[] = {"(", "user", "system_u", ")", "(", "role", "object_r", ")", "(", "type", "etc_t", ")", "(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "ioportcon", "1", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next->next->next, args); args->pass = CIL_PASS_MISC3; int rc = cil_resolve_ioportcon(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_ioportcon_anon_context_neg(CuTest *tc) { char *line[] = {"(", "ioportcon", "1", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_ioportcon(test_db->ast->root->cl_head, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_pcidevicecon(CuTest *tc) { char *line[] = {"(", "context", "con", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", "(", "pcidevicecon", "1", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_pcidevicecon(test_db->ast->root->cl_head->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_pcidevicecon_context_neg(CuTest *tc) { char *line[] = {"(", "context", "con", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", "(", "pcidevicecon", "1", "dne", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_pcidevicecon(test_db->ast->root->cl_head->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_pcidevicecon_anon_context(CuTest *tc) { char *line[] = {"(", "user", "system_u", ")", "(", "role", "object_r", ")", "(", "type", "etc_t", ")", "(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "pcidevicecon", "1", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next->next->next, args); args->pass = CIL_PASS_MISC3; int rc = cil_resolve_pcidevicecon(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_pcidevicecon_anon_context_neg(CuTest *tc) { char *line[] = {"(", "pcidevicecon", "1", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_pcidevicecon(test_db->ast->root->cl_head, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_fsuse(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "user", "system_u", ")", "(", "role", "object_r", ")", "(", "type", "netif_t", ")", "(", "context", "con", "(", "system_u", "object_r", "netif_t", "(", "low", "high", ")", ")", ")", "(", "fsuse", "xattr", "ext3", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_fsuse(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_fsuse_nocontext_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "user", "system_u", ")", "(", "role", "object_r", ")", "(", "type", "netif_t", ")", "(", "context", "con", "(", "system_u", "object_r", "netif_t", "(", "low", "high", ")", ")", ")", "(", "fsuse", "xattr", "ext3", "(", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_fsuse(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_resolve_fsuse_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "user", "system_u", ")", "(", "role", "object_r", ")", "(", "type", "netif_t", ")", "(", "context", "con", "(", "system_u", "object_r", "netif_t", "(", "low", "high", ")", ")", ")", "(", "fsuse", "xattr", "ext3", "conn", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_fsuse(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_fsuse_anon(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "user", "system_u", ")", "(", "role", "object_r", ")", "(", "type", "netif_t", ")", "(", "fsuse", "xattr", "ext3", "(", "system_u", "object_r", "netif_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_fsuse(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_fsuse_anon_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "user", "system_u", ")", "(", "role", "object_r", ")", "(", "type", "netif_t", ")", "(", "fsuse", "xattr", "ext3", "(", "system_uu", "object_r", "netif_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_fsuse(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_sidcontext(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "categoryorder", "(", "c0", ")", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "type", "blah_t", ")", "(", "role", "blah_r", ")", "(", "user", "blah_u", ")", "(", "sid", "test", ")", "(", "sidcontext", "test", "(", "blah_u", "blah_r", "blah_t", "(", "(", "s0", "(", "c0", ")", ")", "(", "s0", "(", "c0", ")", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_MISC3; int rc = cil_resolve_sidcontext(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_sidcontext_named_levels(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "categoryorder", "(", "c0", ")", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "type", "blah_t", ")", "(", "role", "blah_r", ")", "(", "user", "blah_u", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "sid", "test", ")", "(", "sidcontext", "test", "(", "blah_u", "blah_r", "blah_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_MISC3; struct cil_tree_node *level = test_db->ast->root->cl_head->next->next->next->next->next->next->next; cil_resolve_level(level, (struct cil_level*)level->data, args); cil_resolve_level(level->next, (struct cil_level*)level->next->data, args); int rc = cil_resolve_sidcontext(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_sidcontext_named_context(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "categoryorder", "(", "c0", ")", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "type", "blah_t", ")", "(", "role", "blah_r", ")", "(", "user", "blah_u", ")", "(", "context", "con", "(", "blah_u", "blah_r", "blah_t", "(", "(", "s0", "(", "c0", ")", ")", "(", "s0", "(", "c0", ")", ")", ")", ")", ")", "(", "sid", "test", ")", "(", "sidcontext", "test", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_MISC3; struct cil_tree_node *context = test_db->ast->root->cl_head->next->next->next->next->next->next->next; cil_resolve_context(context, (struct cil_context*)context->data, args); int rc = cil_resolve_sidcontext(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_sidcontext_named_context_wrongname_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "categoryorder", "(", "c0", ")", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "type", "blah_t", ")", "(", "role", "blah_r", ")", "(", "user", "blah_u", ")", "(", "context", "con", "(", "blah_u", "blah_r", "blah_t", "(", "(", "s0", "(", "c0", ")", ")", "(", "s0", "(", "c0", ")", ")", ")", ")", ")", "(", "sid", "test", ")", "(", "sidcontext", "test", "foo", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_MISC3; struct cil_tree_node *context = test_db->ast->root->cl_head->next->next->next->next->next->next->next; cil_resolve_context(context, (struct cil_context*)context->data, args); int rc = cil_resolve_sidcontext(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_sidcontext_named_context_invaliduser_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "categoryorder", "(", "c0", ")", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "type", "blah_t", ")", "(", "role", "blah_r", ")", "(", "user", "blah_u", ")", "(", "sid", "test", ")", "(", "sidcontext", "test", "(", "", "blah_r", "blah_t", "(", "(", "s0", "(", "c0", ")", ")", "(", "s0", "(", "c0", ")", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next, args); int rc = cil_resolve_sidcontext(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_blockinherit(CuTest *tc) { char *line[] = {"(", "block", "baz", "(", "type", "b", ")", ")", "(", "block", "foo", "(", "type", "a", ")", "(", "blockinherit", "baz", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_blockinherit(test_db->ast->root->cl_head->next->cl_head->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_blockinherit_blockstrdne_neg(CuTest *tc) { char *line[] = {"(", "block", "baz", "(", "type", "b", ")", ")", "(", "block", "foo", "(", "type", "a", ")", "(", "blockinherit", "dne", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_blockinherit(test_db->ast->root->cl_head->next->cl_head->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_in_block(CuTest *tc) { char *line[] = {"(", "class", "char", "(", "read", ")", ")", "(", "block", "foo", "(", "type", "a", ")", ")", "(", "in", "foo", "(", "allow", "test", "baz", "(", "char", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_in(test_db->ast->root->cl_head->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_in_blockstrdne_neg(CuTest *tc) { char *line[] = {"(", "class", "char", "(", "read", ")", ")", "(", "in", "foo", "(", "allow", "test", "baz", "(", "char", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_in(test_db->ast->root->cl_head->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_in_macro(CuTest *tc) { char *line[] = {"(", "class", "char", "(", "read", "write", ")", ")", "(", "macro", "mm", "(", "(", "class", "a", ")", ")", "(", "allow", "foo", "bar", "(", "file", "(", "write", ")", ")", ")", ")", "(", "in", "mm", "(", "allow", "test", "baz", "(", "char", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_in(test_db->ast->root->cl_head->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_in_optional(CuTest *tc) { char *line[] = {"(", "class", "char", "(", "read", "write", ")", ")", "(", "optional", "opt", "(", "allow", "foo", "bar", "(", "baz", "(", "read", ")", ")", ")", ")", "(", "in", "opt", "(", "allow", "test", "baz", "(", "char", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_in(test_db->ast->root->cl_head->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call1_noparam(CuTest *tc) { char *line[] = {"(", "type", "qaz", ")", "(", "class", "file", "(", "read", ")", ")", "(", "macro", "mm", "(", "(", "type", ")", ")", "(", "type", "b", ")", "(", "allow", "qaz", "b", "file", "(", "read", ")", ")", ")", "(", "call", "mm", "(", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call1_type(CuTest *tc) { char *line[] = {"(", "type", "qaz", ")", "(", "class", "file", "(", "read", ")", ")", "(", "macro", "mm", "(", "(", "type", "a", ")", ")", "(", "type", "b", ")", "(", "allow", "a", "b", "(", "file", "(", "read", ")", ")", ")", ")", "(", "call", "mm", "(", "qaz", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call1_role(CuTest *tc) { char *line[] = {"(", "role", "role_r", ")", "(", "class", "file", "(", "read", ")", ")", "(", "macro", "mm", "(", "(", "role", "a", ")", ")", "(", "role", "b", ")", "(", "allow", "a", "b", "(", "file", "(", "read", ")", ")", ")", ")", "(", "call", "mm", "(", "role_r", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call1_user(CuTest *tc) { char *line[] = {"(", "user", "user_u", ")", "(", "class", "file", "(", "read", ")", ")", "(", "macro", "mm", "(", "(", "user", "a", ")", ")", "(", "user", "b", ")", "(", "allow", "a", "b", "(", "file", "(", "read", ")", ")", ")", ")", "(", "call", "mm", "(", "user_u", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call1_sens(CuTest *tc) { char *line[] = {"(", "sensitivity", "sens", ")", "(", "class", "file", "(", "read", ")", ")", "(", "macro", "mm", "(", "(", "sensitivity", "a", ")", ")", "(", "sensitivity", "b", ")", "(", "allow", "a", "b", "(", "file", "(", "read", ")", ")", ")", ")", "(", "call", "mm", "(", "sens", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call1_cat(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "class", "file", "(", "read", ")", ")", "(", "macro", "mm", "(", "(", "category", "a", ")", ")", "(", "category", "b", ")", "(", "allow", "a", "b", "(", "file", "(", "read", ")", ")", ")", ")", "(", "call", "mm", "(", "c0", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call1_catset(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c1", ")", "(", "category", "c2", ")", "(", "categoryset", "somecats", "(", "c0", "c1", "c2", ")", ")", "(", "macro", "mm", "(", "(", "categoryset", "foo", ")", ")", "(", "level", "bar", "(", "s0", "foo", ")", ")", ")", "(", "call", "mm", "(", "somecats", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call1_catset_anon(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c1", ")", "(", "category", "c2", ")", "(", "macro", "mm", "(", "(", "categoryset", "foo", ")", ")", "(", "level", "bar", "(", "s0", "foo", ")", ")", ")", "(", "call", "mm", "(", "(", "c0", "c1", "c2", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call1_catset_anon_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c1", ")", "(", "category", "c2", ")", "(", "macro", "mm", "(", "(", "categoryset", "foo", ")", ")", "(", "level", "bar", "(", "s0", "foo", ")", ")", ")", "(", "call", "mm", "(", "(", "c5", "(", "c2", ")", "c4", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_resolve_call1_level(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "user", "system_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "level", "l", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "h", "(", "s0", "(", "c0", ")", ")", ")", "(", "macro", "mm", "(", "(", "level", "lvl_l", ")", "(", "level", "lvl_h", ")", ")", "(", "context", "foo", "(", "system_u", "role_r", "type_t", "(", "lvl_l", "lvl_h", ")", ")", ")", ")", "(", "call", "mm", "(", "l", "h", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call1_level_anon(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "user", "system_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "level", "l", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "h", "(", "s0", "(", "c0", ")", ")", ")", "(", "macro", "mm", "(", "(", "level", "lvl_l", ")", ")", "(", "context", "foo", "(", "system_u", "role_r", "type_t", "(", "lvl_l", "h", ")", ")", ")", ")", "(", "call", "mm", "(", "(", "s0", "(", "c0", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call1_level_anon_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "user", "system_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "level", "l", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "h", "(", "s0", "(", "c0", ")", ")", ")", "(", "macro", "mm", "(", "(", "level", "lvl_l", ")", ")", "(", "context", "foo", "(", "system_u", "role_r", "type_t", "(", "lvl_l", "h", ")", ")", ")", ")", "(", "call", "mm", "(", "(", "s0", "(", "c0", "(", "c5", ")", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_resolve_call1_ipaddr(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "user", "system_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "level", "lvl_l", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "lvl_h", "(", "s0", "(", "c0", ")", ")", ")", "(", "context", "con", "(", "system_u", "role_r", "type_t", "(", "lvl_l", "lvl_h", ")", ")", ")", "(", "ipaddr", "netmask", "192.168.0.1", ")", "(", "ipaddr", "ip", "192.168.0.1", ")", "(", "macro", "mm", "(", "(", "ipaddr", "addr", ")", ")", "(", "nodecon", "addr", "netmask", "con", ")", ")", "(", "call", "mm", "(", "ip", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call1_ipaddr_anon(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "user", "system_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "level", "lvl_l", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "lvl_h", "(", "s0", "(", "c0", ")", ")", ")", "(", "context", "con", "(", "system_u", "role_r", "type_t", "(", "lvl_l", "lvl_h", ")", ")", ")", "(", "ipaddr", "netmask", "192.168.0.1", ")", "(", "macro", "mm", "(", "(", "ipaddr", "addr", ")", ")", "(", "nodecon", "addr", "netmask", "con", ")", ")", "(", "call", "mm", "(", "(", "192.168.1.1", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call1_ipaddr_anon_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "user", "system_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "level", "lvl_l", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "lvl_h", "(", "s0", "(", "c0", ")", ")", ")", "(", "context", "con", "(", "system_u", "role_r", "type_t", "(", "lvl_l", "lvl_h", ")", ")", ")", "(", "ipaddr", "netmask", "192.168.0.1", ")", "(", "macro", "mm", "(", "(", "ipaddr", "addr", ")", ")", "(", "nodecon", "addr", "netmask", "con", ")", ")", "(", "call", "mm", "(", "(", "192.1.1", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_resolve_call1_class(CuTest *tc) { char *line[] = {"(", "class", "foo", "(", "read", ")", ")", "(", "class", "file", "(", "read", ")", ")", "(", "macro", "mm", "(", "(", "class", "a", ")", ")", "(", "class", "b", "(", "read", ")", ")", "(", "allow", "a", "b", "(", "file", "(", "read", ")", ")", ")", ")", "(", "call", "mm", "(", "foo", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call1_classmap(CuTest *tc) { char *line[] = {"(", "class", "file", "(", "open", ")", ")", "(", "macro", "mm", "(", "(", "classmap", "a", ")", ")", "(", "classmapping", "a", "read", "(", "file", "(", "open", ")", ")", ")", ")", "(", "call", "mm", "(", "(", "read", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_call1(test_db->ast->root->cl_head->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call1_permset(CuTest *tc) { char *line[] = {"(", "permissionset", "foo", "(", "read", "open", ")", ")", "(", "type", "dead", ")", "(", "type", "bar", ")", "(", "class", "baz", "(", "close", "read", "open", ")", ")", "(", "macro", "mm", "(", "(", "permissionset", "a", ")", ")", "(", "allow", "dead", "bar", "(", "baz", "a", ")", ")", ")", "(", "call", "mm", "(", "foo", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call1_permset_anon(CuTest *tc) { char *line[] = {"(", "type", "dead", ")", "(", "type", "bar", ")", "(", "class", "baz", "(", "close", "read", "open", ")", ")", "(", "macro", "mm", "(", "(", "permissionset", "a", ")", ")", "(", "allow", "dead", "bar", "(", "baz", "a", ")", ")", ")", "(", "call", "mm", "(", "(", "read", "open", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call1_classpermset_named(CuTest *tc) { char *line[] = {"(", "classmap", "files", "(", "read", ")", ")", "(", "class", "file", "(", "open", ")", ")", "(", "classpermissionset", "char_w", "(", "file", "(", "open", ")", ")", ")", "(", "macro", "mm", "(", "(", "classpermissionset", "a", ")", ")", "(", "classmapping", "files", "read", "a", ")", ")", "(", "call", "mm", "(", "char_w", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call1_classpermset_anon(CuTest *tc) { char *line[] = {"(", "classmap", "files", "(", "read", ")", ")", "(", "class", "file", "(", "open", ")", ")", "(", "macro", "mm", "(", "(", "classpermissionset", "a", ")", ")", "(", "classmapping", "files", "read", "a", ")", ")", "(", "call", "mm", "(", "(", "file", "(", "open", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call1_classpermset_anon_neg(CuTest *tc) { char *line[] = {"(", "classmap", "files", "(", "read", ")", ")", "(", "class", "file", "(", "open", ")", ")", "(", "macro", "mm", "(", "(", "classpermissionset", "a", ")", ")", "(", "classmapping", "files", "read", "a", ")", ")", "(", "call", "mm", "(", "(", "file", "(", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_resolve_call1_unknown_neg(CuTest *tc) { char *line[] = {"(", "class", "foo", "(", "read", ")", ")", "(", "class", "file", "(", "read", ")", ")", "(", "macro", "mm", "(", "(", "class", "a", ")", ")", "(", "class", "b", "(", "read", ")", ")", "(", "allow", "a", "b", "(", "file", "(", "read", ")", ")", ")", ")", "(", "call", "mm", "(", "foo", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_tree_node *macro_node = NULL; cil_resolve_name(test_db->ast->root->cl_head->next->next->next, ((struct cil_call*)test_db->ast->root->cl_head->next->next->next->data)->macro_str, CIL_SYM_BLOCKS, args, ¯o_node); ((struct cil_call*)test_db->ast->root->cl_head->next->next->next->data)->macro = (struct cil_macro*)macro_node->data; free(((struct cil_call*)test_db->ast->root->cl_head->next->next->next->data)->macro_str); ((struct cil_call*)test_db->ast->root->cl_head->next->next->next->data)->macro_str = NULL; ((struct cil_call*)test_db->ast->root->cl_head->next->next->next->data)->macro->params->head->flavor = CIL_NETIFCON; int rc = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_resolve_call1_unknowncall_neg(CuTest *tc) { char *line[] = {"(", "class", "foo", "(", "read", ")", ")", "(", "class", "file", "(", "read", ")", ")", "(", "macro", "mm", "(", "(", "class", "a", ")", ")", "(", "class", "b", "(", "read", ")", ")", "(", "allow", "a", "b", "(", "file", "(", "read", ")", ")", ")", ")", "(", "call", "m", "(", "foo", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_call1_extraargs_neg(CuTest *tc) { char *line[] = {"(", "class", "foo", "(", "read", ")", ")", "(", "class", "file", "(", "read", ")", ")", "(", "macro", "mm", "(", "(", "class", "a", ")", ")", "(", "class", "b", "(", "read", ")", ")", "(", "allow", "a", "b", "(", "file", "(", "read", ")", ")", ")", ")", "(", "call", "mm", "(", "foo", "bar", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_resolve_call1_copy_dup(CuTest *tc) { char *line[] = {"(", "type", "qaz", ")", "(", "class", "file", "(", "read", ")", ")", "(", "macro", "mm", "(", "(", "type", "a", ")", ")", "(", "type", "qaz", ")", "(", "allow", "a", "b", "(", "file", "(", "read", ")", ")", ")", ")", "(", "call", "mm", "(", "qaz", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call1_missing_arg_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "user", "system_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "level", "l", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "h", "(", "s0", "(", "c0", ")", ")", ")", "(", "macro", "mm", "(", "(", "level", "lvl_l", ")", "(", "level", "lvl_h", ")", ")", "(", "context", "foo", "(", "system_u", "role_r", "type_t", "(", "lvl_l", "lvl_h", ")", ")", ")", ")", "(", "call", "mm", "(", "l", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_resolve_call1_paramsflavor_neg(CuTest *tc) { char *line[] = {"(", "type", "qaz", ")", "(", "class", "file", "(", "read", ")", ")", "(", "macro", "mm", "(", "(", "type", "a", ")", ")", "(", "type", "b", ")", "(", "allow", "a", "b", "(", "file", "(", "read", ")", ")", ")", ")", "(", "call", "mm", "(", "qaz", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_tree_node *macro_node = NULL; struct cil_call *new_call = ((struct cil_call*)test_db->ast->root->cl_head->next->next->next->data); cil_resolve_name(test_db->ast->root->cl_head->next->next->next, new_call->macro_str, CIL_SYM_BLOCKS, args, ¯o_node); new_call->macro = (struct cil_macro*)macro_node->data; struct cil_list_item *item = new_call->macro->params->head; item->flavor = CIL_CONTEXT; int rc = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_resolve_call1_unknownflavor_neg(CuTest *tc) { char *line[] = {"(", "type", "qaz", ")", "(", "class", "file", "(", "read", ")", ")", "(", "macro", "mm", "(", "(", "type", "a", ")", ")", "(", "type", "b", ")", "(", "allow", "a", "b", "(", "file", "(", "read", ")", ")", ")", ")", "(", "call", "mm", "(", "qaz", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_tree_node *macro_node = NULL; struct cil_call *new_call = ((struct cil_call*)test_db->ast->root->cl_head->next->next->next->data); cil_resolve_name(test_db->ast->root->cl_head->next->next->next, new_call->macro_str, CIL_SYM_BLOCKS, args, ¯o_node); new_call->macro = (struct cil_macro*)macro_node->data; struct cil_list_item *item = new_call->macro->params->head; ((struct cil_param*)item->data)->flavor = CIL_CONTEXT; int rc = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_resolve_call2_type(CuTest *tc) { char *line[] = {"(", "type", "qaz", ")", "(", "class", "file", "(", "read", ")", ")", "(", "macro", "mm", "(", "(", "type", "a", ")", ")", "(", "type", "b", ")", "(", "allow", "a", "b", "(", "file", "(", "read", ")", ")", ")", ")", "(", "call", "mm", "(", "qaz", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_call1(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_CALL2; int rc = cil_resolve_call2(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call2_role(CuTest *tc) { char *line[] = {"(", "role", "role_r", ")", "(", "class", "file", "(", "read", ")", ")", "(", "macro", "mm", "(", "(", "role", "a", ")", ")", "(", "role", "b", ")", "(", "allow", "a", "b", "(", "file", "(", "read", ")", ")", ")", ")", "(", "call", "mm", "(", "role_r", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_call1(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_CALL2; int rc = cil_resolve_call2(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call2_user(CuTest *tc) { char *line[] = {"(", "user", "user_u", ")", "(", "class", "file", "(", "read", ")", ")", "(", "macro", "mm", "(", "(", "user", "a", ")", ")", "(", "user", "b", ")", "(", "allow", "a", "b", "(", "file", "(", "read", ")", ")", ")", ")", "(", "call", "mm", "(", "user_u", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_call1(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_CALL2; int rc = cil_resolve_call2(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call2_sens(CuTest *tc) { char *line[] = {"(", "sensitivity", "sens", ")", "(", "class", "file", "(", "read", ")", ")", "(", "macro", "mm", "(", "(", "sensitivity", "a", ")", ")", "(", "sensitivity", "b", ")", "(", "allow", "a", "b", "(", "file", "(", "read", ")", ")", ")", ")", "(", "call", "mm", "(", "sens", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_call1(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_CALL2; int rc = cil_resolve_call2(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call2_cat(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "class", "file", "(", "read", ")", ")", "(", "macro", "mm", "(", "(", "category", "a", ")", ")", "(", "category", "b", ")", "(", "allow", "a", "b", "(", "file", "(", "read", ")", ")", ")", ")", "(", "call", "mm", "(", "c0", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_call1(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_CALL2; int rc = cil_resolve_call2(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call2_catset(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c1", ")", "(", "category", "c2", ")", "(", "categoryset", "somecats", "(", "c0", "c1", "c2", ")", ")", "(", "macro", "mm", "(", "(", "categoryset", "foo", ")", ")", "(", "level", "bar", "(", "s0", "foo", ")", ")", ")", "(", "call", "mm", "(", "somecats", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next->next, args); args->pass = CIL_PASS_CALL2; int rc = cil_resolve_call2(test_db->ast->root->cl_head->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call2_catset_anon(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c1", ")", "(", "category", "c2", ")", "(", "macro", "mm", "(", "(", "categoryset", "foo", ")", ")", "(", "level", "bar", "(", "s0", "foo", ")", ")", ")", "(", "call", "mm", "(", "(", "c0", "c1", "c2", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next, args); args->pass = CIL_PASS_CALL2; int rc = cil_resolve_call2(test_db->ast->root->cl_head->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call2_permset(CuTest *tc) { char *line[] = {"(", "permissionset", "foo", "(", "read", "open", ")", ")", "(", "class", "dead", "(", "close", ")", ")", "(", "class", "bar", "(", "close", ")", ")", "(", "class", "baz", "(", "close", ")", ")", "(", "macro", "mm", "(", "(", "permissionset", "a", ")", ")", "(", "allow", "dead", "bar", "(", "baz", "a", ")", ")", ")", "(", "call", "mm", "(", "foo", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next->next, args); args->pass = CIL_PASS_CALL2; int rc = cil_resolve_call2(test_db->ast->root->cl_head->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call2_permset_anon(CuTest *tc) { char *line[] = {"(", "class", "dead", "(", "close", ")", ")", "(", "class", "bar", "(", "close", ")", ")", "(", "class", "baz", "(", "close", ")", ")", "(", "macro", "mm", "(", "(", "permissionset", "a", ")", ")", "(", "allow", "dead", "bar", "(", "baz", "a", ")", ")", ")", "(", "call", "mm", "(", "(", "read", "open", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next, args); args->pass = CIL_PASS_CALL2; int rc = cil_resolve_call2(test_db->ast->root->cl_head->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call2_classpermset_named(CuTest *tc) { char *line[] = {"(", "classmap", "files", "(", "read", ")", ")", "(", "class", "file", "(", "open", ")", ")", "(", "classpermissionset", "char_w", "(", "file", "(", "open", ")", ")", ")", "(", "macro", "mm", "(", "(", "classpermissionset", "a", ")", ")", "(", "classmapping", "files", "read", "a", ")", ")", "(", "call", "mm", "(", "char_w", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next, args); args->pass = CIL_PASS_CALL2; int rc = cil_resolve_call2(test_db->ast->root->cl_head->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call2_classpermset_anon(CuTest *tc) { char *line[] = {"(", "classmap", "files", "(", "read", ")", ")", "(", "class", "file", "(", "open", ")", ")", "(", "macro", "mm", "(", "(", "classpermissionset", "a", ")", ")", "(", "classmapping", "files", "read", "a", ")", ")", "(", "call", "mm", "(", "(", "file", "(", "open", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_call1(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_CALL2; int rc = cil_resolve_call2(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call2_class(CuTest *tc) { char *line[] = {"(", "class", "foo", "(", "read", ")", ")", "(", "class", "file", "(", "read", ")", ")", "(", "macro", "mm", "(", "(", "class", "a", ")", ")", "(", "class", "b", "(", "read", ")", ")", "(", "allow", "a", "b", "(", "file", "(", "read", ")", ")", ")", ")", "(", "call", "mm", "(", "foo", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_call1(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_CALL2; int rc = cil_resolve_call2(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call2_classmap(CuTest *tc) { char *line[] = {"(", "class", "file", "(", "open", ")", ")", "(", "classmap", "files", "(", "read", ")", ")", "(", "macro", "mm", "(", "(", "classmap", "a", ")", ")", "(", "classmapping", "a", "read", "(", "file", "(", "open", ")", ")", ")", ")", "(", "call", "mm", "(", "files", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc2 = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_CALL2; int rc = cil_resolve_call2(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, SEPOL_OK, rc2); } void test_cil_resolve_call2_level(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "user", "system_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "level", "l", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "h", "(", "s0", "(", "c0", ")", ")", ")", "(", "macro", "mm", "(", "(", "level", "lvl_l", ")", "(", "level", "lvl_h", ")", ")", "(", "context", "foo", "(", "system_u", "role_r", "type_t", "(", "lvl_l", "lvl_h", ")", ")", ")", ")", "(", "call", "mm", "(", "l", "h", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); args->pass = CIL_PASS_CALL2; int rc = cil_resolve_call2(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call2_level_anon(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "user", "system_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "level", "l", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "h", "(", "s0", "(", "c0", ")", ")", ")", "(", "macro", "mm", "(", "(", "level", "lvl_l", ")", ")", "(", "context", "foo", "(", "system_u", "role_r", "type_t", "(", "lvl_l", "h", ")", ")", ")", ")", "(", "call", "mm", "(", "(", "s0", "(", "c0", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); args->pass = CIL_PASS_CALL2; int rc = cil_resolve_call2(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call2_ipaddr(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "user", "system_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "level", "lvl_l", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "lvl_h", "(", "s0", "(", "c0", ")", ")", ")", "(", "context", "con", "(", "system_u", "role_r", "type_t", "(", "lvl_l", "lvl_h", ")", ")", ")", "(", "ipaddr", "netmask", "192.168.0.1", ")", "(", "ipaddr", "ip", "192.168.0.1", ")", "(", "macro", "mm", "(", "(", "ipaddr", "addr", ")", ")", "(", "nodecon", "addr", "netmask", "con", ")", ")", "(", "call", "mm", "(", "ip", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next->next->next, args); args->pass = CIL_PASS_CALL2; int rc = cil_resolve_call2(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call2_ipaddr_anon(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "user", "system_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "level", "lvl_l", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "lvl_h", "(", "s0", "(", "c0", ")", ")", ")", "(", "context", "con", "(", "system_u", "role_r", "type_t", "(", "lvl_l", "lvl_h", ")", ")", ")", "(", "ipaddr", "netmask", "192.168.0.1", ")", "(", "macro", "mm", "(", "(", "ipaddr", "addr", ")", ")", "(", "nodecon", "addr", "netmask", "con", ")", ")", "(", "call", "mm", "(", "(", "192.168.1.1", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next->next, args); args->pass = CIL_PASS_CALL2; int rc = cil_resolve_call2(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_call2_unknown_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "user", "system_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "level", "l", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "h", "(", "s0", "(", "c0", ")", ")", ")", "(", "macro", "mm", "(", "(", "level", "lvl_l", ")", "(", "level", "lvl_h", ")", ")", "(", "context", "foo", "(", "system_u", "role_r", "type_t", "(", "lvl_l", "lvl_h", ")", ")", ")", ")", "(", "call", "mm", "(", "l", "h", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); ((struct cil_args*)((struct cil_list_item *)((struct cil_call *)test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->data)->args->head)->data)->flavor = CIL_SYM_UNKNOWN; args->pass = CIL_PASS_CALL2; int rc = cil_resolve_call2(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_resolve_call2_name_neg(CuTest *tc) { char *line[] = {"(", "class", "foo", "(", "read", ")", ")", "(", "class", "file", "(", "read", ")", ")", "(", "macro", "mm", "(", "(", "class", "a", ")", ")", "(", "class", "b", "(", "read", ")", ")", "(", "allow", "a", "b", "(", "file", "(", "read", ")", ")", ")", ")", "(", "call", "mm", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_call1(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_CALL2; int rc = cil_resolve_call2(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_resolve_name_call_args(CuTest *tc) { char *line[] = {"(", "type", "qaz", ")", "(", "class", "file", "(", "read", ")", ")", "(", "macro", "mm", "(", "(", "type", "a", ")", ")", "(", "type", "b", ")", "(", "allow", "a", "b", "(", "file", "(", "read", ")", ")", ")", ")", "(", "call", "mm", "(", "qaz", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_tree_node *test_node; cil_tree_node_init(&test_node); cil_resolve_call1(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_CALL2; cil_resolve_call2(test_db->ast->root->cl_head->next->next->next, args); int rc = cil_resolve_name_call_args((struct cil_call *)test_db->ast->root->cl_head->next->next->next->data, "a", CIL_SYM_TYPES, &test_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_name_call_args_multipleparams(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "user", "system_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "level", "l", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "h", "(", "s0", "(", "c0", ")", ")", ")", "(", "macro", "mm", "(", "(", "level", "lvl_l", ")", "(", "level", "lvl_h", ")", ")", "(", "context", "foo", "(", "system_u", "role_r", "type_t", "(", "lvl_l", "lvl_h", ")", ")", ")", ")", "(", "call", "mm", "(", "l", "h", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_tree_node *test_node; cil_tree_node_init(&test_node); cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); args->pass = CIL_PASS_CALL2; cil_resolve_call2(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, args); int rc = cil_resolve_name_call_args((struct cil_call *)test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->data, "lvl_h", CIL_SYM_LEVELS, &test_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_name_call_args_diffflavor(CuTest *tc) { char *line[] = {"(", "type", "qaz", ")", "(", "class", "file", "(", "read", ")", ")", "(", "macro", "mm", "(", "(", "type", "a", ")", ")", "(", "type", "b", ")", "(", "allow", "a", "b", "(", "file", "(", "read", ")", ")", ")", ")", "(", "call", "mm", "(", "qaz", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_tree_node *test_node; cil_tree_node_init(&test_node); cil_resolve_call1(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_CALL2; cil_resolve_call2(test_db->ast->root->cl_head->next->next->next, args); int rc = cil_resolve_name_call_args((struct cil_call *)test_db->ast->root->cl_head->next->next->next->data, "qaz", CIL_LEVEL, &test_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_resolve_name_call_args_callnull_neg(CuTest *tc) { char *line[] = {"(", "type", "qaz", ")", "(", "class", "file", "(", "read", ")", ")", "(", "macro", "mm", "(", "(", "type", "a", ")", ")", "(", "type", "b", ")", "(", "allow", "a", "b", "(", "file", "(", "read", ")", ")", ")", ")", "(", "call", "mm", "(", "qaz", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); struct cil_tree_node *test_node; cil_tree_node_init(&test_node); cil_resolve_call1(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_CALL2; cil_resolve_call2(test_db->ast->root->cl_head->next->next->next, args); int rc = cil_resolve_name_call_args(NULL, "qaz", CIL_LEVEL, &test_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_resolve_name_call_args_namenull_neg(CuTest *tc) { char *line[] = {"(", "type", "qaz", ")", "(", "class", "file", "(", "read", ")", ")", "(", "macro", "mm", "(", "(", "type", "a", ")", ")", "(", "type", "b", ")", "(", "allow", "a", "b", "(", "file", "(", "read", ")", ")", ")", ")", "(", "call", "mm", "(", "qaz", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_tree_node *test_node; cil_tree_node_init(&test_node); cil_resolve_call1(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_CALL2; cil_resolve_call2(test_db->ast->root->cl_head->next->next->next, args); int rc = cil_resolve_name_call_args((struct cil_call *)test_db->ast->root->cl_head->next->next->next->data, NULL, CIL_LEVEL, &test_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_resolve_name_call_args_callargsnull_neg(CuTest *tc) { char *line[] = {"(", "type", "qaz", ")", "(", "class", "file", "(", "read", ")", ")", "(", "macro", "mm", "(", "(", "type", "a", ")", ")", "(", "type", "b", ")", "(", "allow", "a", "b", "(", "file", "(", "read", ")", ")", ")", ")", "(", "call", "mm", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_tree_node *test_node; cil_tree_node_init(&test_node); cil_resolve_call1(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_CALL2; cil_resolve_call2(test_db->ast->root->cl_head->next->next->next, args); int rc = cil_resolve_name_call_args((struct cil_call *)test_db->ast->root->cl_head->next->next->next->data, "qas", CIL_LEVEL, &test_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_resolve_name_call_args_name_neg(CuTest *tc) { char *line[] = {"(", "type", "qaz", ")", "(", "class", "file", "(", "read", ")", ")", "(", "macro", "mm", "(", "(", "type", "a", ")", ")", "(", "type", "b", ")", "(", "allow", "a", "b", "(", "file", "(", "read", ")", ")", ")", ")", "(", "call", "mm", "(", "baz", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_tree_node *test_node = NULL; //cil_tree_node_init(&test_node); cil_resolve_call1(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_CALL2; cil_resolve_call2(test_db->ast->root->cl_head->next->next->next, args); int rc = cil_resolve_name_call_args((struct cil_call *)test_db->ast->root->cl_head->next->next->next->data, "qas", CIL_TYPE, &test_node); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_resolve_expr_stack_bools(CuTest *tc) { char *line[] = {"(", "boolean", "foo", "true", ")", "(", "boolean", "bar", "false", ")", "(", "class", "baz", "(", "read", ")", ")", "(", "booleanif", "(", "and", "foo", "bar", ")", "(", "allow", "foo", "bar", "(", "baz", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_booleanif *bif = (struct cil_booleanif*)test_db->ast->root->cl_head->next->next->next->data; int rc = cil_resolve_expr_stack(bif->expr_stack, test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_expr_stack_tunables(CuTest *tc) { char *line[] = {"(", "tunable", "foo", "true", ")", "(", "tunable", "bar", "false", ")", "(", "class", "baz", "(", "read", ")", ")", "(", "tunableif", "(", "and", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "(", "baz", "(", "read", ")", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_TIF, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_tunableif *tif = (struct cil_tunableif*)test_db->ast->root->cl_head->next->next->next->data; int rc = cil_resolve_expr_stack(tif->expr_stack, test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_expr_stack_type(CuTest *tc) { char *line[] = {"(", "class", "file", "(", "create", "relabelto", ")", ")", "(", "class", "dir", "(", "create", "relabelto", ")", ")", "(", "type", "t1", ")", "(", "type", "type_t", ")", "(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "t1", "type_t", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_constrain *cons = (struct cil_constrain*)test_db->ast->root->cl_head->next->next->next->next->data; int rc = cil_resolve_expr_stack(cons->expr, test_db->ast->root->cl_head->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_expr_stack_role(CuTest *tc) { char *line[] = {"(", "class", "file", "(", "create", "relabelto", ")", ")", "(", "class", "dir", "(", "create", "relabelto", ")", ")", "(", "role", "r1", ")", "(", "role", "role_r", ")", "(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "r1", "role_r", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_constrain *cons = (struct cil_constrain*)test_db->ast->root->cl_head->next->next->next->next->data; int rc = cil_resolve_expr_stack(cons->expr, test_db->ast->root->cl_head->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_expr_stack_user(CuTest *tc) { char *line[] = {"(", "class", "file", "(", "create", "relabelto", ")", ")", "(", "class", "dir", "(", "create", "relabelto", ")", ")", "(", "user", "u1", ")", "(", "user", "user_u", ")", "(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "u1", "user_u", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_constrain *cons = (struct cil_constrain*)test_db->ast->root->cl_head->next->next->next->next->data; int rc = cil_resolve_expr_stack(cons->expr, test_db->ast->root->cl_head->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_expr_stack_neg(CuTest *tc) { char *line[] = {"(", "boolean", "foo", "true", ")", "(", "boolean", "bar", "false", ")", "(", "class", "baz", "(", "read", ")", ")", "(", "booleanif", "(", "and", "beef", "baf", ")", "(", "true", "(", "allow", "foo", "bar", "(", "baz", "(", "read", ")", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_booleanif *bif = (struct cil_booleanif*)test_db->ast->root->cl_head->next->next->next->data; int rc = cil_resolve_expr_stack(bif->expr_stack,test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_expr_stack_emptystr_neg(CuTest *tc) { char *line[] = {"(", "boolean", "foo", "true", ")", "(", "boolean", "bar", "false", ")", "(", "class", "baz", "(", "read", ")", ")", "(", "booleanif", "(", "and", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "(", "baz", "(", "read", ")", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_booleanif *bif = (struct cil_booleanif*)test_db->ast->root->cl_head->next->next->next->data; ((struct cil_conditional*)bif->expr_stack->head->data)->str = NULL; int rc = cil_resolve_expr_stack(bif->expr_stack,test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_resolve_boolif(CuTest *tc) { char *line[] = {"(", "boolean", "foo", "true", ")", "(", "boolean", "bar", "false", ")", "(", "class", "baz", "(", "read", ")", ")", "(", "booleanif", "(", "and", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "(", "baz", "(", "read", ")", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_boolif(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_boolif_neg(CuTest *tc) { char *line[] = {"(", "boolean", "foo", "true", ")", "(", "boolean", "bar", "false", ")", "(", "class", "baz", "(", "read", ")", ")", "(", "booleanif", "(", "and", "dne", "N/A", ")", "(", "true", "(", "allow", "foo", "bar", "(", "baz", "(", "read", ")", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_boolif(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_evaluate_expr_stack_and(CuTest *tc) { char *line[] = {"(", "tunable", "foo", "true", ")", "(", "tunable", "bar", "false", ")", "(", "class", "baz", "(", "read", ")", ")", "(", "tunableif", "(", "and", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "(", "baz", "(", "read", ")", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint16_t result = CIL_FALSE; uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_TIF, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_tunableif *tif = (struct cil_tunableif*)test_db->ast->root->cl_head->next->next->next->data; cil_resolve_expr_stack(tif->expr_stack, test_db->ast->root->cl_head->next->next->next, args); int rc = cil_evaluate_expr_stack(tif->expr_stack, &result); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_evaluate_expr_stack_not(CuTest *tc) { char *line[] = {"(", "tunable", "foo", "true", ")", "(", "tunable", "bar", "false", ")", "(", "class", "baz", "(", "read", ")", ")", "(", "tunableif", "(", "not", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "(", "baz", "(", "read", ")", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint16_t result = CIL_FALSE; uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_TIF, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_tunableif *tif = (struct cil_tunableif*)test_db->ast->root->cl_head->next->next->next->data; cil_resolve_expr_stack(tif->expr_stack, test_db->ast->root->cl_head->next->next->next, args); int rc = cil_evaluate_expr_stack(tif->expr_stack, &result); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_evaluate_expr_stack_or(CuTest *tc) { char *line[] = {"(", "tunable", "foo", "true", ")", "(", "tunable", "bar", "false", ")", "(", "class", "baz", "(", "read", ")", ")", "(", "tunableif", "(", "or", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "(", "baz", "(", "read", ")", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint16_t result = CIL_FALSE; uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_TIF, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_tunableif *tif = (struct cil_tunableif*)test_db->ast->root->cl_head->next->next->next->data; cil_resolve_expr_stack(tif->expr_stack, test_db->ast->root->cl_head->next->next->next, args); int rc = cil_evaluate_expr_stack(tif->expr_stack, &result); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_evaluate_expr_stack_xor(CuTest *tc) { char *line[] = {"(", "tunable", "foo", "true", ")", "(", "tunable", "bar", "false", ")", "(", "class", "baz", "(", "read", ")", ")", "(", "tunableif", "(", "xor", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "(", "baz", "(", "read", ")", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint16_t result = CIL_FALSE; uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_TIF, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_tunableif *tif = (struct cil_tunableif*)test_db->ast->root->cl_head->next->next->next->data; cil_resolve_expr_stack(tif->expr_stack, test_db->ast->root->cl_head->next->next->next, args); int rc = cil_evaluate_expr_stack(tif->expr_stack, &result); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_evaluate_expr_stack_eq(CuTest *tc) { char *line[] = {"(", "tunable", "foo", "true", ")", "(", "tunable", "bar", "false", ")", "(", "class", "baz", "(", "read", ")", ")", "(", "tunableif", "(", "eq", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "(", "baz", "(", "read", ")", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint16_t result = CIL_FALSE; uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_TIF, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_tunableif *tif = (struct cil_tunableif*)test_db->ast->root->cl_head->next->next->next->data; cil_resolve_expr_stack(tif->expr_stack, test_db->ast->root->cl_head->next->next->next, args); int rc = cil_evaluate_expr_stack(tif->expr_stack, &result); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_evaluate_expr_stack_neq(CuTest *tc) { char *line[] = {"(", "tunable", "foo", "true", ")", "(", "tunable", "bar", "false", ")", "(", "class", "baz", "(", "read", ")", ")", "(", "tunableif", "(", "neq", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "(", "baz", "(", "read", ")", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint16_t result = CIL_FALSE; uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_TIF, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_tunableif *tif = (struct cil_tunableif*)test_db->ast->root->cl_head->next->next->next->data; cil_resolve_expr_stack(tif->expr_stack, test_db->ast->root->cl_head->next->next->next, args); int rc = cil_evaluate_expr_stack(tif->expr_stack, &result); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_evaluate_expr_stack_oper1(CuTest *tc) { char *line[] = {"(", "tunable", "foo", "true", ")", "(", "tunable", "bar", "false", ")", "(", "tunable", "baz", "false", ")", "(", "class", "baz", "(", "read", ")", ")", "(", "tunableif", "(", "and", "(", "or", "foo", "bar", ")", "baz", ")", "(", "true", "(", "allow", "foo", "bar", "(", "jaz", "(", "read", ")", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint16_t result = CIL_FALSE; uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_TIF, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_tunableif *tif = (struct cil_tunableif*)test_db->ast->root->cl_head->next->next->next->next->data; cil_resolve_expr_stack(tif->expr_stack, test_db->ast->root->cl_head->next->next->next->next, args); int rc = cil_evaluate_expr_stack(tif->expr_stack, &result); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_evaluate_expr_stack_oper2(CuTest *tc) { char *line[] = {"(", "tunable", "foo", "true", ")", "(", "tunable", "bar", "false", ")", "(", "tunable", "baz", "false", ")", "(", "class", "baz", "(", "read", ")", ")", "(", "tunableif", "(", "and", "baz", "(", "or", "foo", "bar", ")", ")", "(", "true", "(", "allow", "foo", "bar", "(", "jaz", "(", "read", ")", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint16_t result = CIL_FALSE; uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_TIF, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_tunableif *tif = (struct cil_tunableif*)test_db->ast->root->cl_head->next->next->next->next->data; cil_resolve_expr_stack(tif->expr_stack, test_db->ast->root->cl_head->next->next->next->next, args); int rc = cil_evaluate_expr_stack(tif->expr_stack, &result); CuAssertIntEquals(tc, SEPOL_OK, rc); } /* void test_cil_evaluate_expr_stack_neg(CuTest *tc) { char *line[] = {"(", "tunable", "foo", "true", ")", "(", "tunable", "bar", "false", ")", "(", "class", "baz", "(", "read", ")", ")", "(", "tunableif", "(", "neq", "foo", "bar", ")", "(", "allow", "foo", "bar", "(", "baz", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint16_t result = CIL_FALSE; cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_tree_node *test_node; cil_tree_node_init(&test_node); struct cil_conditional *new_cond; cil_conditional_init(&new_cond); new_cond->flavor = CIL_COND; char *baz = "baz"; new_cond->str = baz; new_cond->flavor = CIL_TUNABLE; struct cil_tunableif *tif = test_db->ast->root->cl_head->next->next->next->next->data; test_node->data = new_cond; test_node->cl_head = tif->expr_stack; tif->expr_stack->parent = test_node; cil_resolve_expr_stack(test_db, tif->expr_stack, test_db->ast->root->cl_head->next->next->next, NULL); int rc = cil_evaluate_expr_stack(tif->expr_stack, &result); CuAssertIntEquals(tc, SEPOL_ERR, rc); } */ void test_cil_resolve_tunif_false(CuTest *tc) { char *line[] = {"(", "tunable", "foo", "true", ")", "(", "tunable", "bar", "false", ")", "(", "class", "baz", "(", "read", ")", ")", "(", "tunableif", "(", "and", "foo", "bar", ")", "(", "false", "(", "allow", "foo", "bar", "(", "baz", "(", "read", ")", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_TIF, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_tunif(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_tunif_true(CuTest *tc) { char *line[] = {"(", "tunable", "foo", "true", ")", "(", "tunable", "bar", "true", ")", "(", "class", "baz", "(", "read", ")", ")", "(", "tunableif", "(", "and", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "(", "baz", "(", "read", ")", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_TIF, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_tunif(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_tunif_resolveexpr_neg(CuTest *tc) { char *line[] = {"(", "tunable", "foo", "true", ")", "(", "tunable", "bar", "false", ")", "(", "class", "baz", "(", "read", ")", ")", "(", "tunableif", "(", "and", "dne", "N/A", ")", "(", "true", "(", "allow", "foo", "bar", "(", "baz", "(", "read", ")", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_TIF, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_tunif(test_db->ast->root->cl_head->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } /* void test_cil_resolve_tunif_evaluateexpr_neg(CuTest *tc) { char *line[] = {"(", "tunable", "foo", "true", ")", "(", "tunable", "bar", "false", ")", "(", "class", "baz", "(", "read", ")", ")", "(", "tunableif", "(", "and", "foo", "bar", ")", "(", "allow", "foo", "bar", "(", "baz", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); struct cil_tree_node *test_node; cil_tree_node_init(&test_node); struct cil_conditional *new_cond; cil_conditional_init(&new_cond); new_cond->flavor = CIL_COND; char *baz = "baz"; new_cond->str = baz; new_cond->flavor = CIL_TUNABLE; struct tunableif *tif = test_db->ast->root->cl_head->next->next->next->data; test_node->data = new_cond; test_node->cl_head = tif->expr_stack; tif->expr_stack->parent = test_node; int rc = cil_resolve_tunif(test_db, test_db->ast->root->cl_head->next->next->next, NULL); CuAssertIntEquals(tc, SEPOL_ERR, rc); } */ void test_cil_resolve_userbounds(CuTest *tc) { char *line[] = {"(", "user", "user1", ")", "(", "user", "user2", ")", "(", "userbounds", "user1", "user2", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_userbounds(test_db->ast->root->cl_head->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_userbounds_exists_neg(CuTest *tc) { char *line[] = {"(", "user", "user1", ")", "(", "user", "user2", ")", "(", "userbounds", "user1", "user2", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_userbounds(test_db->ast->root->cl_head->next->next, args); int rc = cil_resolve_userbounds(test_db->ast->root->cl_head->next->next, args); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_resolve_userbounds_user1_neg(CuTest *tc) { char *line[] = {"(", "user", "user1", ")", "(", "user", "user2", ")", "(", "userbounds", "user_DNE", "user2", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_userbounds(test_db->ast->root->cl_head->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_userbounds_user2_neg(CuTest *tc) { char *line[] = {"(", "user", "user1", ")", "(", "user", "user2", ")", "(", "userbounds", "user1", "user_DNE", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_userbounds(test_db->ast->root->cl_head->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_roletype(CuTest *tc) { char *line[] = {"(", "role", "admin_r", ")", "(", "type", "admin_t", ")", "(", "roletype", "admin_r", "admin_t", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_roletype(test_db->ast->root->cl_head->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_roletype_type_neg(CuTest *tc) { char *line[] = {"(", "role", "admin_r", ")", "(", "roletype", "admin_r", "admin_t", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_roletype(test_db->ast->root->cl_head->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_roletype_role_neg(CuTest *tc) { char *line[] = {"(", "type", "admin_t", ")", "(", "roletype", "admin_r", "admin_t", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_roletype(test_db->ast->root->cl_head->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_userrole(CuTest *tc) { char *line[] = {"(", "role", "staff_r", ")", "(", "user", "staff_u", ")", "(", "userrole", "staff_u", "staff_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); int rc = cil_resolve_userrole(test_db->ast->root->cl_head->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_userrole_user_neg(CuTest *tc) { char *line[] = {"(", "role", "staff_r", ")", "(", "userrole", "staff_u", "staff_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_userrole(test_db->ast->root->cl_head->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_userrole_role_neg(CuTest *tc) { char *line[] = {"(", "user", "staff_u", ")", "(", "userrole", "staff_u", "staff_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = cil_resolve_userrole(test_db->ast->root->cl_head->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_userlevel(CuTest *tc) { char *line[] = {"(", "user", "foo_u", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "userlevel", "foo_u", "low", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_MISC3; int rc = cil_resolve_userlevel(test_db->ast->root->cl_head->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_userlevel_macro(CuTest *tc) { char *line[] = {"(", "user", "foo_u", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "macro", "mm", "(", "(", "level", "l", ")", ")", "(", "userlevel", "foo_u", "l", ")", ")", "(", "call", "mm", "(", "(", "s0", "(", "c0", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); args->pass = CIL_PASS_CALL1; int rc2 = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next->next, args); args->pass = CIL_PASS_CALL2; int rc3 = cil_resolve_call2(test_db->ast->root->cl_head->next->next->next->next->next, args); args->pass = CIL_PASS_MISC2; cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_MISC3; args->callstack = test_db->ast->root->cl_head->next->next->next->next->next; int rc = cil_resolve_userlevel(test_db->ast->root->cl_head->next->next->next->next->next->cl_head, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, SEPOL_OK, rc2); CuAssertIntEquals(tc, SEPOL_OK, rc3); } void test_cil_resolve_userlevel_macro_neg(CuTest *tc) { char *line[] = {"(", "user", "foo_u", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "macro", "mm", "(", "(", "level", "l", ")", ")", "(", "userlevel", "foo_u", "l", ")", ")", "(", "call", "mm", "(", "(", "DNE", "(", "c0", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc2 = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next->next, args); args->pass = CIL_PASS_CALL2; int rc3 = cil_resolve_call2(test_db->ast->root->cl_head->next->next->next->next->next, args); args->pass = CIL_PASS_MISC2; cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_MISC3; args->callstack = test_db->ast->root->cl_head->next->next->next->next->next; int rc = cil_resolve_userlevel(test_db->ast->root->cl_head->next->next->next->next->next->cl_head, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, SEPOL_OK, rc2); CuAssertIntEquals(tc, SEPOL_OK, rc3); } void test_cil_resolve_userlevel_level_anon(CuTest *tc) { char *line[] = {"(", "user", "foo_u", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "userlevel", "foo_u", "(", "s0", "(", "c0", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_MISC3; int rc = cil_resolve_userlevel(test_db->ast->root->cl_head->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_userlevel_level_anon_neg(CuTest *tc) { char *line[] = {"(", "user", "foo_u", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "userlevel", "foo_u", "(", "s0", "(", "DNE", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_MISC3; int rc = cil_resolve_userlevel(test_db->ast->root->cl_head->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_userlevel_user_neg(CuTest *tc) { char *line[] = {"(", "user", "foo_u", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "userlevel", "DNE", "low", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_MISC3; int rc = cil_resolve_userlevel(test_db->ast->root->cl_head->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_userlevel_level_neg(CuTest *tc) { char *line[] = {"(", "user", "foo_u", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "userlevel", "foo_u", "DNE", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_MISC3; int rc = cil_resolve_userlevel(test_db->ast->root->cl_head->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_userrange(CuTest *tc) { char *line[] = {"(", "user", "foo_u", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "levelrange", "range", "(", "(", "s0", "(", "c0", ")", ")", "(", "s0", "(", "c0", ")", ")", ")", ")", "(", "userrange", "foo_u", "range", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next, args); int rc = cil_resolve_userrange(test_db->ast->root->cl_head->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_userrange_macro(CuTest *tc) { char *line[] = {"(", "user", "foo_u", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "macro", "mm", "(", "(", "levelrange", "range", ")", ")", "(", "userrange", "foo_u", "range", ")", ")", "(", "call", "mm", "(", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc2 = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next->next->next->next, args); args->pass = CIL_PASS_CALL2; int rc3 = cil_resolve_call2(test_db->ast->root->cl_head->next->next->next->next->next->next->next, args); args->pass = CIL_PASS_MISC2; cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_MISC3; args->callstack = test_db->ast->root->cl_head->next->next->next->next->next->next->next; int rc = cil_resolve_userrange(test_db->ast->root->cl_head->next->next->next->next->next->next->next->cl_head, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, SEPOL_OK, rc2); CuAssertIntEquals(tc, SEPOL_OK, rc3); } void test_cil_resolve_userrange_macro_neg(CuTest *tc) { char *line[] = {"(", "user", "foo_u", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "macro", "mm", "(", "(", "levelrange", "range", ")", ")", "(", "userrange", "foo_u", "range", ")", ")", "(", "call", "mm", "(", "(", "DNE", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc2 = cil_resolve_call1(test_db->ast->root->cl_head->next->next->next->next->next->next->next, args); args->pass = CIL_PASS_CALL2; int rc3 = cil_resolve_call2(test_db->ast->root->cl_head->next->next->next->next->next->next->next, args); args->pass = CIL_PASS_MISC2; cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_MISC3; args->callstack = test_db->ast->root->cl_head->next->next->next->next->next->next->next; int rc = cil_resolve_userrange(test_db->ast->root->cl_head->next->next->next->next->next->next->next->cl_head, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, SEPOL_OK, rc2); CuAssertIntEquals(tc, SEPOL_OK, rc3); } void test_cil_resolve_userrange_range_anon(CuTest *tc) { char *line[] = {"(", "user", "foo_u", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "userrange", "foo_u", "(", "low", "high", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_MISC3; int rc = cil_resolve_userrange(test_db->ast->root->cl_head->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_userrange_range_anon_neg(CuTest *tc) { char *line[] = {"(", "user", "foo_u", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "userrange", "foo_u", "(", "DNE", "high", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_MISC3; int rc = cil_resolve_userrange(test_db->ast->root->cl_head->next->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_userrange_user_neg(CuTest *tc) { char *line[] = {"(", "user", "foo_u", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "levelrange", "range", "(", "(", "s0", "(", "c0", ")", ")", "(", "s0", "(", "c0", ")", ")", ")", ")", "(", "userrange", "DNE", "range", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_MISC3; int rc = cil_resolve_userrange(test_db->ast->root->cl_head->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_userrange_range_neg(CuTest *tc) { char *line[] = {"(", "user", "foo_u", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "levelrange", "range", "(", "(", "s0", "(", "c0", ")", ")", "(", "s0", "(", "c0", ")", ")", ")", ")", "(", "userrange", "foo_u", "DNE", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_senscat(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_MISC3; int rc = cil_resolve_userrange(test_db->ast->root->cl_head->next->next->next->next->next, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_disable_children_helper_optional_enabled(CuTest *tc) { char *line[] = {"(", "optional", "opt", "(", "allow", "foo", "bar", "(", "baz", "file", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t finished = 0; int rc = __cil_disable_children_helper(test_db->ast->root->cl_head, &finished, NULL); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_disable_children_helper_optional_disabled(CuTest *tc) { char *line[] = {"(", "optional", "opt", "(", "allow", "foo", "bar", "(", "baz", "file", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t finished = 0; ((struct cil_optional *)test_db->ast->root->cl_head->data)->datum.state = CIL_STATE_DISABLED; int rc = __cil_disable_children_helper(test_db->ast->root->cl_head, &finished, NULL); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_disable_children_helper_block(CuTest *tc) { char *line[] = {"(", "block", "a", "(", "type", "log", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t finished = 0; int rc = __cil_disable_children_helper(test_db->ast->root->cl_head, &finished, NULL); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_disable_children_helper_user(CuTest *tc) { char *line[] = {"(", "user", "staff_u", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t finished = 0; int rc = __cil_disable_children_helper(test_db->ast->root->cl_head, &finished, NULL); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_disable_children_helper_role(CuTest *tc) { char *line[] = {"(", "role", "role_r", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t finished = 0; int rc = __cil_disable_children_helper(test_db->ast->root->cl_head, &finished, NULL); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_disable_children_helper_type(CuTest *tc) { char *line[] = {"(", "type", "type_t", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t finished = 0; int rc = __cil_disable_children_helper(test_db->ast->root->cl_head, &finished, NULL); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_disable_children_helper_typealias(CuTest *tc) { char *line[] = {"(", "typealias", ".test.type", "type_t", ")", "(", "type", "test", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t finished = 0; int rc = __cil_disable_children_helper(test_db->ast->root->cl_head, &finished, NULL); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_disable_children_helper_common(CuTest *tc) { char *line[] = {"(", "common", "foo", "(", "read", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t finished = 0; int rc = __cil_disable_children_helper(test_db->ast->root->cl_head, &finished, NULL); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_disable_children_helper_class(CuTest *tc) { char *line[] = {"(", "class", "foo", "(", "read", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t finished = 0; int rc = __cil_disable_children_helper(test_db->ast->root->cl_head, &finished, NULL); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_disable_children_helper_bool(CuTest *tc) { char *line[] = {"(", "boolean", "foo", "true", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t finished = 0; int rc = __cil_disable_children_helper(test_db->ast->root->cl_head, &finished, NULL); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_disable_children_helper_sens(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t finished = 0; int rc = __cil_disable_children_helper(test_db->ast->root->cl_head, &finished, NULL); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_disable_children_helper_cat(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t finished = 0; int rc = __cil_disable_children_helper(test_db->ast->root->cl_head, &finished, NULL); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_disable_children_helper_catset(CuTest *tc) { char *line[] = {"(", "categoryset", "somecats", "(", "c0", "c1", "c2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t finished = 0; int rc = __cil_disable_children_helper(test_db->ast->root->cl_head, &finished, NULL); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_disable_children_helper_sid(CuTest *tc) { char *line[] = {"(", "sid", "foo", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t finished = 0; int rc = __cil_disable_children_helper(test_db->ast->root->cl_head, &finished, NULL); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_disable_children_helper_macro(CuTest *tc) { char *line[] = {"(", "macro", "mm", "(", "(", "type", "a", ")", ")", "(", "type", "b", ")", "(", "allow", "a", "b", "(", "file", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t finished = 0; int rc = __cil_disable_children_helper(test_db->ast->root->cl_head, &finished, NULL); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_disable_children_helper_context(CuTest *tc) { char *line[] = {"(", "context", "con", "(", "system_u", "object_r", "netif_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t finished = 0; int rc = __cil_disable_children_helper(test_db->ast->root->cl_head, &finished, NULL); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_disable_children_helper_level(CuTest *tc) { char *line[] = {"(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t finished = 0; int rc = __cil_disable_children_helper(test_db->ast->root->cl_head, &finished, NULL); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_disable_children_helper_policycap(CuTest *tc) { char *line[] = {"(", "policycap", "foo", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t finished = 0; int rc = __cil_disable_children_helper(test_db->ast->root->cl_head, &finished, NULL); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_disable_children_helper_perm(CuTest *tc) { char *line[] = {"(", "class", "foo", "(", "read", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t finished = 0; int rc = __cil_disable_children_helper(test_db->ast->root->cl_head->cl_head, &finished, NULL); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_disable_children_helper_catalias(CuTest *tc) { char *line[] = {"(", "categoryalias", "c0", "red", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t finished = 0; int rc = __cil_disable_children_helper(test_db->ast->root->cl_head, &finished, NULL); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_disable_children_helper_sensalias(CuTest *tc) { char *line[] = {"(", "sensitivityalias", "s0", "red", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t finished = 0; int rc = __cil_disable_children_helper(test_db->ast->root->cl_head, &finished, NULL); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_disable_children_helper_tunable(CuTest *tc) { char *line[] = {"(", "tunable", "foo", "false", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t finished = 0; int rc = __cil_disable_children_helper(test_db->ast->root->cl_head, &finished, NULL); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_disable_children_helper_unknown(CuTest *tc) { char *line[] = {"(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "l2", "h2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); cil_build_ast(test_db, test_tree->root, test_db->ast->root); uint32_t finished = 0; int rc = __cil_disable_children_helper(test_db->ast->root->cl_head, &finished, NULL); CuAssertIntEquals(tc, SEPOL_OK, rc); } /* __cil_resolve_ast_node_helper test cases */ void test_cil_resolve_ast_node_helper_call1(CuTest *tc) { char *line[] = {"(", "type", "qaz", ")", "(", "class", "file", "(", "read", ")", ")", "(", "macro", "mm", "(", "(", "type", "a", ")", ")", "(", "type", "b", ")", "(", "allow", "a", "b", "(", "file", "(", "read", ")", ")", ")", ")", "(", "call", "mm", "(", "qaz", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_call1_neg(CuTest *tc) { char *line[] = {"(", "type", "qaz", ")", "(", "class", "file", "(", "read", ")", ")", "(", "macro", "mm", "(", "(", "type", "a", ")", ")", "(", "type", "b", ")", "(", "allow", "a", "b", "(", "file", "(", "read", ")", ")", ")", ")", "(", "call", "m", "(", "qaz", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_call2(CuTest *tc) { char *line[] = {"(", "type", "qaz", ")", "(", "class", "file", "(", "read", ")", ")", "(", "macro", "mm", "(", "(", "type", "a", ")", ")", "(", "type", "b", ")", "(", "allow", "a", "b", "(", "file", "(", "read", ")", ")", ")", ")", "(", "call", "mm", "(", "qaz", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_call1(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_CALL2; int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_call2_neg(CuTest *tc) { char *line[] = {"(", "type", "qaz", ")", "(", "class", "file", "(", "read", ")", ")", "(", "macro", "mm", "(", "(", "type", "a", ")", ")", "(", "type", "b", ")", "(", "allow", "a", "b", "(", "file", "(", "read", ")", ")", ")", ")", "(", "call", "mm", "(", "foo", "extra", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_call1(test_db->ast->root->cl_head->next->next->next, args); args->pass = CIL_PASS_CALL2; int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_ast_node_helper_boolif(CuTest *tc) { char *line[] = {"(", "boolean", "foo", "true", ")", "(", "boolean", "bar", "false", ")", "(", "class", "baz", "(", "read", ")", ")", "(", "booleanif", "(", "and", "foo", "bar", ")", "(", "true", "(", "allow", "foo", "bar", "(", "baz", "(", "read", ")", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC1, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_boolif_neg(CuTest *tc) { char *line[] = {"(", "boolean", "foo", "true", ")", "(", "boolean", "bar", "false", ")", "(", "class", "baz", "(", "read", ")", ")", "(", "booleanif", "(", "and", "dne", "N/A", ")", "(", "true", "(", "allow", "foo", "bar", "(", "baz", "(", "read", ")", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC1, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_tunif(CuTest *tc) { char *line[] = {"(", "tunable", "foo", "true", ")", "(", "tunable", "bar", "false", ")", "(", "class", "baz", "(", "read", ")", ")", "(", "tunableif", "(", "and", "foo", "bar", ")", "(", "false", "(", "allow", "foo", "bar", "(", "baz", "(", "read", ")", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_TIF, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_tunif_neg(CuTest *tc) { char *line[] = {"(", "tunable", "foo", "true", ")", "(", "tunable", "bar", "false", ")", "(", "class", "baz", "(", "read", ")", ")", "(", "tunableif", "(", "and", "dne", "N/A", ")", "(", "true", "(", "allow", "foo", "bar", "(", "baz", "(", "read", ")", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_TIF, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_catorder(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c1", ")", "(", "category", "c2", ")", "(", "categoryorder", "(", "c0", "c1", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC1, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_catorder_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c1", ")", "(", "category", "c2", ")", "(", "categoryorder", "(", "c8", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC1, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_dominance(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "sensitivity", "s1", ")", "(", "sensitivity", "s2", ")", "(", "dominance", "(", "s0", "s1", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC1, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_dominance_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "sensitivity", "s1", ")", "(", "sensitivity", "s2", ")", "(", "dominance", "(", "s0", "s6", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC1, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_roleallow(CuTest *tc) { char *line[] = {"(", "role", "foo", ")", \ "(", "role", "bar", ")", \ "(", "roleallow", "foo", "bar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_roleallow_neg(CuTest *tc) { char *line[] = {"(", "role", "foo", ")", \ "(", "roleallow", "foo", "bar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_sensalias(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "sensitivityalias", "s0", "alias", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MLS, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_sensalias_neg(CuTest *tc) { char *line[] = {"(", "sensitivityalias", "s0", "alias", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MLS, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_catalias(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "categoryalias", "c0", "red", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MLS, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_catalias_neg(CuTest *tc) { char *line[] = {"(", "categoryalias", "c0", "red", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_catset(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c1", ")", "(", "category", "c2", ")", "(", "categoryset", "somecats", "(", "c0", "c1", "c2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MLS, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_catset_catlist_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c1", ")", "(", "categoryset", "somecats", "(", "c0", "c1", "c2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MLS, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_catrange(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c255", ")", "(", "categoryorder", "(", "c0", "c255", ")", ")", "(", "categoryrange", "range", "(", "c0", "c255", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC1, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_catorder(test_db->ast->root->cl_head->next->next, args); __cil_verify_order(test_db->catorder, test_db->ast->root, CIL_CAT); args->pass = CIL_PASS_MLS; int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_catrange_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "category", "c255", ")", "(", "categoryorder", "(", "c0", "c255", ")", ")", "(", "categoryrange", "range", "(", "c255", "c0", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MLS, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_level(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c1", ")", "(", "sensitivitycategory", "s0", "(", "c1", ")", ")", "(", "level", "l2", "(", "s0", "(", "c1", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC1, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_tree_walk(test_db->ast->root, __cil_resolve_ast_node_helper, NULL, NULL, args); __cil_verify_order(test_db->catorder, test_db->ast->root, CIL_CAT); __cil_verify_order(test_db->dominance, test_db->ast->root, CIL_SENS); args->pass = CIL_PASS_MLS; cil_tree_walk(test_db->ast->root, __cil_resolve_ast_node_helper, NULL, NULL, args); args->pass = CIL_PASS_MISC2; cil_tree_walk(test_db->ast->root, __cil_resolve_ast_node_helper, NULL, NULL, args); args->pass = CIL_PASS_MISC3; int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, finished, 0); } void test_cil_resolve_ast_node_helper_level_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c1", ")", "(", "sensitivitycategory", "s0", "(", "c1", ")", ")", "(", "level", "l2", "(", "s8", "(", "c1", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC1, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_tree_walk(test_db->ast->root, __cil_resolve_ast_node_helper, NULL, NULL, args); __cil_verify_order(test_db->catorder, test_db->ast->root, CIL_CAT); __cil_verify_order(test_db->dominance, test_db->ast->root, CIL_SENS); args->pass = CIL_PASS_MLS; cil_tree_walk(test_db->ast->root, __cil_resolve_ast_node_helper, NULL, NULL, args); args->pass = CIL_PASS_MISC3; int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, finished, 0); } void test_cil_resolve_ast_node_helper_levelrange(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "categoryorder", "(", "c0", ")", ")", "(", "dominance", "(", "s0", ")", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "levelrange", "range", "(", "(", "s0", "(", "c0", ")", ")", "(", "s0", "(", "c0", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC1, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_tree_walk(test_db->ast->root, __cil_resolve_ast_node_helper, NULL, NULL, args); __cil_verify_order(test_db->catorder, test_db->ast->root, CIL_CAT); __cil_verify_order(test_db->dominance, test_db->ast->root, CIL_SENS); args->pass = CIL_PASS_MLS; cil_tree_walk(test_db->ast->root, __cil_resolve_ast_node_helper, NULL, NULL, args); args->pass = CIL_PASS_MISC2; cil_tree_walk(test_db->ast->root, __cil_resolve_ast_node_helper, NULL, NULL, args); args->pass = CIL_PASS_MISC3; int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, finished, 0); } void test_cil_resolve_ast_node_helper_levelrange_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "categoryorder", "(", "c0", ")", ")", "(", "dominance", "(", "s0", ")", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "levelrange", "range", "(", "(", "DNE", "(", "c0", ")", ")", "(", "s0", "(", "c0", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC1, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_tree_walk(test_db->ast->root, __cil_resolve_ast_node_helper, NULL, NULL, args); __cil_verify_order(test_db->catorder, test_db->ast->root, CIL_CAT); __cil_verify_order(test_db->dominance, test_db->ast->root, CIL_SENS); args->pass = CIL_PASS_MLS; cil_tree_walk(test_db->ast->root, __cil_resolve_ast_node_helper, NULL, NULL, args); args->pass = CIL_PASS_MISC3; int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, finished, 0); } void test_cil_resolve_ast_node_helper_constrain(CuTest *tc) { char *line[] = {"(", "class", "file", "(", "create", "relabelto", ")", ")", "(", "class", "dir", "(", "create", "relabelto", ")", ")", "(", "sensitivity", "s0", ")", "(", "category", "c1", ")", "(", "role", "r1", ")", "(", "role", "r2", ")", "(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "r1", "r2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_constrain_neg(CuTest *tc) { char *line[] = {"(", "class", "file", "(", "create", ")", ")", "(", "class", "dir", "(", "create", ")", ")", "(", "sensitivity", "s0", ")", "(", "category", "c1", ")", "(", "role", "r1", ")", "(", "role", "r2", ")", "(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "r1", "r2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_mlsconstrain(CuTest *tc) { char *line[] = {"(", "class", "file", "(", "create", "relabelto", ")", ")", "(", "class", "dir", "(", "create", "relabelto", ")", ")", "(", "sensitivity", "s0", ")", "(", "category", "c1", ")", "(", "level", "l2", "(", "s0", "(", "c1", ")", ")", ")", "(", "level", "h2", "(", "s0", "(", "c1", ")", ")", ")", "(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "l2", "h2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_mlsconstrain_neg(CuTest *tc) { char *line[] = {"(", "class", "file", "(", "read", ")", ")", "(", "class", "dir", "(", "read", ")", ")", "(", "sensitivity", "s0", ")", "(", "category", "c1", ")", "(", "level", "l2", "(", "s0", "(", "c1", ")", ")", ")", "(", "level", "h2", "(", "s0", "(", "c1", ")", ")", ")", "(", "mlsconstrain", "(", "file", "(", "create", "relabelto", ")", ")", "(", "eq", "l2", "h2", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_context(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "user", "system_u", ")", "(", "role", "object_r", ")", "(", "type", "netif_t", ")", "(", "context", "con", "(", "system_u", "object_r", "netif_t", "(", "low", "high", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC1, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_tree_walk(test_db->ast->root, __cil_resolve_ast_node_helper, NULL, NULL, args); __cil_verify_order(test_db->catorder, test_db->ast->root, CIL_CAT); __cil_verify_order(test_db->dominance, test_db->ast->root, CIL_SENS); args->pass = CIL_PASS_MLS; cil_tree_walk(test_db->ast->root, __cil_resolve_ast_node_helper, NULL, NULL, args); args->pass = CIL_PASS_MISC3; int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, finished, 0); } void test_cil_resolve_ast_node_helper_context_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "user", "system_u", ")", "(", "role", "object_r", ")", "(", "type", "netif_t", ")", "(", "context", "con", "(", "system_u", "object_r", "netif_t", "DNE", "high", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC1, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_tree_walk(test_db->ast->root, __cil_resolve_ast_node_helper, NULL, NULL, args); __cil_verify_order(test_db->catorder, test_db->ast->root, CIL_CAT); __cil_verify_order(test_db->dominance, test_db->ast->root, CIL_SENS); args->pass = CIL_PASS_MLS; cil_tree_walk(test_db->ast->root, __cil_resolve_ast_node_helper, NULL, NULL, args); args->pass = CIL_PASS_MISC3; int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, finished, 0); } void test_cil_resolve_ast_node_helper_senscat(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "sensitivity", "s1", ")", "(", "dominance", "(", "s0", "s1", ")", ")", "(", "category", "c0", ")", "(", "category", "c255", ")", "(", "categoryorder", "(", "c0", "c255", ")", ")", "(", "sensitivitycategory", "s1", "(", "c0", "c255", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_senscat_neg(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "sensitivity", "s1", ")", "(", "dominance", "(", "s0", "s1", ")", ")", "(", "category", "c0", ")", "(", "category", "c255", ")", "(", "categoryorder", "(", "c0", "c255", ")", ")", "(", "sensitivitycategory", "s5", "foo", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_roletransition(CuTest *tc) { char *line[] = {"(", "role", "foo_r", ")", "(", "type", "bar_t", ")", "(", "role", "foobar_r", ")", "(", "class", "process", "(", "transition", ")", ")", "(", "roletransition", "foo_r", "bar_t", "process", "foobar_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_roletransition_srcdecl_neg(CuTest *tc) { char *line[] = {"(", "type", "bar_t", ")", "(", "role", "foobar_r", ")", "(", "class", "process", "(", "transition", ")", ")", "(", "roletransition", "foo_r", "bar_t", "process", "foobar_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_roletransition_tgtdecl_neg(CuTest *tc) { char *line[] = {"(", "role", "foo_r", ")", "(", "role", "foobar_r", ")", "(", "class", "process", "(", "transition", ")", ")", "(", "roletransition", "foo_r", "bar_t", "process", "foobar_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_roletransition_resultdecl_neg(CuTest *tc) { char *line[] = {"(", "role", "foo_r", ")", "(", "type", "bar_t", ")", "(", "class", "process", "(", "transition", ")", ")", "(", "roletransition", "foo_r", "bar_t", "process", "foobar_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_typeattributeset(CuTest *tc) { char *line[] = {"(", "typeattribute", "attrs", ")", "(", "type", "type_t", ")", "(", "type", "type_tt", ")", "(", "typeattributeset", "attrs", "(", "type_t", "type_tt", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_typeattributeset_undef_type_neg(CuTest *tc) { char *line[] = {"(", "typeattribute", "attrs", ")", "(", "type", "type_t", ")", "(", "typeattributeset", "attrs", "(", "not", "t_t", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_typealias(CuTest *tc) { char *line[] = {"(", "block", "foo", "(", "typealias", ".foo.test", "type_t", ")", "(", "type", "test", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->cl_head, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_typealias_notype_neg(CuTest *tc) { char *line[] = {"(", "block", "bar", "(", "typealias", ".bar.test", "type_t", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->cl_head, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_typebounds(CuTest *tc) { char *line[] = {"(", "type", "type_a", ")", "(", "type", "type_b", ")", "(", "typebounds", "type_a", "type_b", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_typebounds_neg(CuTest *tc) { char *line[] = {"(", "type", "type_b", ")", "(", "typebounds", "type_a", "type_b", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_typepermissive(CuTest *tc) { char *line[] = {"(", "type", "type_a", ")", "(", "typepermissive", "type_a", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_typepermissive_neg(CuTest *tc) { char *line[] = {"(", "type", "type_b", ")", "(", "typepermissive", "type_a", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_rangetransition(CuTest *tc) { char *line[] = {"(", "class", "class_", "(", "read", ")", ")", "(", "type", "type_a", ")", "(", "type", "type_b", ")", "(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "rangetransition", "type_a", "type_b", "class_", "(", "low", "high", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next->next->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_rangetransition_neg(CuTest *tc) { char *line[] = {"(", "class", "class_", "(", "read", ")", ")", "(", "type", "type_a", ")", "(", "type", "type_b", ")", "(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "rangetransition", "type_DNE", "type_b", "class_", "(", "low", "high", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next->next->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_nametypetransition(CuTest *tc) { char *line[] = {"(", "type", "foo", ")", "(", "type", "bar", ")", "(", "class", "file", "(", "read", ")", ")", "(", "type", "foobar", ")", "(", "nametypetransition", "str", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_nametypetransition_neg(CuTest *tc) { char *line[] = {"(", "type", "foo", ")", "(", "type", "bar", ")", "(", "class", "file", "(", "read", ")", ")", "(", "type", "foobar", ")", "(", "nametypetransition", "str", "foo", "bar", "file", "foobarrr", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_avrule(CuTest *tc) { char *line[] = {"(", "class", "bar", "(", "read", "write", "open", ")", ")", "(", "type", "test", ")", "(", "type", "foo", ")", "(", "allow", "test", "foo", "(", "bar", "(", "read", "write", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_avrule_src_nores_neg(CuTest *tc) { char *line[] = {"(", "allow", "test", "foo", "(", "bar", "(", "read", "write", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_avrule_tgt_nores_neg(CuTest *tc) { char *line[] = {"(", "type", "test", ")", "(", "allow", "test", "foo", "(", "bar", "(", "read", "write", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_avrule_class_nores_neg(CuTest *tc) { char *line[] = {"(", "type", "test", ")", "(", "type", "foo", ")", "(", "allow", "test", "foo", "(", "bar", "(", "read", "write", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_avrule_datum_null_neg(CuTest *tc) { char *line[] = {"(", "class", "bar", "(", "read", "write", "open", ")", ")", "(", "type", "test", ")", "(", "type", "foo", ")", "(", "allow", "test", "foo", "(", "bar", "(","fake", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_type_rule_transition(CuTest *tc) { char *line[] = {"(", "type", "foo", ")", "(", "type", "bar", ")", "(", "class", "file", "(", "write", ")", ")", "(", "type", "foobar", ")", "(", "typetransition", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_type_rule_transition_neg(CuTest *tc) { char *line[] = {"(", "type", "foo", ")", "(", "class", "file", "(", "write", ")", ")", "(", "type", "foobar", ")", "(", "typetransition", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_type_rule_change(CuTest *tc) { char *line[] = {"(", "type", "foo", ")", "(", "type", "bar", ")", "(", "class", "file", "(", "write", ")", ")", "(", "type", "foobar", ")", "(", "typechange", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_type_rule_change_neg(CuTest *tc) { char *line[] = {"(", "type", "foo", ")", "(", "class", "file", "(", "write", ")", ")", "(", "type", "foobar", ")", "(", "typechange", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_type_rule_member(CuTest *tc) { char *line[] = {"(", "type", "foo", ")", "(", "type", "bar", ")", "(", "class", "file", "(", "write", ")", ")", "(", "type", "foobar", ")", "(", "typemember", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_type_rule_member_neg(CuTest *tc) { char *line[] = {"(", "type", "foo", ")", "(", "class", "file", "(", "write", ")", ")", "(", "type", "foobar", ")", "(", "typemember", "foo", "bar", "file", "foobar", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_userbounds(CuTest *tc) { char *line[] = {"(", "user", "user1", ")", "(", "user", "user2", ")", "(", "userbounds", "user1", "user2", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); uint32_t finished = 0; uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next, &finished, args); CuAssertIntEquals(tc, 0, finished); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_ast_node_helper_userbounds_neg(CuTest *tc) { char *line[] = {"(", "user", "user1", ")", "(", "userbounds", "user1", "user2", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); uint32_t finished = 0; uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next, &finished, args); CuAssertIntEquals(tc, 0, finished); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_ast_node_helper_roletype(CuTest *tc) { char *line[] = {"(", "role", "admin_r", ")", "(", "type", "admin_t", ")", "(", "roletype", "admin_r", "admin_t", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); uint32_t finished = 0; uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next, &finished, args); CuAssertIntEquals(tc, 0, finished); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_ast_node_helper_roletype_role_neg(CuTest *tc) { char *line[] = {"(", "type", "admin_t", ")", "(", "roletype", "admin_r", "admin_t", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); uint32_t finished = 0; uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next, &finished, args); CuAssertIntEquals(tc, 0, finished); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_ast_node_helper_roletype_type_neg(CuTest *tc) { char *line[] = {"(", "role", "admin_r", ")", "(", "roletype", "admin_r", "admin_t", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); uint32_t finished = 0; uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next, &finished, args); CuAssertIntEquals(tc, 0, finished); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_ast_node_helper_userrole(CuTest *tc) { char *line[] = {"(", "role", "staff_r", ")", "(", "user", "staff_u", ")", "(", "userrole", "staff_u", "staff_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); uint32_t finished = 0; uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next, &finished, args); CuAssertIntEquals(tc, 0, finished); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_ast_node_helper_userrole_user_neg(CuTest *tc) { char *line[] = {"(", "role", "staff_r", ")", "(", "userrole", "staff_u", "staff_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); uint32_t finished = 0; uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next, &finished, args); CuAssertIntEquals(tc, 0, finished); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_ast_node_helper_userrole_role_neg(CuTest *tc) { char *line[] = {"(", "user", "staff_u", ")", "(", "userrole", "staff_u", "staff_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); uint32_t finished = 0; uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next, &finished, args); CuAssertIntEquals(tc, 0, finished); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_ast_node_helper_userlevel(CuTest *tc) { char *line[] = {"(", "user", "foo_u", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "userlevel", "foo_u", "low", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); uint32_t finished = 0; uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next->next->next, &finished, args); CuAssertIntEquals(tc, 0, finished); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_ast_node_helper_userlevel_neg(CuTest *tc) { char *line[] = {"(", "user", "foo_u", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "userlevel", "DNE", "low", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); uint32_t finished = 0; uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next->next->next, &finished, args); CuAssertIntEquals(tc, 0, finished); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_ast_node_helper_userrange(CuTest *tc) { char *line[] = {"(", "user", "foo_u", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "levelrange", "range", "(", "(", "s0", "(", "c0", ")", ")", "(", "s0", "(", "c0", ")", ")", ")", ")", "(", "userrange", "foo_u", "range", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); uint32_t finished = 0; uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next->next->next, &finished, args); CuAssertIntEquals(tc, 0, finished); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_ast_node_helper_userrange_neg(CuTest *tc) { char *line[] = {"(", "user", "foo_u", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "levelrange", "range", "(", "(", "s0", "(", "c0", ")", ")", "(", "s0", "(", "c0", ")", ")", ")", ")", "(", "userrange", "DNE", "range", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); uint32_t finished = 0; uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next->next->next, &finished, args); CuAssertIntEquals(tc, 0, finished); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_ast_node_helper_filecon(CuTest *tc) { char *line[] = {"(", "user", "user_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "context", "con", "(", "user_u", "role_r", "type_t", "(", "low", "high", ")", ")", ")", "(", "filecon", "root", "path", "file", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_filecon_neg(CuTest *tc) { char *line[] = {"(", "user", "user_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "context", "con", "(", "user_u", "role_r", "type_t", "(", "low", "high", ")", ")", ")", "(", "filecon", "root", "path", "file", "foo", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_portcon(CuTest *tc) { char *line[] = {"(", "user", "user_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "context", "con", "(", "user_u", "role_r", "type_t", "(", "low", "high", ")", ")", ")", "(", "portcon", "udp", "25", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_portcon_neg(CuTest *tc) { char *line[] = {"(", "user", "user_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "context", "con", "(", "user_u", "role_r", "type_t", "(", "low", "high", ")", ")", ")", "(", "portcon", "udp", "25", "foo", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_genfscon(CuTest *tc) { char *line[] = {"(", "user", "user_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "context", "con", "(", "user_u", "role_r", "type_t", "(", "low", "high", ")", ")", ")", "(", "genfscon", "type", "path", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_genfscon_neg(CuTest *tc) { char *line[] = {"(", "user", "user_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "context", "con", "(", "user_u", "role_r", "type_t", "(", "low", "high", ")", ")", ")", "(", "genfscon", "type", "path", "foo", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_nodecon(CuTest *tc) { char *line[] = {"(", "user", "user_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "context", "con", "(", "user_u", "role_r", "type_t", "(", "low", "high", ")", ")", ")", "(", "ipaddr", "ip", "192.168.1.1", ")", "(", "nodecon", "ip", "ip", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_nodecon_ipaddr_neg(CuTest *tc) { char *line[] = {"(", "user", "user_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "context", "con", "(", "user_u", "role_r", "type_t", "(", "low", "high", ")", ")", ")", "(", "ipaddr", "ip", "192.168.1.1", ")", "(", "ipaddr", "netmask", "192.168.1.1", ")", "(", "nodecon", "ipp", "netmask", "foo", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_nodecon_netmask_neg(CuTest *tc) { char *line[] = {"(", "user", "user_u", ")", "(", "role", "role_r", ")", "(", "type", "type_t", ")", "(", "category", "c0", ")", "(", "sensitivity", "s0", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "context", "con", "(", "user_u", "role_r", "type_t", "(", "low", "high", ")", ")", ")", "(", "ipaddr", "ip", "192.168.1.1", ")", "(", "ipaddr", "netmask", "192.168.1.1", ")", "(", "nodecon", "ip", "nnetmask", "foo", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_netifcon(CuTest *tc) { char *line[] = {"(", "context", "if_default", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", "(", "context", "packet_default", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", "(", "netifcon", "eth0", "if_default", "packet_default", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_netifcon_neg(CuTest *tc) { char *line[] = {"(", "context", "if_default", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", "(", "netifcon", "eth0", "if_default", "packet_default", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_pirqcon(CuTest *tc) { char *line[] = {"(", "context", "con", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", "(", "pirqcon", "1", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_pirqcon_neg(CuTest *tc) { char *line[] = {"(", "context", "con", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", "(", "pirqcon", "1", "dne", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_iomemcon(CuTest *tc) { char *line[] = {"(", "context", "con", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", "(", "iomemcon", "1", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_iomemcon_neg(CuTest *tc) { char *line[] = {"(", "context", "con", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", "(", "iomemcon", "1", "dne", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_ioportcon(CuTest *tc) { char *line[] = {"(", "context", "con", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", "(", "ioportcon", "1", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_ioportcon_neg(CuTest *tc) { char *line[] = {"(", "context", "con", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", "(", "ioportcon", "1", "dne", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_pcidevicecon(CuTest *tc) { char *line[] = {"(", "context", "con", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", "(", "pcidevicecon", "1", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_pcidevicecon_neg(CuTest *tc) { char *line[] = {"(", "context", "con", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", "(", "pcidevicecon", "1", "dne", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_fsuse(CuTest *tc) { char *line[] = {"(", "sensitivity", "s0", ")", "(", "category", "c0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "user", "system_u", ")", "(", "role", "object_r", ")", "(", "type", "netif_t", ")", "(", "context", "con", "(", "system_u", "object_r", "netif_t", "(", "low", "high", ")", ")", ")", "(", "fsuse", "xattr", "ext3", "con", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_fsuse_neg(CuTest *tc) { char *line[] = {"(", "context", "if_default", "(", "system_u", "object_r", "etc_t", "(", "low", "high", ")", ")", ")", "(", "netifcon", "eth0", "if_default", "packet_default", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_sidcontext(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "categoryorder", "(", "c0", ")", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "type", "blah_t", ")", "(", "role", "blah_r", ")", "(", "user", "blah_u", ")", "(", "level", "low", "(", "s0", "(", "c0", ")", ")", ")", "(", "level", "high", "(", "s0", "(", "c0", ")", ")", ")", "(", "sid", "test", "(", "blah_u", "blah_r", "blah_t", "(", "low", "high", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next->next->next->next->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_sidcontext_neg(CuTest *tc) { char *line[] = {"(", "category", "c0", ")", "(", "categoryorder", "(", "c0", ")", ")", "(", "sensitivity", "s0", ")", "(", "sensitivitycategory", "s0", "(", "c0", ")", ")", "(", "type", "blah_t", ")", "(", "role", "blah_r", ")", "(", "user", "blah_u", ")", "(", "sidcontext", "test", "(", "", "blah_r", "blah_t", "(", "(", "s0", "(", "c0", ")", ")", "(", "s0", "(", "c0", ")", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next->next->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_blockinherit(CuTest *tc) { char *line[] = {"(", "block", "baz", "(", "type", "foo", ")", ")", "(", "block", "bar", "(", "type", "a", ")", "(", "blockinherit", "baz", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_BLKIN, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->cl_head->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_classcommon(CuTest *tc) { char *line[] = {"(", "class", "file", "(", "read", ")", ")", "(", "common", "file", "(", "write", ")", ")", "(", "classcommon", "file", "file", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_classcommon_neg(CuTest *tc) { char *line[] = {"(", "class", "file", "(", "read", ")", ")", "(", "classcommon", "file", "file", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_rolebounds(CuTest *tc) { char *line[] = {"(", "role", "role1", ")", "(", "role", "role2", ")", "(", "rolebounds", "role1", "role2", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); uint32_t finished = 0; uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next, &finished, args); CuAssertIntEquals(tc, 0, finished); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_ast_node_helper_rolebounds_neg(CuTest *tc) { char *line[] = {"(", "role", "role1", ")", "(", "rolebounds", "role1", "role2", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); uint32_t finished = 0; uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next, &finished, args); CuAssertIntEquals(tc, 0, finished); CuAssertIntEquals(tc, SEPOL_ENOENT, rc); } void test_cil_resolve_ast_node_helper_callstack(CuTest *tc) { char *line[] = {"(", "call", "mm", "(", "foo", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_tree_node *test_ast_node_call; cil_tree_node_init(&test_ast_node_call); test_ast_node_call->flavor = CIL_CALL; uint32_t finished = 0; uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); __cil_resolve_ast_node_helper(test_db->ast->root->cl_head, &finished, args); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_ast_node_helper_call(CuTest *tc) { char *line[] = {"(", "call", "mm", "(", "foo", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_tree_node *test_ast_node_call; cil_tree_node_init(&test_ast_node_call); test_ast_node_call->flavor = CIL_CALL; uint32_t finished = 0; uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_ast_node_helper_optional(CuTest *tc) { char *line[] = {"(", "optional", "opt", "(", "allow", "foo", "bar", "(", "file", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_tree_node *test_ast_node_opt; cil_tree_node_init(&test_ast_node_opt); test_ast_node_opt->flavor = CIL_OPTIONAL; uint32_t finished = 0; uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); // set optional to disabled ((struct cil_symtab_datum *)test_db->ast->root->cl_head->data)->state = CIL_STATE_DISABLED; int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_ast_node_helper_macro(CuTest *tc) { char *line[] = {"(", "macro", "mm", "(", "(", "type", "a", ")", ")", "(", "type", "b", ")", "(", "allow", "a", "b", "(", "file", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); uint32_t finished = 0; uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_ast_node_helper_optstack(CuTest *tc) { char *line[] = {"(", "class", "baz", "(", "read", ")", ")", "(", "type", "foo", ")", "(", "type", "bar", ")", "(", "optional", "opt", "(", "allow", "foo", "bar", "(", "baz", "(", "read", ")", ")", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_tree_node *test_ast_node_opt; cil_tree_node_init(&test_ast_node_opt); test_ast_node_opt->flavor = CIL_OPTIONAL; uint32_t finished = 0; uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next, &finished, args); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); } void test_cil_resolve_ast_node_helper_optstack_tunable_neg(CuTest *tc) { char *line[] = {"(", "tunable", "foo", "true", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node_opt; cil_tree_node_init(&test_ast_node_opt); test_ast_node_opt->flavor = CIL_OPTIONAL; uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_TIF, &changed, NULL, test_ast_node_opt, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head, &finished, args); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_resolve_ast_node_helper_optstack_macro_neg(CuTest *tc) { char *line[] = {"(", "type", "qaz", ")", "(", "class", "file", "(", "read", ")", ")", "(", "macro", "mm", "(", "(", "type", "a", ")", ")", "(", "type", "b", ")", "(", "allow", "a", "b", "(", "file", "(", "read", ")", ")", ")", ")", "(", "call", "mm", "(", "qaz", ")", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node_opt; cil_tree_node_init(&test_ast_node_opt); test_ast_node_opt->flavor = CIL_OPTIONAL; uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_CALL1, &changed, NULL, test_ast_node_opt, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); cil_resolve_call1(test_db->ast->root->cl_head->next->next, args); args->pass = CIL_PASS_CALL2; int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ERR, rc); CuAssertIntEquals(tc, 0, finished); } void test_cil_resolve_ast_node_helper_nodenull_neg(CuTest *tc) { char *line[] = {"(", "role", "staff_r", ")", "(", "user", "staff_u", ")", "(", "userrole", "staff_u", "staff_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_TIF, &changed, NULL, NULL, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(NULL, &finished, args); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_resolve_ast_node_helper_extraargsnull_neg(CuTest *tc) { char *line[] = {"(", "role", "staff_r", ")", "(", "user", "staff_u", ")", "(", "userrole", "staff_u", "staff_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next, &finished, NULL); CuAssertIntEquals(tc, 0, finished); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_resolve_ast_node_helper_dbflavor_neg(CuTest *tc) { char *line[] = {"(", "role", "staff_r", ")", "(", "user", "staff_u", ")", "(", "userrole", "staff_u", "staff_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); uint32_t finished = 0; uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_resolve_ast_node_helper_pass_neg(CuTest *tc) { char *line[] = {"(", "role", "staff_r", ")", "(", "user", "staff_u", ")", "(", "userrole", "staff_u", "staff_r", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); uint32_t finished = 0; uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC3, &changed, NULL, NULL, NULL); cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next->next, &finished, args); CuAssertIntEquals(tc, SEPOL_ERR, rc); } void test_cil_resolve_ast_node_helper_optfailedtoresolve(CuTest *tc) { char *line[] = {"(", "class", "file", "(", "read", ")", ")", "(", "classcommon", "file", "file", ")", NULL}; struct cil_tree *test_tree; gen_test_tree(&test_tree, line); struct cil_db *test_db; cil_db_init(&test_db); struct cil_optional *opt; cil_optional_init(&opt); struct cil_tree_node *test_ast_node_opt; cil_tree_node_init(&test_ast_node_opt); test_ast_node_opt->flavor = CIL_OPTIONAL; test_ast_node_opt->data = opt; uint32_t changed = CIL_FALSE; struct cil_args_resolve *args = gen_resolve_args(test_db, CIL_PASS_MISC2, &changed, NULL, test_ast_node_opt, NULL); uint32_t finished = 0; cil_build_ast(test_db, test_tree->root, test_db->ast->root); int rc = __cil_resolve_ast_node_helper(test_db->ast->root->cl_head->next, &finished, args); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertIntEquals(tc, 0, finished); } libsepol-3.8.1/cil/test/unit/test_cil_resolve_ast.h000066400000000000000000000640471476211737200224530ustar00rootroot00000000000000/* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #ifndef TEST_CIL_RESOLVE_AST_H_ #define TEST_CIL_RESOLVE_AST_H_ #include "CuTest.h" void test_cil_resolve_name(CuTest *); void test_cil_resolve_name_invalid_type_neg(CuTest *); void test_cil_resolve_ast_curr_null_neg(CuTest *); /* cil_resolve test cases */ void test_cil_resolve_roleallow(CuTest *); void test_cil_resolve_roleallow_srcdecl_neg(CuTest *); void test_cil_resolve_roleallow_tgtdecl_neg(CuTest *); void test_cil_resolve_rolebounds(CuTest *tc); void test_cil_resolve_rolebounds_exists_neg(CuTest *tc); void test_cil_resolve_rolebounds_role1_neg(CuTest *tc); void test_cil_resolve_rolebounds_role2_neg(CuTest *tc); void test_cil_resolve_sensalias(CuTest *); void test_cil_resolve_sensalias_sensdecl_neg(CuTest *); void test_cil_resolve_catalias(CuTest *); void test_cil_resolve_catalias_catdecl_neg(CuTest *); void test_cil_resolve_catorder(CuTest *); void test_cil_resolve_catorder_neg(CuTest *); void test_cil_resolve_dominance(CuTest *); void test_cil_resolve_dominance_neg(CuTest *); void test_cil_resolve_cat_list(CuTest *); void test_cil_resolve_cat_list_catlistnull_neg(CuTest *); void test_cil_resolve_cat_list_rescatlistnull_neg(CuTest *); void test_cil_resolve_cat_list_catrange(CuTest *); void test_cil_resolve_cat_list_catrange_neg(CuTest *); void test_cil_resolve_cat_list_catname_neg(CuTest *); void test_cil_resolve_catset(CuTest *); void test_cil_resolve_catset_catlist_neg(CuTest *); void test_cil_resolve_catrange(CuTest *); void test_cil_resolve_catrange_catloworder_neg(CuTest *); void test_cil_resolve_catrange_cathighorder_neg(CuTest *); void test_cil_resolve_catrange_cat1_neg(CuTest *); void test_cil_resolve_catrange_cat2_neg(CuTest *); void test_cil_resolve_senscat(CuTest *); void test_cil_resolve_senscat_catrange_neg(CuTest *); void test_cil_resolve_senscat_catsetname(CuTest *); void test_cil_resolve_senscat_catsetname_neg(CuTest *); void test_cil_resolve_senscat_sublist(CuTest *); void test_cil_resolve_senscat_missingsens_neg(CuTest *); void test_cil_resolve_senscat_sublist_neg(CuTest *); void test_cil_resolve_senscat_category_neg(CuTest *); void test_cil_resolve_senscat_currrangecat(CuTest *); void test_cil_resolve_senscat_currrangecat_neg(CuTest *); void test_cil_resolve_level(CuTest *); void test_cil_resolve_level_catlist(CuTest *); void test_cil_resolve_level_catset(CuTest *); void test_cil_resolve_level_catset_name_neg(CuTest *); void test_cil_resolve_level_sens_neg(CuTest *); void test_cil_resolve_level_cat_neg(CuTest *); void test_cil_resolve_level_senscat_neg(CuTest *); void test_cil_resolve_levelrange_namedlvl(CuTest *); void test_cil_resolve_levelrange_namedlvl_low_neg(CuTest *); void test_cil_resolve_levelrange_namedlvl_high_neg(CuTest *); void test_cil_resolve_levelrange_anonlvl(CuTest *); void test_cil_resolve_levelrange_anonlvl_low_neg(CuTest *); void test_cil_resolve_levelrange_anonlvl_high_neg(CuTest *); void test_cil_resolve_constrain(CuTest *); void test_cil_resolve_constrain_class_neg(CuTest *); void test_cil_resolve_constrain_perm_neg(CuTest *); void test_cil_resolve_constrain_perm_resolve_neg(CuTest *); void test_cil_resolve_context(CuTest *); void test_cil_resolve_context_macro(CuTest *); void test_cil_resolve_context_macro_neg(CuTest *); void test_cil_resolve_context_namedrange(CuTest *); void test_cil_resolve_context_namedrange_neg(CuTest *); void test_cil_resolve_context_macro_namedrange_anon(CuTest *); void test_cil_resolve_context_user_neg(CuTest *); void test_cil_resolve_context_role_neg(CuTest *); void test_cil_resolve_context_type_neg(CuTest *); void test_cil_resolve_context_anon_level_neg(CuTest *); void test_cil_resolve_roletransition(CuTest *); void test_cil_resolve_roletransition_srcdecl_neg(CuTest *); void test_cil_resolve_roletransition_tgtdecl_neg(CuTest *); void test_cil_resolve_roletransition_resultdecl_neg(CuTest *); void test_cil_resolve_typeattributeset_type_in_multiple_attrs(CuTest *); void test_cil_resolve_typeattributeset_multiple_excludes_with_not(CuTest *); void test_cil_resolve_typeattributeset_multiple_types_with_and(CuTest *); void test_cil_resolve_typeattributeset_using_attr(CuTest *); void test_cil_resolve_typeattributeset_name_neg(CuTest *); void test_cil_resolve_typeattributeset_undef_type_neg(CuTest *); void test_cil_resolve_typeattributeset_not(CuTest *); void test_cil_resolve_typeattributeset_undef_type_not_neg(CuTest *); void test_cil_resolve_typealias(CuTest *); void test_cil_resolve_typealias_neg(CuTest *); void test_cil_resolve_typebounds(CuTest *); void test_cil_resolve_typebounds_repeatbind_neg(CuTest *); void test_cil_resolve_typebounds_type1_neg(CuTest *); void test_cil_resolve_typebounds_type2_neg(CuTest *); void test_cil_resolve_typepermissive(CuTest *); void test_cil_resolve_typepermissive_neg(CuTest *); void test_cil_resolve_nametypetransition(CuTest *); void test_cil_resolve_nametypetransition_src_neg(CuTest *); void test_cil_resolve_nametypetransition_tgt_neg(CuTest *); void test_cil_resolve_nametypetransition_class_neg(CuTest *); void test_cil_resolve_nametypetransition_dest_neg(CuTest *); void test_cil_resolve_rangetransition(CuTest *); void test_cil_resolve_rangetransition_namedrange(CuTest *); void test_cil_resolve_rangetransition_namedrange_anon(CuTest *); void test_cil_resolve_rangetransition_namedrange_anon_neg(CuTest *); void test_cil_resolve_rangetransition_namedrange_neg(CuTest *); void test_cil_resolve_rangetransition_type1_neg(CuTest *); void test_cil_resolve_rangetransition_type2_neg(CuTest *); void test_cil_resolve_rangetransition_class_neg(CuTest *); void test_cil_resolve_rangetransition_call_level_l_anon(CuTest *); void test_cil_resolve_rangetransition_call_level_l_anon_neg(CuTest *); void test_cil_resolve_rangetransition_call_level_h_anon(CuTest *); void test_cil_resolve_rangetransition_call_level_h_anon_neg(CuTest *); void test_cil_resolve_rangetransition_level_l_neg(CuTest *); void test_cil_resolve_rangetransition_level_h_neg(CuTest *); void test_cil_resolve_rangetransition_anon_level_l(CuTest *); void test_cil_resolve_rangetransition_anon_level_l_neg(CuTest *); void test_cil_resolve_rangetransition_anon_level_h(CuTest *); void test_cil_resolve_rangetransition_anon_level_h_neg(CuTest *); void test_cil_resolve_classcommon(CuTest *); void test_cil_resolve_classcommon_no_class_neg(CuTest *); void test_cil_resolve_classcommon_neg(CuTest *); void test_cil_resolve_classcommon_no_common_neg(CuTest *); void test_cil_resolve_classmapping_named(CuTest *); void test_cil_resolve_classmapping_anon(CuTest *); void test_cil_resolve_classmapping_anon_inmacro(CuTest *); void test_cil_resolve_classmapping_anon_inmacro_neg(CuTest *); void test_cil_resolve_classmapping_named_classmapname_neg(CuTest *); void test_cil_resolve_classmapping_anon_classmapname_neg(CuTest *); void test_cil_resolve_classmapping_anon_permset_neg(CuTest *); void test_cil_resolve_classpermset_named(CuTest *); void test_cil_resolve_classpermset_named_namedpermlist(CuTest *); void test_cil_resolve_classpermset_named_permlist_neg(CuTest *); void test_cil_resolve_classpermset_named_unnamedcps_neg(CuTest *); void test_cil_resolve_classpermset_anon(CuTest *); void test_cil_resolve_classpermset_anon_namedpermlist(CuTest *); void test_cil_resolve_classpermset_anon_permlist_neg(CuTest *); void test_cil_resolve_avrule(CuTest *); void test_cil_resolve_avrule_permset(CuTest *); void test_cil_resolve_avrule_permset_neg(CuTest *); void test_cil_resolve_avrule_permset_permdne_neg(CuTest *); void test_cil_resolve_avrule_firsttype_neg(CuTest *); void test_cil_resolve_avrule_secondtype_neg(CuTest *); void test_cil_resolve_avrule_class_neg(CuTest *); void test_cil_resolve_avrule_perm_neg(CuTest *); void test_cil_resolve_type_rule_transition(CuTest *); void test_cil_resolve_type_rule_transition_srcdecl_neg(CuTest *); void test_cil_resolve_type_rule_transition_tgtdecl_neg(CuTest *); void test_cil_resolve_type_rule_transition_objdecl_neg(CuTest *); void test_cil_resolve_type_rule_transition_resultdecl_neg(CuTest *); void test_cil_resolve_type_rule_change(CuTest *); void test_cil_resolve_type_rule_change_srcdecl_neg(CuTest *); void test_cil_resolve_type_rule_change_tgtdecl_neg(CuTest *); void test_cil_resolve_type_rule_change_objdecl_neg(CuTest *); void test_cil_resolve_type_rule_change_resultdecl_neg(CuTest *); void test_cil_resolve_type_rule_member(CuTest *); void test_cil_resolve_type_rule_member_srcdecl_neg(CuTest *); void test_cil_resolve_type_rule_member_tgtdecl_neg(CuTest *); void test_cil_resolve_type_rule_member_objdecl_neg(CuTest *); void test_cil_resolve_type_rule_member_resultdecl_neg(CuTest *); void test_cil_resolve_filecon(CuTest *); void test_cil_resolve_filecon_neg(CuTest *); void test_cil_resolve_filecon_anon_context(CuTest *); void test_cil_resolve_filecon_anon_context_neg(CuTest *); void test_cil_resolve_ast_node_helper_filecon(CuTest *tc); void test_cil_resolve_ast_node_helper_filecon_neg(CuTest *tc); void test_cil_resolve_portcon(CuTest *); void test_cil_resolve_portcon_neg(CuTest *); void test_cil_resolve_portcon_anon_context(CuTest *); void test_cil_resolve_portcon_anon_context_neg(CuTest *); void test_cil_resolve_ast_node_helper_portcon(CuTest *tc); void test_cil_resolve_ast_node_helper_portcon_neg(CuTest *tc); void test_cil_resolve_genfscon(CuTest *); void test_cil_resolve_genfscon_neg(CuTest *); void test_cil_resolve_genfscon_anon_context(CuTest *); void test_cil_resolve_genfscon_anon_context_neg(CuTest *); void test_cil_resolve_ast_node_helper_genfscon(CuTest *tc); void test_cil_resolve_ast_node_helper_genfscon_neg(CuTest *tc); void test_cil_resolve_nodecon_ipv4(CuTest *); void test_cil_resolve_nodecon_ipv6(CuTest *); void test_cil_resolve_nodecon_anonipaddr_ipv4(CuTest *); void test_cil_resolve_nodecon_anonnetmask_ipv4(CuTest *); void test_cil_resolve_nodecon_anonipaddr_ipv6(CuTest *); void test_cil_resolve_nodecon_anonnetmask_ipv6(CuTest *); void test_cil_resolve_nodecon_diffipfam_neg(CuTest *); void test_cil_resolve_nodecon_context_neg(CuTest *); void test_cil_resolve_nodecon_ipaddr_neg(CuTest *); void test_cil_resolve_nodecon_netmask_neg(CuTest *); void test_cil_resolve_nodecon_anon_context(CuTest *); void test_cil_resolve_nodecon_anon_context_neg(CuTest *); void test_cil_resolve_ast_node_helper_nodecon(CuTest *tc); void test_cil_resolve_ast_node_helper_nodecon_ipaddr_neg(CuTest *tc); void test_cil_resolve_ast_node_helper_nodecon_netmask_neg(CuTest *tc); void test_cil_resolve_netifcon(CuTest *); void test_cil_resolve_netifcon_otf_neg(CuTest *); void test_cil_resolve_netifcon_interface_neg(CuTest *); void test_cil_resolve_netifcon_unnamed(CuTest *); void test_cil_resolve_netifcon_unnamed_packet_neg(CuTest *); void test_cil_resolve_netifcon_unnamed_otf_neg(CuTest *); void test_cil_resolve_ast_node_helper_netifcon(CuTest *tc); void test_cil_resolve_ast_node_helper_netifcon_neg(CuTest *tc); void test_cil_resolve_pirqcon(CuTest *); void test_cil_resolve_pirqcon_context_neg(CuTest *); void test_cil_resolve_pirqcon_anon_context(CuTest *); void test_cil_resolve_pirqcon_anon_context_neg(CuTest *); void test_cil_resolve_ast_node_helper_pirqcon(CuTest *tc); void test_cil_resolve_ast_node_helper_pirqcon_neg(CuTest *tc); void test_cil_resolve_iomemcon(CuTest *); void test_cil_resolve_iomemcon_context_neg(CuTest *); void test_cil_resolve_iomemcon_anon_context(CuTest *); void test_cil_resolve_iomemcon_anon_context_neg(CuTest *); void test_cil_resolve_ast_node_helper_iomemcon(CuTest *tc); void test_cil_resolve_ast_node_helper_iomemcon_neg(CuTest *tc); void test_cil_resolve_ioportcon(CuTest *); void test_cil_resolve_ioportcon_context_neg(CuTest *); void test_cil_resolve_ioportcon_anon_context(CuTest *); void test_cil_resolve_ioportcon_anon_context_neg(CuTest *); void test_cil_resolve_ast_node_helper_ioportcon(CuTest *tc); void test_cil_resolve_ast_node_helper_ioportcon_neg(CuTest *tc); void test_cil_resolve_pcidevicecon(CuTest *); void test_cil_resolve_pcidevicecon_context_neg(CuTest *); void test_cil_resolve_pcidevicecon_anon_context(CuTest *); void test_cil_resolve_pcidevicecon_anon_context_neg(CuTest *); void test_cil_resolve_ast_node_helper_pcidevicecon(CuTest *tc); void test_cil_resolve_ast_node_helper_pcidevicecon_neg(CuTest *tc); void test_cil_resolve_fsuse(CuTest *); void test_cil_resolve_fsuse_neg(CuTest *); void test_cil_resolve_fsuse_anon(CuTest *); void test_cil_resolve_fsuse_anon_neg(CuTest *); void test_cil_resolve_ast_node_helper_fsuse(CuTest *tc); void test_cil_resolve_ast_node_helper_fsuse_neg(CuTest *tc); void test_cil_resolve_sidcontext(CuTest *); void test_cil_resolve_sidcontext_named_levels(CuTest *); void test_cil_resolve_sidcontext_named_context(CuTest *); void test_cil_resolve_sidcontext_named_context_wrongname_neg(CuTest *tc); void test_cil_resolve_sidcontext_named_context_invaliduser_neg(CuTest *tc); void test_cil_resolve_sidcontext_named_context_sidcontextnull_neg(CuTest *tc); void test_cil_resolve_ast_node_helper_sidcontext(CuTest *tc); void test_cil_resolve_ast_node_helper_sidcontext_neg(CuTest *tc); void test_cil_resolve_blockinherit(CuTest *); void test_cil_resolve_blockinherit_blockstrdne_neg(CuTest *); void test_cil_resolve_ast_node_helper_blockinherit(CuTest *tc); void test_cil_resolve_in_block(CuTest *); void test_cil_resolve_in_blockstrdne_neg(CuTest *); void test_cil_resolve_in_macro(CuTest *); void test_cil_resolve_in_optional(CuTest *); void test_cil_resolve_call1_noparam(CuTest *); void test_cil_resolve_call1_type(CuTest *); void test_cil_resolve_call1_role(CuTest *); void test_cil_resolve_call1_user(CuTest *); void test_cil_resolve_call1_sens(CuTest *); void test_cil_resolve_call1_cat(CuTest *); void test_cil_resolve_call1_catset(CuTest *); void test_cil_resolve_call1_catset_anon(CuTest *); void test_cil_resolve_call1_catset_anon_neg(CuTest *); void test_cil_resolve_call1_level(CuTest *); void test_cil_resolve_call1_class(CuTest *); void test_cil_resolve_call1_classmap(CuTest *); void test_cil_resolve_call1_permset(CuTest *); void test_cil_resolve_call1_permset_anon(CuTest *); void test_cil_resolve_call1_classpermset_named(CuTest *); void test_cil_resolve_call1_classpermset_anon(CuTest *); void test_cil_resolve_call1_classpermset_anon_neg(CuTest *); void test_cil_resolve_call1_level(CuTest *); void test_cil_resolve_call1_level_anon(CuTest *); void test_cil_resolve_call1_level_anon_neg(CuTest *); void test_cil_resolve_call1_ipaddr(CuTest *); void test_cil_resolve_call1_ipaddr_anon(CuTest *); void test_cil_resolve_call1_ipaddr_anon_neg(CuTest *); void test_cil_resolve_call1_unknown_neg(CuTest *); void test_cil_resolve_call1_unknowncall_neg(CuTest *); void test_cil_resolve_call1_extraargs_neg(CuTest *); void test_cil_resolve_call1_copy_dup(CuTest *); void test_cil_resolve_call1_missing_arg_neg(CuTest *); void test_cil_resolve_call1_paramsflavor_neg(CuTest *); void test_cil_resolve_call1_unknownflavor_neg(CuTest *); void test_cil_resolve_call2_type(CuTest *); void test_cil_resolve_call2_role(CuTest *); void test_cil_resolve_call2_user(CuTest *); void test_cil_resolve_call2_sens(CuTest *); void test_cil_resolve_call2_cat(CuTest *); void test_cil_resolve_call2_catset(CuTest *); void test_cil_resolve_call2_catset_anon(CuTest *); void test_cil_resolve_call2_permset(CuTest *); void test_cil_resolve_call2_permset_anon(CuTest *); void test_cil_resolve_call2_classpermset_named(CuTest *); void test_cil_resolve_call2_classpermset_anon(CuTest *); void test_cil_resolve_call2_class(CuTest *); void test_cil_resolve_call2_classmap(CuTest *); void test_cil_resolve_call2_level(CuTest *); void test_cil_resolve_call2_level_anon(CuTest *); void test_cil_resolve_call2_ipaddr(CuTest *); void test_cil_resolve_call2_ipaddr_anon(CuTest *); void test_cil_resolve_call2_unknown_neg(CuTest *); void test_cil_resolve_name_call_args(CuTest *); void test_cil_resolve_name_call_args_multipleparams(CuTest *); void test_cil_resolve_name_call_args_diffflavor(CuTest *); void test_cil_resolve_name_call_args_callnull_neg(CuTest *); void test_cil_resolve_name_call_args_namenull_neg(CuTest *); void test_cil_resolve_name_call_args_callargsnull_neg(CuTest *); void test_cil_resolve_name_call_args_name_neg(CuTest *); void test_cil_resolve_expr_stack_bools(CuTest *); void test_cil_resolve_expr_stack_tunables(CuTest *); void test_cil_resolve_expr_stack_type(CuTest *); void test_cil_resolve_expr_stack_role(CuTest *); void test_cil_resolve_expr_stack_user(CuTest *); void test_cil_resolve_expr_stack_neg(CuTest *); void test_cil_resolve_expr_stack_emptystr_neg(CuTest *); void test_cil_resolve_boolif(CuTest *); void test_cil_resolve_boolif_neg(CuTest *); void test_cil_evaluate_expr_stack_and(CuTest *); void test_cil_evaluate_expr_stack_not(CuTest *); void test_cil_evaluate_expr_stack_or(CuTest *); void test_cil_evaluate_expr_stack_xor(CuTest *); void test_cil_evaluate_expr_stack_eq(CuTest *); void test_cil_evaluate_expr_stack_neq(CuTest *); void test_cil_evaluate_expr_stack_oper1(CuTest *); void test_cil_evaluate_expr_stack_oper2(CuTest *); void test_cil_evaluate_expr_stack_neg(CuTest *); void test_cil_resolve_tunif_false(CuTest *); void test_cil_resolve_tunif_true(CuTest *); void test_cil_resolve_tunif_resolveexpr_neg(CuTest *); void test_cil_resolve_tunif_evaluateexpr_neg(CuTest *); void test_cil_resolve_userbounds(CuTest *tc); void test_cil_resolve_userbounds_exists_neg(CuTest *tc); void test_cil_resolve_userbounds_user1_neg(CuTest *tc); void test_cil_resolve_userbounds_user2_neg(CuTest *tc); void test_cil_resolve_roletype(CuTest *tc); void test_cil_resolve_roletype_type_neg(CuTest *tc); void test_cil_resolve_roletype_role_neg(CuTest *tc); void test_cil_resolve_userrole(CuTest *tc); void test_cil_resolve_userrole_user_neg(CuTest *tc); void test_cil_resolve_userrole_role_neg(CuTest *tc); void test_cil_resolve_userlevel(CuTest *tc); void test_cil_resolve_userlevel_macro(CuTest *tc); void test_cil_resolve_userlevel_macro_neg(CuTest *tc); void test_cil_resolve_userlevel_level_anon(CuTest *tc); void test_cil_resolve_userlevel_level_anon_neg(CuTest *tc); void test_cil_resolve_userlevel_user_neg(CuTest *tc); void test_cil_resolve_userlevel_level_neg(CuTest *tc); void test_cil_resolve_userrange(CuTest *tc); void test_cil_resolve_userrange_macro(CuTest *tc); void test_cil_resolve_userrange_macro_neg(CuTest *tc); void test_cil_resolve_userrange_range_anon(CuTest *tc); void test_cil_resolve_userrange_range_anon_neg(CuTest *tc); void test_cil_resolve_userrange_user_neg(CuTest *tc); void test_cil_resolve_userrange_range_neg(CuTest *tc); void test_cil_disable_children_helper_optional_enabled(CuTest *tc); void test_cil_disable_children_helper_optional_disabled(CuTest *tc); void test_cil_disable_children_helper_block(CuTest *tc); void test_cil_disable_children_helper_user(CuTest *tc); void test_cil_disable_children_helper_role(CuTest *tc); void test_cil_disable_children_helper_type(CuTest *tc); void test_cil_disable_children_helper_typealias(CuTest *tc); void test_cil_disable_children_helper_common(CuTest *tc); void test_cil_disable_children_helper_class(CuTest *tc); void test_cil_disable_children_helper_bool(CuTest *tc); void test_cil_disable_children_helper_sens(CuTest *tc); void test_cil_disable_children_helper_cat(CuTest *tc); void test_cil_disable_children_helper_catset(CuTest *tc); void test_cil_disable_children_helper_sid(CuTest *tc); void test_cil_disable_children_helper_macro(CuTest *tc); void test_cil_disable_children_helper_context(CuTest *tc); void test_cil_disable_children_helper_level(CuTest *tc); void test_cil_disable_children_helper_policycap(CuTest *tc); void test_cil_disable_children_helper_perm(CuTest *tc); void test_cil_disable_children_helper_catalias(CuTest *tc); void test_cil_disable_children_helper_sensalias(CuTest *tc); void test_cil_disable_children_helper_tunable(CuTest *tc); void test_cil_disable_children_helper_unknown(CuTest *tc); /* __cil_resolve_ast_node_helper test cases */ void test_cil_resolve_ast_node_helper_call1(CuTest *); void test_cil_resolve_ast_node_helper_call1_neg(CuTest *); void test_cil_resolve_ast_node_helper_call2(CuTest *); void test_cil_resolve_ast_node_helper_call2_neg(CuTest *); void test_cil_resolve_ast_node_helper_boolif(CuTest *); void test_cil_resolve_ast_node_helper_boolif_neg(CuTest *); void test_cil_resolve_ast_node_helper_tunif(CuTest *); void test_cil_resolve_ast_node_helper_tunif_neg(CuTest *); void test_cil_resolve_ast_node_helper_catorder(CuTest *); void test_cil_resolve_ast_node_helper_catorder_neg(CuTest *); void test_cil_resolve_ast_node_helper_dominance(CuTest *); void test_cil_resolve_ast_node_helper_dominance_neg(CuTest *); void test_cil_resolve_ast_node_helper_roleallow(CuTest *); void test_cil_resolve_ast_node_helper_roleallow_neg(CuTest *); void test_cil_resolve_ast_node_helper_rolebounds(CuTest *tc); void test_cil_resolve_ast_node_helper_rolebounds_neg(CuTest *tc); void test_cil_resolve_ast_node_helper_sensalias(CuTest *); void test_cil_resolve_ast_node_helper_sensalias_neg(CuTest *); void test_cil_resolve_ast_node_helper_catalias(CuTest *); void test_cil_resolve_ast_node_helper_catalias_neg(CuTest *); void test_cil_resolve_ast_node_helper_catset(CuTest *); void test_cil_resolve_ast_node_helper_catset_catlist_neg(CuTest *); void test_cil_resolve_ast_node_helper_level(CuTest *); void test_cil_resolve_ast_node_helper_level_neg(CuTest *); void test_cil_resolve_ast_node_helper_levelrange(CuTest *); void test_cil_resolve_ast_node_helper_levelrange_neg(CuTest *); void test_cil_resolve_ast_node_helper_constrain(CuTest *); void test_cil_resolve_ast_node_helper_constrain_neg(CuTest *); void test_cil_resolve_ast_node_helper_mlsconstrain(CuTest *); void test_cil_resolve_ast_node_helper_mlsconstrain_neg(CuTest *); void test_cil_resolve_ast_node_helper_context(CuTest *); void test_cil_resolve_ast_node_helper_context_neg(CuTest *); void test_cil_resolve_ast_node_helper_catrange(CuTest *tc); void test_cil_resolve_ast_node_helper_catrange_neg(CuTest *tc); void test_cil_resolve_ast_node_helper_senscat(CuTest *tc); void test_cil_resolve_ast_node_helper_senscat_neg(CuTest *tc); void test_cil_resolve_ast_node_helper_roletransition(CuTest *); void test_cil_resolve_ast_node_helper_roletransition_srcdecl_neg(CuTest *); void test_cil_resolve_ast_node_helper_roletransition_tgtdecl_neg(CuTest *); void test_cil_resolve_ast_node_helper_roletransition_resultdecl_neg(CuTest *); void test_cil_resolve_ast_node_helper_typeattributeset(CuTest *); void test_cil_resolve_ast_node_helper_typeattributeset_undef_type_neg(CuTest *); void test_cil_resolve_ast_node_helper_typealias(CuTest *); void test_cil_resolve_ast_node_helper_typealias_notype_neg(CuTest *); void test_cil_resolve_ast_node_helper_typebounds(CuTest *); void test_cil_resolve_ast_node_helper_typebounds_neg(CuTest *); void test_cil_resolve_ast_node_helper_typepermissive(CuTest *); void test_cil_resolve_ast_node_helper_typepermissive_neg(CuTest *); void test_cil_resolve_ast_node_helper_nametypetransition(CuTest *); void test_cil_resolve_ast_node_helper_nametypetransition_neg(CuTest *); void test_cil_resolve_ast_node_helper_rangetransition(CuTest *); void test_cil_resolve_ast_node_helper_rangetransition_neg(CuTest *); void test_cil_resolve_ast_node_helper_avrule(CuTest *); void test_cil_resolve_ast_node_helper_avrule_src_nores_neg(CuTest *); void test_cil_resolve_ast_node_helper_avrule_tgt_nores_neg(CuTest *); void test_cil_resolve_ast_node_helper_avrule_class_nores_neg(CuTest *); void test_cil_resolve_ast_node_helper_avrule_datum_null_neg(CuTest *); void test_cil_resolve_ast_node_helper_type_rule_transition(CuTest *); void test_cil_resolve_ast_node_helper_type_rule_transition_neg(CuTest *); void test_cil_resolve_ast_node_helper_type_rule_change(CuTest *); void test_cil_resolve_ast_node_helper_type_rule_change_neg(CuTest *); void test_cil_resolve_ast_node_helper_type_rule_member(CuTest *); void test_cil_resolve_ast_node_helper_type_rule_member_neg(CuTest *); void test_cil_resolve_ast_node_helper_userbounds(CuTest *tc); void test_cil_resolve_ast_node_helper_userbounds_neg(CuTest *tc); void test_cil_resolve_ast_node_helper_roletype(CuTest *tc); void test_cil_resolve_ast_node_helper_roletype_role_neg(CuTest *tc); void test_cil_resolve_ast_node_helper_roletype_type_neg(CuTest *tc); void test_cil_resolve_ast_node_helper_userrole(CuTest *tc); void test_cil_resolve_ast_node_helper_userrole_user_neg(CuTest *tc); void test_cil_resolve_ast_node_helper_userrole_role_neg(CuTest *tc); void test_cil_resolve_ast_node_helper_userlevel(CuTest *tc); void test_cil_resolve_ast_node_helper_userlevel_neg(CuTest *tc); void test_cil_resolve_ast_node_helper_userlevel(CuTest *tc); void test_cil_resolve_ast_node_helper_userlevel_neg(CuTest *tc); void test_cil_resolve_ast_node_helper_userrange(CuTest *tc); void test_cil_resolve_ast_node_helper_userrange_neg(CuTest *tc); void test_cil_resolve_ast_node_helper_classcommon(CuTest *tc); void test_cil_resolve_ast_node_helper_classcommon_neg(CuTest *tc); void test_cil_resolve_ast_node_helper_callstack(CuTest *tc); void test_cil_resolve_ast_node_helper_call(CuTest *tc); void test_cil_resolve_ast_node_helper_optional(CuTest *tc); void test_cil_resolve_ast_node_helper_macro(CuTest *tc); void test_cil_resolve_ast_node_helper_optstack(CuTest *tc); void test_cil_resolve_ast_node_helper_optstack_tunable_neg(CuTest *tc); void test_cil_resolve_ast_node_helper_optstack_macro_neg(CuTest *tc); void test_cil_resolve_ast_node_helper_nodenull_neg(CuTest *tc); void test_cil_resolve_ast_node_helper_extraargsnull_neg(CuTest *tc); void test_cil_resolve_ast_node_helper_optfailedtoresolve(CuTest *tc); #endif libsepol-3.8.1/cil/test/unit/test_cil_symtab.c000066400000000000000000000047271476211737200214160ustar00rootroot00000000000000/* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #include #include "CuTest.h" #include "test_cil_symtab.h" #include "../../src/cil_tree.h" #include "../../src/cil_symtab.h" #include "../../src/cil_internal.h" void test_cil_symtab_insert(CuTest *tc) { symtab_t *test_symtab = NULL; char* test_name = "test"; struct cil_block *test_block = malloc(sizeof(*test_block)); struct cil_tree_node *test_ast_node; cil_tree_node_init(&test_ast_node); struct cil_db *test_db; cil_db_init(&test_db); test_ast_node->parent = test_db->ast->root; test_ast_node->line = 1; cil_symtab_array_init(test_block->symtab, cil_sym_sizes[CIL_SYM_ARRAY_BLOCK]); test_block->is_abstract = 0; cil_get_symtab(test_db, test_ast_node->parent, &test_symtab, CIL_SYM_BLOCKS); int rc = cil_symtab_insert(test_symtab, (hashtab_key_t)test_name, (struct cil_symtab_datum*)test_block, test_ast_node); CuAssertIntEquals(tc, SEPOL_OK, rc); } libsepol-3.8.1/cil/test/unit/test_cil_symtab.h000066400000000000000000000033071476211737200214140ustar00rootroot00000000000000/* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #ifndef TEST_CIL_SYMTAB_H_ #define TEST_CIL_SYMTAB_H_ #include "CuTest.h" void test_cil_symtab_insert(CuTest *); #endif libsepol-3.8.1/cil/test/unit/test_cil_tree.c000066400000000000000000000054211476211737200210460ustar00rootroot00000000000000/* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #include #include "CuTest.h" #include "test_cil_tree.h" #include "../../src/cil_tree.h" void test_cil_tree_node_init(CuTest *tc) { struct cil_tree_node *test_node; cil_tree_node_init(&test_node); CuAssertPtrNotNull(tc, test_node); CuAssertPtrEquals(tc, NULL, test_node->cl_head); CuAssertPtrEquals(tc, NULL, test_node->cl_tail); CuAssertPtrEquals(tc, NULL, test_node->parent); CuAssertPtrEquals(tc, NULL, test_node->data); CuAssertPtrEquals(tc, NULL, test_node->next); CuAssertIntEquals(tc, 0, test_node->flavor); CuAssertIntEquals(tc, 0, test_node->line); free(test_node); } void test_cil_tree_init(CuTest *tc) { struct cil_tree *test_tree; int rc = cil_tree_init(&test_tree); CuAssertIntEquals(tc, SEPOL_OK, rc); CuAssertPtrNotNull(tc, test_tree); CuAssertPtrEquals(tc, NULL, test_tree->root->cl_head); CuAssertPtrEquals(tc, NULL, test_tree->root->cl_tail); CuAssertPtrEquals(tc, NULL, test_tree->root->parent); CuAssertPtrEquals(tc, NULL, test_tree->root->data); CuAssertPtrEquals(tc, NULL, test_tree->root->next); CuAssertIntEquals(tc, 0, test_tree->root->flavor); CuAssertIntEquals(tc, 0, test_tree->root->line); free(test_tree); } libsepol-3.8.1/cil/test/unit/test_cil_tree.h000066400000000000000000000033471476211737200210600ustar00rootroot00000000000000/* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #ifndef TEST_CIL_TREE_H_ #define TEST_CIL_TREE_H_ #include "CuTest.h" void test_cil_tree_node_init(CuTest *); void test_cil_tree_init(CuTest *); #endif libsepol-3.8.1/cil/test/unit/test_integration.c000066400000000000000000000061731476211737200216100ustar00rootroot00000000000000/* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #include #include "CuTest.h" #include "test_integration.h" #include #include #include #include #include void test_integration(CuTest *tc) { int status = 0, status1 = 0, status2 = 0; status = system("./secilc -M -c 24 test/integration.cil &> /dev/null"); if (WIFSIGNALED(status) && (WTERMSIG(status) == SIGINT || WTERMSIG(status) == SIGQUIT)) printf("Call to system for secilc failed.\n"); status1 = system("checkpolicy -M -c 24 -o policy.conf.24 test/policy.conf &> /dev/null"); if (WIFSIGNALED(status1) && (WTERMSIG(status1) == SIGINT || WTERMSIG(status1) == SIGQUIT)) printf("Call to checkpolicy failed.\n"); status2 = system("sediff -q policy.24 \\; policy.conf.24 &> /dev/null"); if (WIFSIGNALED(status2) && (WTERMSIG(status2) == SIGINT || WTERMSIG(status2) == SIGQUIT)) printf("Call to sediff for secilc failed.\n"); CuAssertIntEquals(tc, 1, WIFEXITED(status)); CuAssertIntEquals(tc, 0, WEXITSTATUS(status)); CuAssertIntEquals(tc, 1, WIFEXITED(status1)); CuAssertIntEquals(tc, 0, WEXITSTATUS(status1)); CuAssertIntEquals(tc, 1, WIFEXITED(status2)); CuAssertIntEquals(tc, 0, WEXITSTATUS(status2)); } void test_min_policy(CuTest *tc) { int status = 0; status = system("./secilc -M -c 24 test/policy.cil &> /dev/null"); if (WIFSIGNALED(status) && (WTERMSIG(status) == SIGINT || WTERMSIG(status) == SIGQUIT)) printf("Call to system for secilc failed.\n"); CuAssertIntEquals(tc, 1, WIFEXITED(status)); CuAssertIntEquals(tc, 0, WEXITSTATUS(status)); } libsepol-3.8.1/cil/test/unit/test_integration.h000066400000000000000000000033411476211737200216070ustar00rootroot00000000000000/* * Copyright 2011 Tresys Technology, LLC. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those * of the authors and should not be interpreted as representing official policies, * either expressed or implied, of Tresys Technology, LLC. */ #ifndef TEST_INTEGRATION_H #define TEST_INTEGRATION_H #include "CuTest.h" void test_min_policy(CuTest *); void test_integration(CuTest *); #endif libsepol-3.8.1/fuzz/000077500000000000000000000000001476211737200143445ustar00rootroot00000000000000libsepol-3.8.1/fuzz/binpolicy-fuzzer.c000066400000000000000000000047011476211737200200250ustar00rootroot00000000000000#include #include #include #include #include #include #include extern int policydb_validate(sepol_handle_t *handle, const policydb_t *p); extern int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); // set to 1 to enable more verbose libsepol logging #define VERBOSE 0 static int write_binary_policy(policydb_t *p, FILE *outfp) { struct policy_file pf; policy_file_init(&pf); pf.type = PF_USE_STDIO; pf.fp = outfp; return policydb_write(p, &pf); } int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { policydb_t policydb = {}, out = {}; sidtab_t sidtab = {}; struct policy_file pf; FILE *devnull = NULL; sepol_debug(VERBOSE); policy_file_init(&pf); pf.type = PF_USE_MEMORY; pf.data = (char *) data; pf.len = size; if (policydb_init(&policydb)) goto exit; if (policydb_read(&policydb, &pf, VERBOSE)) goto exit; if (policydb_load_isids(&policydb, &sidtab)) goto exit; if (policydb.policy_type == POLICY_KERN) { (void) policydb_optimize(&policydb); if (policydb_validate(NULL, &policydb) == -1) abort(); } if (policydb.global->branch_list) (void) check_assertions(NULL, &policydb, policydb.global->branch_list->avrules); (void) hierarchy_check_constraints(NULL, &policydb); devnull = fopen("/dev/null", "we"); if (!devnull) goto exit; if (write_binary_policy(&policydb, devnull)) abort(); if (policydb.policy_type == POLICY_KERN) { if (sepol_kernel_policydb_to_conf(devnull, &policydb)) abort(); if (sepol_kernel_policydb_to_cil(devnull, &policydb)) abort(); } else if (policydb.policy_type == POLICY_BASE) { if (link_modules(NULL, &policydb, NULL, 0, VERBOSE)) goto exit; if (policydb_init(&out)) goto exit; if (expand_module(NULL, &policydb, &out, VERBOSE, /*check_assertions=*/0)) goto exit; (void) check_assertions(NULL, &out, out.global->branch_list->avrules); (void) hierarchy_check_constraints(NULL, &out); if (write_binary_policy(&out, devnull)) abort(); if (sepol_kernel_policydb_to_conf(devnull, &out)) abort(); if (sepol_kernel_policydb_to_cil(devnull, &out)) abort(); } exit: if (devnull != NULL) fclose(devnull); policydb_destroy(&out); policydb_destroy(&policydb); sepol_sidtab_destroy(&sidtab); /* Non-zero return values are reserved for future use. */ return 0; } libsepol-3.8.1/fuzz/policy.bin000066400000000000000000000030201476211737200163300ustar00rootroot00000000000000Œÿ|ùSE Linux  @@dirblk_filechr_filelnk_fileprocess dyntransition transition fifo_filefile sock_filesys_role@@@@object_r@@ dpkg_script_t rpm_script_tsys_isidsys_user@@@@@@s0@@ defaultsens@@ sensdefault@@c0 @ @ @ @ @@@@@devpts@devtmpfs@@@libsepol-3.8.1/fuzz/secilc-fuzzer.c000066400000000000000000000034411476211737200172770ustar00rootroot00000000000000#include #include #include #include #include #include #include #include static void log_handler(__attribute__((unused)) int lvl, __attribute__((unused)) const char *msg) { /* be quiet */ } int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { enum cil_log_level log_level = CIL_ERR; struct sepol_policy_file *pf = NULL; FILE *dev_null = NULL; int target = SEPOL_TARGET_SELINUX; int disable_dontaudit = 0; int multiple_decls = 0; int disable_neverallow = 0; int preserve_tunables = 0; int policyvers = POLICYDB_VERSION_MAX; int mls = -1; int attrs_expand_generated = 0; struct cil_db *db = NULL; sepol_policydb_t *pdb = NULL; cil_set_log_level(log_level); cil_set_log_handler(log_handler); cil_db_init(&db); cil_set_disable_dontaudit(db, disable_dontaudit); cil_set_multiple_decls(db, multiple_decls); cil_set_disable_neverallow(db, disable_neverallow); cil_set_preserve_tunables(db, preserve_tunables); cil_set_mls(db, mls); cil_set_target_platform(db, target); cil_set_policy_version(db, policyvers); cil_set_attrs_expand_generated(db, attrs_expand_generated); if (cil_add_file(db, "fuzz", (const char *)data, size) != SEPOL_OK) goto exit; if (cil_compile(db) != SEPOL_OK) goto exit; if (cil_build_policydb(db, &pdb) != SEPOL_OK) goto exit; if (sepol_policydb_optimize(pdb) != SEPOL_OK) goto exit; dev_null = fopen("/dev/null", "w"); if (dev_null == NULL) goto exit; if (sepol_policy_file_create(&pf) != 0) goto exit; sepol_policy_file_set_fp(pf, dev_null); if (sepol_policydb_write(pdb, pf) != 0) goto exit; exit: if (dev_null != NULL) fclose(dev_null); cil_db_destroy(&db); sepol_policydb_free(pdb); sepol_policy_file_free(pf); return 0; } libsepol-3.8.1/include/000077500000000000000000000000001476211737200147715ustar00rootroot00000000000000libsepol-3.8.1/include/Makefile000066400000000000000000000011471476211737200164340ustar00rootroot00000000000000# Installation directories. PREFIX ?= /usr INCDIR = $(PREFIX)/include/sepol CILDIR ?= ../cil all: install: all test -d $(DESTDIR)$(INCDIR) || install -m 755 -d $(DESTDIR)$(INCDIR) test -d $(DESTDIR)$(INCDIR)/policydb || install -m 755 -d $(DESTDIR)$(INCDIR)/policydb test -d $(DESTDIR)$(INCDIR)/cil || install -m 755 -d $(DESTDIR)$(INCDIR)/cil install -m 644 $(wildcard sepol/*.h) $(DESTDIR)$(INCDIR) install -m 644 $(wildcard sepol/policydb/*.h) $(DESTDIR)$(INCDIR)/policydb install -m 644 $(wildcard $(CILDIR)/include/cil/*.h) $(DESTDIR)$(INCDIR)/cil indent: ../../scripts/Lindent $(wildcard sepol/*.h) libsepol-3.8.1/include/sepol/000077500000000000000000000000001476211737200161135ustar00rootroot00000000000000libsepol-3.8.1/include/sepol/boolean_record.h000066400000000000000000000030171476211737200212420ustar00rootroot00000000000000#ifndef _SEPOL_BOOLEAN_RECORD_H_ #define _SEPOL_BOOLEAN_RECORD_H_ #include #include #ifdef __cplusplus extern "C" { #endif struct sepol_bool; struct sepol_bool_key; typedef struct sepol_bool sepol_bool_t; typedef struct sepol_bool_key sepol_bool_key_t; /* Key */ extern int sepol_bool_key_create(sepol_handle_t * handle, const char *name, sepol_bool_key_t ** key); extern void sepol_bool_key_unpack(const sepol_bool_key_t * key, const char **name); extern int sepol_bool_key_extract(sepol_handle_t * handle, const sepol_bool_t * boolean, sepol_bool_key_t ** key_ptr); extern void sepol_bool_key_free(sepol_bool_key_t * key); extern int sepol_bool_compare(const sepol_bool_t * boolean, const sepol_bool_key_t * key); extern int sepol_bool_compare2(const sepol_bool_t * boolean, const sepol_bool_t * boolean2); /* Name */ extern const char *sepol_bool_get_name(const sepol_bool_t * boolean); extern int sepol_bool_set_name(sepol_handle_t * handle, sepol_bool_t * boolean, const char *name); /* Value */ extern int sepol_bool_get_value(const sepol_bool_t * boolean); extern void sepol_bool_set_value(sepol_bool_t * boolean, int value); /* Create/Clone/Destroy */ extern int sepol_bool_create(sepol_handle_t * handle, sepol_bool_t ** bool_ptr); extern int sepol_bool_clone(sepol_handle_t * handle, const sepol_bool_t * boolean, sepol_bool_t ** bool_ptr); extern void sepol_bool_free(sepol_bool_t * boolean); #ifdef __cplusplus } #endif #endif libsepol-3.8.1/include/sepol/booleans.h000066400000000000000000000024571476211737200200760ustar00rootroot00000000000000#ifndef _SEPOL_BOOLEANS_H_ #define _SEPOL_BOOLEANS_H_ #include #include #include #include #ifdef __cplusplus extern "C" { #endif /* Set the specified boolean */ extern int sepol_bool_set(sepol_handle_t * handle, sepol_policydb_t * policydb, const sepol_bool_key_t * key, const sepol_bool_t * data); /* Return the number of booleans */ extern int sepol_bool_count(sepol_handle_t * handle, const sepol_policydb_t * p, unsigned int *response); /* Check if the specified boolean exists */ extern int sepol_bool_exists(sepol_handle_t * handle, const sepol_policydb_t * policydb, const sepol_bool_key_t * key, int *response); /* Query a boolean - returns the boolean, or NULL if not found */ extern int sepol_bool_query(sepol_handle_t * handle, const sepol_policydb_t * p, const sepol_bool_key_t * key, sepol_bool_t ** response); /* Iterate the booleans * The handler may return: * -1 to signal an error condition, * 1 to signal successful exit * 0 to signal continue */ extern int sepol_bool_iterate(sepol_handle_t * handle, const sepol_policydb_t * policydb, int (*fn) (const sepol_bool_t * boolean, void *fn_arg), void *arg); #ifdef __cplusplus } #endif #endif libsepol-3.8.1/include/sepol/context.h000066400000000000000000000013601476211737200177500ustar00rootroot00000000000000#ifndef _SEPOL_CONTEXT_H_ #define _SEPOL_CONTEXT_H_ #include #include #include #ifdef __cplusplus extern "C" { #endif /* -- Deprecated -- */ extern int sepol_check_context(const char *context); /* -- End deprecated -- */ extern int sepol_context_check(sepol_handle_t * handle, const sepol_policydb_t * policydb, const sepol_context_t * context); extern int sepol_mls_contains(sepol_handle_t * handle, const sepol_policydb_t * policydb, const char *mls1, const char *mls2, int *response); extern int sepol_mls_check(sepol_handle_t * handle, const sepol_policydb_t * policydb, const char *mls); #ifdef __cplusplus } #endif #endif libsepol-3.8.1/include/sepol/context_record.h000066400000000000000000000032061476211737200213070ustar00rootroot00000000000000#ifndef _SEPOL_CONTEXT_RECORD_H_ #define _SEPOL_CONTEXT_RECORD_H_ #include #ifdef __cplusplus extern "C" { #endif struct sepol_context; typedef struct sepol_context sepol_context_t; /* We don't need a key, because the context is never stored * in a data collection by itself */ /* User */ extern const char *sepol_context_get_user(const sepol_context_t * con); extern int sepol_context_set_user(sepol_handle_t * handle, sepol_context_t * con, const char *user); /* Role */ extern const char *sepol_context_get_role(const sepol_context_t * con); extern int sepol_context_set_role(sepol_handle_t * handle, sepol_context_t * con, const char *role); /* Type */ extern const char *sepol_context_get_type(const sepol_context_t * con); extern int sepol_context_set_type(sepol_handle_t * handle, sepol_context_t * con, const char *type); /* MLS */ extern const char *sepol_context_get_mls(const sepol_context_t * con); extern int sepol_context_set_mls(sepol_handle_t * handle, sepol_context_t * con, const char *mls_range); /* Create/Clone/Destroy */ extern int sepol_context_create(sepol_handle_t * handle, sepol_context_t ** con_ptr); extern int sepol_context_clone(sepol_handle_t * handle, const sepol_context_t * con, sepol_context_t ** con_ptr); extern void sepol_context_free(sepol_context_t * con); /* Parse to/from string */ extern int sepol_context_from_string(sepol_handle_t * handle, const char *str, sepol_context_t ** con); extern int sepol_context_to_string(sepol_handle_t * handle, const sepol_context_t * con, char **str_ptr); #ifdef __cplusplus } #endif #endif libsepol-3.8.1/include/sepol/debug.h000066400000000000000000000017171476211737200173600ustar00rootroot00000000000000#ifndef _SEPOL_DEBUG_H_ #define _SEPOL_DEBUG_H_ #include #ifdef __cplusplus extern "C" { #endif /* Deprecated */ extern void sepol_debug(int on); /* End deprecated */ #define SEPOL_MSG_ERR 1 #define SEPOL_MSG_WARN 2 #define SEPOL_MSG_INFO 3 extern int sepol_msg_get_level(sepol_handle_t * handle); extern const char *sepol_msg_get_channel(sepol_handle_t * handle); extern const char *sepol_msg_get_fname(sepol_handle_t * handle); /* Set the messaging callback. * By the default, the callback will print * the message on standard output, in a * particular format. Passing NULL here * indicates that messaging should be suppressed */ extern void sepol_msg_set_callback(sepol_handle_t * handle, #ifdef __GNUC__ __attribute__ ((format(printf, 3, 4))) #endif void (*msg_callback) (void *varg, sepol_handle_t * handle, const char *fmt, ...), void *msg_callback_arg); #ifdef __cplusplus } #endif #endif libsepol-3.8.1/include/sepol/errcodes.h000066400000000000000000000014721476211737200200760ustar00rootroot00000000000000/* Author: Karl MacMillan */ #ifndef __sepol_errno_h__ #define __sepol_errno_h__ #include #ifdef __cplusplus extern "C" { #endif #define SEPOL_OK 0 /* These first error codes are defined for compatibility with * previous version of libsepol. In the future, custom error * codes that don't map to system error codes should be defined * outside of the range of system error codes. */ #define SEPOL_ERR (-1) #define SEPOL_ENOTSUP (-2) /* feature not supported in module language */ #define SEPOL_EREQ (-3) /* requirements not met */ /* Error codes that map to system error codes */ #define SEPOL_ENOMEM (-ENOMEM) #define SEPOL_EEXIST (-EEXIST) #define SEPOL_ENOENT (-ENOENT) #ifdef __cplusplus } #endif #endif libsepol-3.8.1/include/sepol/handle.h000066400000000000000000000025611476211737200175230ustar00rootroot00000000000000#ifndef _SEPOL_HANDLE_H_ #define _SEPOL_HANDLE_H_ #ifdef __cplusplus extern "C" { #endif struct sepol_handle; typedef struct sepol_handle sepol_handle_t; /* Create and return a sepol handle. */ sepol_handle_t *sepol_handle_create(void); /* Get whether or not dontaudits will be disabled, same values as * specified by set_disable_dontaudit. This value reflects the state * your system will be set to upon commit, not necessarily its * current state.*/ int sepol_get_disable_dontaudit(sepol_handle_t * sh); /* Set whether or not to disable dontaudits, 0 is default and does * not disable dontaudits, 1 disables them */ void sepol_set_disable_dontaudit(sepol_handle_t * sh, int disable_dontaudit); /* Set whether module_expand() should consume the base policy passed in. * This should reduce the amount of memory required to expand the policy. */ void sepol_set_expand_consume_base(sepol_handle_t * sh, int consume_base); /* Destroy a sepol handle. */ void sepol_handle_destroy(sepol_handle_t *); /* Get whether or not needless unused branch of tunables would be preserved */ int sepol_get_preserve_tunables(sepol_handle_t * sh); /* Set whether or not to preserve the needless unused branch of tunables, * 0 is default and discard such branch, 1 preserves them */ void sepol_set_preserve_tunables(sepol_handle_t * sh, int preserve_tunables); #ifdef __cplusplus } #endif #endif libsepol-3.8.1/include/sepol/ibendport_record.h000066400000000000000000000042061476211737200216120ustar00rootroot00000000000000#ifndef _SEPOL_IBENDPORT_RECORD_H_ #define _SEPOL_IBENDPORT_RECORD_H_ #include #include #include #ifdef __cplusplus extern "C" { #endif struct sepol_ibendport; struct sepol_ibendport_key; typedef struct sepol_ibendport sepol_ibendport_t; typedef struct sepol_ibendport_key sepol_ibendport_key_t; extern int sepol_ibendport_compare(const sepol_ibendport_t *ibendport, const sepol_ibendport_key_t *key); extern int sepol_ibendport_compare2(const sepol_ibendport_t *ibendport, const sepol_ibendport_t *ibendport2); extern int sepol_ibendport_key_create(sepol_handle_t *handle, const char *ibdev_name, int port, sepol_ibendport_key_t **key_ptr); extern void sepol_ibendport_key_unpack(const sepol_ibendport_key_t *key, const char **ibdev_name, int *port); extern int sepol_ibendport_alloc_ibdev_name(sepol_handle_t *handle, char **ibdev_name); extern int sepol_ibendport_key_extract(sepol_handle_t *handle, const sepol_ibendport_t *ibendport, sepol_ibendport_key_t **key_ptr); extern void sepol_ibendport_key_free(sepol_ibendport_key_t *key); extern void sepol_ibendport_set_port(sepol_ibendport_t *ibendport, int port); extern int sepol_ibendport_get_port(const sepol_ibendport_t *ibendport); extern int sepol_ibendport_get_ibdev_name(sepol_handle_t *handle, const sepol_ibendport_t *ibendport, char **ibdev_name); extern int sepol_ibendport_set_ibdev_name(sepol_handle_t *handle, sepol_ibendport_t *ibendport, const char *ibdev_name); extern sepol_context_t *sepol_ibendport_get_con(const sepol_ibendport_t *ibendport); extern int sepol_ibendport_set_con(sepol_handle_t *handle, sepol_ibendport_t *ibendport, sepol_context_t *con); extern int sepol_ibendport_create(sepol_handle_t *handle, sepol_ibendport_t **ibendport_ptr); extern int sepol_ibendport_clone(sepol_handle_t *handle, const sepol_ibendport_t *ibendport, sepol_ibendport_t **ibendport_ptr); extern void sepol_ibendport_free(sepol_ibendport_t *ibendport); #ifdef __cplusplus } #endif #endif libsepol-3.8.1/include/sepol/ibendports.h000066400000000000000000000025531476211737200204420ustar00rootroot00000000000000#ifndef _SEPOL_IBENDPORTS_H_ #define _SEPOL_IBENDPORTS_H_ #include #include #include #ifdef __cplusplus extern "C" { #endif /* Return the number of ibendports */ extern int sepol_ibendport_count(sepol_handle_t *handle, const sepol_policydb_t *p, unsigned int *response); /* Check if a ibendport exists */ extern int sepol_ibendport_exists(sepol_handle_t *handle, const sepol_policydb_t *policydb, const sepol_ibendport_key_t *key, int *response); /* Query a ibendport - returns the ibendport, or NULL if not found */ extern int sepol_ibendport_query(sepol_handle_t *handle, const sepol_policydb_t *policydb, const sepol_ibendport_key_t *key, sepol_ibendport_t **response); /* Modify a ibendport, or add it, if the key is not found */ extern int sepol_ibendport_modify(sepol_handle_t *handle, sepol_policydb_t *policydb, const sepol_ibendport_key_t *key, const sepol_ibendport_t *data); /* Iterate the ibendports * The handler may return: * -1 to signal an error condition, * 1 to signal successful exit * 0 to signal continue */ extern int sepol_ibendport_iterate(sepol_handle_t *handle, const sepol_policydb_t *policydb, int (*fn)(const sepol_ibendport_t *ibendport, void *fn_arg), void *arg); #ifdef __cplusplus } #endif #endif libsepol-3.8.1/include/sepol/ibpkey_record.h000066400000000000000000000043751476211737200211160ustar00rootroot00000000000000#ifndef _SEPOL_IBPKEY_RECORD_H_ #define _SEPOL_IBPKEY_RECORD_H_ #include #include #include #include #define INET6_ADDRLEN 16 #ifdef __cplusplus extern "C" { #endif struct sepol_ibpkey; struct sepol_ibpkey_key; typedef struct sepol_ibpkey sepol_ibpkey_t; typedef struct sepol_ibpkey_key sepol_ibpkey_key_t; extern int sepol_ibpkey_compare(const sepol_ibpkey_t *ibpkey, const sepol_ibpkey_key_t *key); extern int sepol_ibpkey_compare2(const sepol_ibpkey_t *ibpkey, const sepol_ibpkey_t *ibpkey2); extern int sepol_ibpkey_key_create(sepol_handle_t *handle, const char *subnet_prefix, int low, int high, sepol_ibpkey_key_t **key_ptr); extern void sepol_ibpkey_key_unpack(const sepol_ibpkey_key_t *key, uint64_t *subnet_prefix, int *low, int *high); extern int sepol_ibpkey_key_extract(sepol_handle_t *handle, const sepol_ibpkey_t *ibpkey, sepol_ibpkey_key_t **key_ptr); extern void sepol_ibpkey_key_free(sepol_ibpkey_key_t *key); extern int sepol_ibpkey_get_low(const sepol_ibpkey_t *ibpkey); extern int sepol_ibpkey_get_high(const sepol_ibpkey_t *ibpkey); extern void sepol_ibpkey_set_pkey(sepol_ibpkey_t *ibpkey, int pkey_num); extern void sepol_ibpkey_set_range(sepol_ibpkey_t *ibpkey, int low, int high); extern int sepol_ibpkey_get_subnet_prefix(sepol_handle_t *handle, const sepol_ibpkey_t *ibpkey, char **subnet_prefix); extern uint64_t sepol_ibpkey_get_subnet_prefix_bytes(const sepol_ibpkey_t *ibpkey); extern int sepol_ibpkey_set_subnet_prefix(sepol_handle_t *handle, sepol_ibpkey_t *ibpkey, const char *subnet_prefix); extern void sepol_ibpkey_set_subnet_prefix_bytes(sepol_ibpkey_t *ibpkey, uint64_t subnet_prefix); extern sepol_context_t *sepol_ibpkey_get_con(const sepol_ibpkey_t *ibpkey); extern int sepol_ibpkey_set_con(sepol_handle_t *handle, sepol_ibpkey_t *ibpkey, sepol_context_t *con); extern int sepol_ibpkey_create(sepol_handle_t *handle, sepol_ibpkey_t **ibpkey_ptr); extern int sepol_ibpkey_clone(sepol_handle_t *handle, const sepol_ibpkey_t *ibpkey, sepol_ibpkey_t **ibpkey_ptr); extern void sepol_ibpkey_free(sepol_ibpkey_t *ibpkey); #ifdef __cplusplus } #endif #endif libsepol-3.8.1/include/sepol/ibpkeys.h000066400000000000000000000025031476211737200177320ustar00rootroot00000000000000#ifndef _SEPOL_IBPKEYS_H_ #define _SEPOL_IBPKEYS_H_ #include #include #include #ifdef __cplusplus extern "C" { #endif /* Return the number of ibpkeys */ extern int sepol_ibpkey_count(sepol_handle_t *handle, const sepol_policydb_t *p, unsigned int *response); /* Check if a ibpkey exists */ extern int sepol_ibpkey_exists(sepol_handle_t *handle, const sepol_policydb_t *policydb, const sepol_ibpkey_key_t *key, int *response); /* Query a ibpkey - returns the ibpkey, or NULL if not found */ extern int sepol_ibpkey_query(sepol_handle_t *handle, const sepol_policydb_t *policydb, const sepol_ibpkey_key_t *key, sepol_ibpkey_t **response); /* Modify a ibpkey, or add it, if the key is not found */ extern int sepol_ibpkey_modify(sepol_handle_t *handle, sepol_policydb_t *policydb, const sepol_ibpkey_key_t *key, const sepol_ibpkey_t *data); /* Iterate the ibpkeys * The handler may return: * -1 to signal an error condition, * 1 to signal successful exit * 0 to signal continue */ extern int sepol_ibpkey_iterate(sepol_handle_t *handle, const sepol_policydb_t *policydb, int (*fn)(const sepol_ibpkey_t *ibpkey, void *fn_arg), void *arg); #ifdef __cplusplus } #endif #endif libsepol-3.8.1/include/sepol/iface_record.h000066400000000000000000000034601476211737200206740ustar00rootroot00000000000000#ifndef _SEPOL_IFACE_RECORD_H_ #define _SEPOL_IFACE_RECORD_H_ #include #include #ifdef __cplusplus extern "C" { #endif struct sepol_iface; struct sepol_iface_key; typedef struct sepol_iface sepol_iface_t; typedef struct sepol_iface_key sepol_iface_key_t; /* Key */ extern int sepol_iface_compare(const sepol_iface_t * iface, const sepol_iface_key_t * key); extern int sepol_iface_compare2(const sepol_iface_t * iface, const sepol_iface_t * iface2); extern void sepol_iface_key_unpack(const sepol_iface_key_t * key, const char **name); extern int sepol_iface_key_create(sepol_handle_t * handle, const char *name, sepol_iface_key_t ** key_ptr); extern int sepol_iface_key_extract(sepol_handle_t * handle, const sepol_iface_t * iface, sepol_iface_key_t ** key_ptr); extern void sepol_iface_key_free(sepol_iface_key_t * key); /* Name */ extern const char *sepol_iface_get_name(const sepol_iface_t * iface); extern int sepol_iface_set_name(sepol_handle_t * handle, sepol_iface_t * iface, const char *name); /* Context */ extern sepol_context_t *sepol_iface_get_ifcon(const sepol_iface_t * iface); extern int sepol_iface_set_ifcon(sepol_handle_t * handle, sepol_iface_t * iface, sepol_context_t * con); extern sepol_context_t *sepol_iface_get_msgcon(const sepol_iface_t * iface); extern int sepol_iface_set_msgcon(sepol_handle_t * handle, sepol_iface_t * iface, sepol_context_t * con); /* Create/Clone/Destroy */ extern int sepol_iface_create(sepol_handle_t * handle, sepol_iface_t ** iface_ptr); extern int sepol_iface_clone(sepol_handle_t * handle, const sepol_iface_t * iface, sepol_iface_t ** iface_ptr); extern void sepol_iface_free(sepol_iface_t * iface); #ifdef __cplusplus } #endif #endif libsepol-3.8.1/include/sepol/interfaces.h000066400000000000000000000025731476211737200204160ustar00rootroot00000000000000#ifndef __SEPOL_INTERFACES_H_ #define __SEPOL_INTERFACES_H_ #include #include #include #ifdef __cplusplus extern "C" { #endif /* Return the number of interfaces */ extern int sepol_iface_count(sepol_handle_t * handle, const sepol_policydb_t * policydb, unsigned int *response); /* Check if an interface exists */ extern int sepol_iface_exists(sepol_handle_t * handle, const sepol_policydb_t * policydb, const sepol_iface_key_t * key, int *response); /* Query an interface - returns the interface, * or NULL if not found */ extern int sepol_iface_query(sepol_handle_t * handle, const sepol_policydb_t * policydb, const sepol_iface_key_t * key, sepol_iface_t ** response); /* Modify an interface, or add it, if the key * is not found */ extern int sepol_iface_modify(sepol_handle_t * handle, sepol_policydb_t * policydb, const sepol_iface_key_t * key, const sepol_iface_t * data); /* Iterate the interfaces * The handler may return: * -1 to signal an error condition, * 1 to signal successful exit * 0 to signal continue */ extern int sepol_iface_iterate(sepol_handle_t * handle, const sepol_policydb_t * policydb, int (*fn) (const sepol_iface_t * iface, void *fn_arg), void *arg); #ifdef __cplusplus } #endif #endif libsepol-3.8.1/include/sepol/kernel_to_cil.h000066400000000000000000000001751476211737200211000ustar00rootroot00000000000000#include #include int sepol_kernel_policydb_to_cil(FILE *fp, struct policydb *pdb); libsepol-3.8.1/include/sepol/kernel_to_conf.h000066400000000000000000000001761476211737200212570ustar00rootroot00000000000000#include #include int sepol_kernel_policydb_to_conf(FILE *fp, struct policydb *pdb); libsepol-3.8.1/include/sepol/module.h000066400000000000000000000051701476211737200175540ustar00rootroot00000000000000#ifndef _SEPOL_MODULE_H_ #define _SEPOL_MODULE_H_ #include #include #include #include #include #ifdef __cplusplus extern "C" { #endif struct sepol_module_package; typedef struct sepol_module_package sepol_module_package_t; /* Module package public interfaces. */ extern int sepol_module_package_create(sepol_module_package_t ** p); extern void sepol_module_package_free(sepol_module_package_t * p); extern char *sepol_module_package_get_file_contexts(sepol_module_package_t * p); extern size_t sepol_module_package_get_file_contexts_len(sepol_module_package_t * p); extern int sepol_module_package_set_file_contexts(sepol_module_package_t * p, char *data, size_t len); extern char *sepol_module_package_get_seusers(sepol_module_package_t * p); extern size_t sepol_module_package_get_seusers_len(sepol_module_package_t * p); extern int sepol_module_package_set_seusers(sepol_module_package_t * p, char *data, size_t len); extern char *sepol_module_package_get_user_extra(sepol_module_package_t * p); extern size_t sepol_module_package_get_user_extra_len(sepol_module_package_t * p); extern int sepol_module_package_set_user_extra(sepol_module_package_t * p, char *data, size_t len); extern char *sepol_module_package_get_netfilter_contexts(sepol_module_package_t * p); extern size_t sepol_module_package_get_netfilter_contexts_len(sepol_module_package_t * p); extern int sepol_module_package_set_netfilter_contexts(sepol_module_package_t * p, char *data, size_t len); extern sepol_policydb_t *sepol_module_package_get_policy(sepol_module_package_t * p); extern int sepol_link_packages(sepol_handle_t * handle, sepol_module_package_t * base, sepol_module_package_t ** modules, int num_modules, int verbose); extern int sepol_module_package_read(sepol_module_package_t * mod, struct sepol_policy_file *file, int verbose); extern int sepol_module_package_info(struct sepol_policy_file *file, int *type, char **name, char **version); extern int sepol_module_package_write(sepol_module_package_t * p, struct sepol_policy_file *file); /* Module linking/expanding public interfaces. */ extern int sepol_link_modules(sepol_handle_t * handle, sepol_policydb_t * base, sepol_policydb_t ** modules, size_t len, int verbose); extern int sepol_expand_module(sepol_handle_t * handle, sepol_policydb_t * base, sepol_policydb_t * out, int verbose, int check); #ifdef __cplusplus } #endif #endif libsepol-3.8.1/include/sepol/module_to_cil.h000066400000000000000000000005111476211737200210770ustar00rootroot00000000000000#include #include #include int sepol_module_policydb_to_cil(FILE *fp, struct policydb *pdb, int linked); int sepol_module_package_to_cil(FILE *fp, struct sepol_module_package *mod_pkg); int sepol_ppfile_to_module_package(FILE *fp, struct sepol_module_package **mod_pkg); libsepol-3.8.1/include/sepol/node_record.h000066400000000000000000000053661476211737200205610ustar00rootroot00000000000000#ifndef _SEPOL_NODE_RECORD_H_ #define _SEPOL_NODE_RECORD_H_ #include #include #include #ifdef __cplusplus extern "C" { #endif struct sepol_node; struct sepol_node_key; typedef struct sepol_node sepol_node_t; typedef struct sepol_node_key sepol_node_key_t; #define SEPOL_PROTO_IP4 0 #define SEPOL_PROTO_IP6 1 /* Key */ extern int sepol_node_compare(const sepol_node_t * node, const sepol_node_key_t * key); extern int sepol_node_compare2(const sepol_node_t * node, const sepol_node_t * node2); extern int sepol_node_key_create(sepol_handle_t * handle, const char *addr, const char *mask, int proto, sepol_node_key_t ** key_ptr); extern void sepol_node_key_unpack(const sepol_node_key_t * key, const char **addr, const char **mask, int *proto); extern int sepol_node_key_extract(sepol_handle_t * handle, const sepol_node_t * node, sepol_node_key_t ** key_ptr); extern void sepol_node_key_free(sepol_node_key_t * key); /* Address */ extern int sepol_node_get_addr(sepol_handle_t * handle, const sepol_node_t * node, char **addr); extern int sepol_node_get_addr_bytes(sepol_handle_t * handle, const sepol_node_t * node, char **addr, size_t * addr_sz); extern int sepol_node_set_addr(sepol_handle_t * handle, sepol_node_t * node, int proto, const char *addr); extern int sepol_node_set_addr_bytes(sepol_handle_t * handle, sepol_node_t * node, const char *addr, size_t addr_sz); /* Netmask */ extern int sepol_node_get_mask(sepol_handle_t * handle, const sepol_node_t * node, char **mask); extern int sepol_node_get_mask_bytes(sepol_handle_t * handle, const sepol_node_t * node, char **mask, size_t * mask_sz); extern int sepol_node_set_mask(sepol_handle_t * handle, sepol_node_t * node, int proto, const char *mask); extern int sepol_node_set_mask_bytes(sepol_handle_t * handle, sepol_node_t * node, const char *mask, size_t mask_sz); /* Protocol */ extern int sepol_node_get_proto(const sepol_node_t * node); extern void sepol_node_set_proto(sepol_node_t * node, int proto); extern const char *sepol_node_get_proto_str(int proto); /* Context */ extern sepol_context_t *sepol_node_get_con(const sepol_node_t * node); extern int sepol_node_set_con(sepol_handle_t * handle, sepol_node_t * node, sepol_context_t * con); /* Create/Clone/Destroy */ extern int sepol_node_create(sepol_handle_t * handle, sepol_node_t ** node_ptr); extern int sepol_node_clone(sepol_handle_t * handle, const sepol_node_t * node, sepol_node_t ** node_ptr); extern void sepol_node_free(sepol_node_t * node); #ifdef __cplusplus } #endif #endif libsepol-3.8.1/include/sepol/nodes.h000066400000000000000000000024401476211737200173740ustar00rootroot00000000000000#ifndef _SEPOL_NODES_H_ #define _SEPOL_NODES_H_ #include #include #include #ifdef __cplusplus extern "C" { #endif /* Return the number of nodes */ extern int sepol_node_count(sepol_handle_t * handle, const sepol_policydb_t * p, unsigned int *response); /* Check if a node exists */ extern int sepol_node_exists(sepol_handle_t * handle, const sepol_policydb_t * policydb, const sepol_node_key_t * key, int *response); /* Query a node - returns the node, or NULL if not found */ extern int sepol_node_query(sepol_handle_t * handle, const sepol_policydb_t * policydb, const sepol_node_key_t * key, sepol_node_t ** response); /* Modify a node, or add it, if the key is not found */ extern int sepol_node_modify(sepol_handle_t * handle, sepol_policydb_t * policydb, const sepol_node_key_t * key, const sepol_node_t * data); /* Iterate the nodes * The handler may return: * -1 to signal an error condition, * 1 to signal successful exit * 0 to signal continue */ extern int sepol_node_iterate(sepol_handle_t * handle, const sepol_policydb_t * policydb, int (*fn) (const sepol_node_t * node, void *fn_arg), void *arg); #ifdef __cplusplus } #endif #endif libsepol-3.8.1/include/sepol/policydb.h000066400000000000000000000113151476211737200200720ustar00rootroot00000000000000#ifndef _SEPOL_POLICYDB_H_ #define _SEPOL_POLICYDB_H_ #include #include #include #ifdef __cplusplus extern "C" { #endif struct sepol_policy_file; typedef struct sepol_policy_file sepol_policy_file_t; struct sepol_policydb; typedef struct sepol_policydb sepol_policydb_t; /* Policy file public interfaces. */ /* Create and free memory associated with a policy file. */ extern int sepol_policy_file_create(sepol_policy_file_t ** pf); extern void sepol_policy_file_free(sepol_policy_file_t * pf); /* * Set the policy file to represent a binary policy memory image. * Subsequent operations using the policy file will read and write * the image located at the specified address with the specified length. * If 'len' is 0, then merely compute the necessary length upon * subsequent policydb write operations in order to determine the * necessary buffer size to allocate. */ extern void sepol_policy_file_set_mem(sepol_policy_file_t * pf, char *data, size_t len); /* * Get the size of the buffer needed to store a policydb write * previously done on this policy file. */ extern int sepol_policy_file_get_len(sepol_policy_file_t * pf, size_t * len); /* * Set the policy file to represent a FILE. * Subsequent operations using the policy file will read and write * to the FILE. */ extern void sepol_policy_file_set_fp(sepol_policy_file_t * pf, FILE * fp); /* * Associate a handle with a policy file, for use in * error reporting from subsequent calls that take the * policy file as an argument. */ extern void sepol_policy_file_set_handle(sepol_policy_file_t * pf, sepol_handle_t * handle); /* Policydb public interfaces. */ /* Create and free memory associated with a policydb. */ extern int sepol_policydb_create(sepol_policydb_t ** p); extern void sepol_policydb_free(sepol_policydb_t * p); /* Legal types of policies that the policydb can represent. */ #define SEPOL_POLICY_KERN 0 #define SEPOL_POLICY_BASE 1 #define SEPOL_POLICY_MOD 2 /* * Range of policy versions for the kernel policy type supported * by this library. */ extern int sepol_policy_kern_vers_min(void); extern int sepol_policy_kern_vers_max(void); /* * Set the policy type as specified, and automatically initialize the * policy version accordingly to the maximum version supported for the * policy type. * Returns -1 if the policy type is not legal. */ extern int sepol_policydb_set_typevers(sepol_policydb_t * p, unsigned int type); /* * Set the policy version to a different value. * Returns -1 if the policy version is not in the supported range for * the (previously set) policy type. */ extern int sepol_policydb_set_vers(sepol_policydb_t * p, unsigned int vers); /* Set how to handle unknown class/perms. */ #define SEPOL_DENY_UNKNOWN 0 #define SEPOL_REJECT_UNKNOWN 2 #define SEPOL_ALLOW_UNKNOWN 4 extern int sepol_policydb_set_handle_unknown(sepol_policydb_t * p, unsigned int handle_unknown); /* Set the target platform */ #define SEPOL_TARGET_SELINUX 0 #define SEPOL_TARGET_XEN 1 extern int sepol_policydb_set_target_platform(sepol_policydb_t * p, int target_platform); /* * Optimize the policy by removing redundant rules. */ extern int sepol_policydb_optimize(sepol_policydb_t * p); /* * Read a policydb from a policy file. * This automatically sets the type and version based on the * image contents. */ extern int sepol_policydb_read(sepol_policydb_t * p, sepol_policy_file_t * pf); /* * Write a policydb to a policy file. * The generated image will be in the binary format corresponding * to the policy version associated with the policydb. */ extern int sepol_policydb_write(sepol_policydb_t * p, sepol_policy_file_t * pf); /* * Extract a policydb from a binary policy memory image. * This is equivalent to sepol_policydb_read with a policy file * set to refer to memory. */ extern int sepol_policydb_from_image(sepol_handle_t * handle, void *data, size_t len, sepol_policydb_t * p); /* * Generate a binary policy memory image from a policydb. * This is equivalent to sepol_policydb_write with a policy file * set to refer to memory, but internally handles computing the * necessary length and allocating an appropriately sized memory * buffer for the caller. */ extern int sepol_policydb_to_image(sepol_handle_t * handle, sepol_policydb_t * p, void **newdata, size_t * newlen); /* * Check whether the policydb has MLS enabled. */ extern int sepol_policydb_mls_enabled(const sepol_policydb_t * p); /* * Check whether the compatibility mode for SELinux network * checks should be enabled when using this policy. */ extern int sepol_policydb_compat_net(const sepol_policydb_t * p); #ifdef __cplusplus } #endif #endif libsepol-3.8.1/include/sepol/policydb/000077500000000000000000000000001476211737200177205ustar00rootroot00000000000000libsepol-3.8.1/include/sepol/policydb/avrule_block.h000066400000000000000000000031671476211737200225500ustar00rootroot00000000000000/* Authors: Jason Tang * * Copyright (C) 2005 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _SEPOL_AVRULE_BLOCK_H_ #define _SEPOL_AVRULE_BLOCK_H_ #include #ifdef __cplusplus extern "C" { #endif extern avrule_block_t *avrule_block_create(void); extern void avrule_block_destroy(avrule_block_t * x); extern avrule_decl_t *avrule_decl_create(uint32_t decl_id); extern void avrule_decl_destroy(avrule_decl_t * x); extern void avrule_block_list_destroy(avrule_block_t * x); extern avrule_decl_t *get_avrule_decl(policydb_t * p, uint32_t decl_id); extern cond_list_t *get_decl_cond_list(policydb_t * p, avrule_decl_t * decl, cond_list_t * cond); extern int is_id_enabled(const char *id, const policydb_t * p, int symbol_table); extern int is_perm_existent(const class_datum_t *cladatum, const char *perm_id); #ifdef __cplusplus } #endif #endif libsepol-3.8.1/include/sepol/policydb/avtab.h000066400000000000000000000112721476211737200211710ustar00rootroot00000000000000 /* Author : Stephen Smalley, */ /* * Updated: Yuichi Nakamura * Tuned number of hash slots for avtab to reduce memory usage */ /* Updated: Frank Mayer and Karl MacMillan * * Added conditional policy language extensions * * Copyright (C) 2003 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* FLASK */ /* * An access vector table (avtab) is a hash table * of access vectors and transition types indexed * by a type pair and a class. An access vector * table is used to represent the type enforcement * tables. */ #ifndef _SEPOL_POLICYDB_AVTAB_H_ #define _SEPOL_POLICYDB_AVTAB_H_ #include #include #ifdef __cplusplus extern "C" { #endif typedef struct avtab_key { uint16_t source_type; uint16_t target_type; uint16_t target_class; #define AVTAB_ALLOWED 0x0001 #define AVTAB_AUDITALLOW 0x0002 #define AVTAB_AUDITDENY 0x0004 #define AVTAB_NEVERALLOW 0x0080 #define AVTAB_AV (AVTAB_ALLOWED | AVTAB_AUDITALLOW | AVTAB_AUDITDENY) #define AVTAB_TRANSITION 0x0010 #define AVTAB_MEMBER 0x0020 #define AVTAB_CHANGE 0x0040 #define AVTAB_TYPE (AVTAB_TRANSITION | AVTAB_MEMBER | AVTAB_CHANGE) #define AVTAB_XPERMS_ALLOWED 0x0100 #define AVTAB_XPERMS_AUDITALLOW 0x0200 #define AVTAB_XPERMS_DONTAUDIT 0x0400 #define AVTAB_XPERMS_NEVERALLOW 0x0800 #define AVTAB_XPERMS (AVTAB_XPERMS_ALLOWED | AVTAB_XPERMS_AUDITALLOW | AVTAB_XPERMS_DONTAUDIT) #define AVTAB_ENABLED_OLD 0x80000000 #define AVTAB_ENABLED 0x8000 /* reserved for used in cond_avtab */ uint16_t specified; /* what fields are specified */ } avtab_key_t; typedef struct avtab_extended_perms { #define AVTAB_XPERMS_IOCTLFUNCTION 0x01 #define AVTAB_XPERMS_IOCTLDRIVER 0x02 #define AVTAB_XPERMS_NLMSG 0x03 /* extension of the avtab_key specified */ uint8_t specified; uint8_t driver; uint32_t perms[8]; } avtab_extended_perms_t; typedef struct avtab_datum { uint32_t data; /* access vector or type */ avtab_extended_perms_t *xperms; } avtab_datum_t; typedef struct avtab_node *avtab_ptr_t; struct avtab_node { avtab_key_t key; avtab_datum_t datum; avtab_ptr_t next; void *parse_context; /* generic context pointer used by parser; * not saved in binary policy */ unsigned merged; /* flag for avtab_write only; not saved in binary policy */ }; typedef struct avtab { avtab_ptr_t *htable; uint32_t nel; /* number of elements */ uint32_t nslot; /* number of hash slots */ uint32_t mask; /* mask to compute hash func */ } avtab_t; extern int avtab_init(avtab_t *); extern int avtab_alloc(avtab_t *, uint32_t); extern int avtab_insert(avtab_t * h, avtab_key_t * k, avtab_datum_t * d); extern avtab_datum_t *avtab_search(avtab_t * h, avtab_key_t * k); extern void avtab_destroy(avtab_t * h); extern int avtab_map(const avtab_t * h, int (*apply) (avtab_key_t * k, avtab_datum_t * d, void *args), void *args); extern void avtab_hash_eval(avtab_t * h, char *tag); struct policy_file; extern int avtab_read_item(struct policy_file *fp, uint32_t vers, avtab_t * a, int (*insert) (avtab_t * a, avtab_key_t * k, avtab_datum_t * d, void *p), void *p); extern int avtab_read(avtab_t * a, struct policy_file *fp, uint32_t vers); extern avtab_ptr_t avtab_insert_nonunique(avtab_t * h, avtab_key_t * key, avtab_datum_t * datum); extern avtab_ptr_t avtab_insert_with_parse_context(avtab_t * h, avtab_key_t * key, avtab_datum_t * datum, void *parse_context); extern avtab_ptr_t avtab_search_node(avtab_t * h, avtab_key_t * key); extern avtab_ptr_t avtab_search_node_next(avtab_ptr_t node, int specified); #define MAX_AVTAB_HASH_BITS 20 #define MAX_AVTAB_HASH_BUCKETS (1 << MAX_AVTAB_HASH_BITS) #define MAX_AVTAB_HASH_MASK (MAX_AVTAB_HASH_BUCKETS-1) /* avtab_alloc uses one bucket per 2-4 elements, so adjust to get maximum buckets */ #define MAX_AVTAB_SIZE (MAX_AVTAB_HASH_BUCKETS << 1) #ifdef __cplusplus } #endif #endif /* _AVTAB_H_ */ /* FLASK */ libsepol-3.8.1/include/sepol/policydb/conditional.h000066400000000000000000000113651476211737200224020ustar00rootroot00000000000000/* Authors: Karl MacMillan * Frank Mayer * * Copyright (C) 2003 - 2005 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _SEPOL_POLICYDB_CONDITIONAL_H_ #define _SEPOL_POLICYDB_CONDITIONAL_H_ #include #include #include #include #ifdef __cplusplus extern "C" { #endif #define COND_EXPR_MAXDEPTH 10 /* this is the max unique bools in a conditional expression * for which we precompute all outcomes for the expression. * * NOTE - do _NOT_ use value greater than 5 because * cond_node_t->expr_pre_comp can only hold at most 32 values */ #define COND_MAX_BOOLS 5 /* * A conditional expression is a list of operators and operands * in reverse polish notation. */ typedef struct cond_expr { #define COND_BOOL 1 /* plain bool */ #define COND_NOT 2 /* !bool */ #define COND_OR 3 /* bool || bool */ #define COND_AND 4 /* bool && bool */ #define COND_XOR 5 /* bool ^ bool */ #define COND_EQ 6 /* bool == bool */ #define COND_NEQ 7 /* bool != bool */ #define COND_LAST COND_NEQ uint32_t expr_type; /* The member `boolean` was renamed from `bool` in version 3.6 */ #define COND_EXPR_T_RENAME_BOOL_BOOLEAN uint32_t boolean; struct cond_expr *next; } cond_expr_t; /* * Each cond_node_t contains a list of rules to be enabled/disabled * depending on the current value of the conditional expression. This * struct is for that list. */ typedef struct cond_av_list { avtab_ptr_t node; struct cond_av_list *next; } cond_av_list_t; /* * A cond node represents a conditional block in a policy. It * contains a conditional expression, the current state of the expression, * two lists of rules to enable/disable depending on the value of the * expression (the true list corresponds to if and the false list corresponds * to else).. */ typedef struct cond_node { int cur_state; cond_expr_t *expr; /* these true/false lists point into te_avtab when that is used */ cond_av_list_t *true_list; cond_av_list_t *false_list; /* and these are used during parsing and for modules */ avrule_t *avtrue_list; avrule_t *avfalse_list; /* these fields are not written to binary policy */ unsigned int nbools; uint32_t bool_ids[COND_MAX_BOOLS]; uint32_t expr_pre_comp; struct cond_node *next; /* a tunable conditional, calculated and used at expansion */ #define COND_NODE_FLAGS_TUNABLE UINT32_C(0x01) uint32_t flags; } cond_node_t; extern int cond_evaluate_expr(policydb_t * p, cond_expr_t * expr); extern cond_expr_t *cond_copy_expr(cond_expr_t * expr); extern int cond_expr_equal(cond_node_t * a, cond_node_t * b); extern int cond_normalize_expr(policydb_t * p, cond_node_t * cn); extern void cond_node_destroy(cond_node_t * node); extern void cond_expr_destroy(cond_expr_t * expr); extern cond_node_t *cond_node_find(policydb_t * p, cond_node_t * needle, cond_node_t * haystack, int *was_created); extern cond_node_t *cond_node_create(policydb_t * p, cond_node_t * node); extern cond_node_t *cond_node_search(policydb_t * p, cond_node_t * list, cond_node_t * cn); extern int evaluate_conds(policydb_t * p); extern avtab_datum_t *cond_av_list_search(avtab_key_t * key, cond_av_list_t * cond_list); extern void cond_av_list_destroy(cond_av_list_t * list); extern void cond_optimize_lists(cond_list_t * cl); extern int cond_policydb_init(policydb_t * p); extern void cond_policydb_destroy(policydb_t * p); extern void cond_list_destroy(cond_list_t * list); extern int cond_init_bool_indexes(policydb_t * p); extern int cond_destroy_bool(hashtab_key_t key, hashtab_datum_t datum, void *p); extern int cond_index_bool(hashtab_key_t key, hashtab_datum_t datum, void *datap); extern int cond_read_bool(policydb_t * p, hashtab_t h, struct policy_file *fp); extern int cond_read_list(policydb_t * p, cond_list_t ** list, void *fp); extern void cond_compute_av(avtab_t * ctab, avtab_key_t * key, struct sepol_av_decision *avd); #ifdef __cplusplus } #endif #endif /* _CONDITIONAL_H_ */ libsepol-3.8.1/include/sepol/policydb/constraint.h000066400000000000000000000047411476211737200222630ustar00rootroot00000000000000/* Author : Stephen Smalley, */ /* FLASK */ /* * A constraint is a condition that must be satisfied in * order for one or more permissions to be granted. * Constraints are used to impose additional restrictions * beyond the type-based rules in `te' or the role-based * transition rules in `rbac'. Constraints are typically * used to prevent a process from transitioning to a new user * identity or role unless it is in a privileged type. * Constraints are likewise typically used to prevent a * process from labeling an object with a different user * identity. */ #ifndef _SEPOL_POLICYDB_CONSTRAINT_H_ #define _SEPOL_POLICYDB_CONSTRAINT_H_ #include #include #ifdef __cplusplus extern "C" { #endif #define CEXPR_MAXDEPTH 5 struct type_set; typedef struct constraint_expr { #define CEXPR_NOT 1 /* not expr */ #define CEXPR_AND 2 /* expr and expr */ #define CEXPR_OR 3 /* expr or expr */ #define CEXPR_ATTR 4 /* attr op attr */ #define CEXPR_NAMES 5 /* attr op names */ uint32_t expr_type; /* expression type */ #define CEXPR_USER 1 /* user */ #define CEXPR_ROLE 2 /* role */ #define CEXPR_TYPE 4 /* type */ #define CEXPR_TARGET 8 /* target if set, source otherwise */ #define CEXPR_XTARGET 16 /* special 3rd target for validatetrans rule */ #define CEXPR_L1L2 32 /* low level 1 vs. low level 2 */ #define CEXPR_L1H2 64 /* low level 1 vs. high level 2 */ #define CEXPR_H1L2 128 /* high level 1 vs. low level 2 */ #define CEXPR_H1H2 256 /* high level 1 vs. high level 2 */ #define CEXPR_L1H1 512 /* low level 1 vs. high level 1 */ #define CEXPR_L2H2 1024 /* low level 2 vs. high level 2 */ uint32_t attr; /* attribute */ #define CEXPR_EQ 1 /* == or eq */ #define CEXPR_NEQ 2 /* != */ #define CEXPR_DOM 3 /* dom */ #define CEXPR_DOMBY 4 /* domby */ #define CEXPR_INCOMP 5 /* incomp */ uint32_t op; /* operator */ ebitmap_t names; /* names */ struct type_set *type_names; struct constraint_expr *next; /* next expression */ } constraint_expr_t; typedef struct constraint_node { sepol_access_vector_t permissions; /* constrained permissions */ constraint_expr_t *expr; /* constraint on permissions */ struct constraint_node *next; /* next constraint */ } constraint_node_t; extern int constraint_expr_init(constraint_expr_t * expr); extern void constraint_expr_destroy(constraint_expr_t * expr); #ifdef __cplusplus } #endif #endif /* _CONSTRAINT_H_ */ /* FLASK */ libsepol-3.8.1/include/sepol/policydb/context.h000066400000000000000000000067711476211737200215700ustar00rootroot00000000000000/* Author : Stephen Smalley, */ /* FLASK */ /* * A security context is a set of security attributes * associated with each subject and object controlled * by the security policy. Security contexts are * externally represented as variable-length strings * that can be interpreted by a user or application * with an understanding of the security policy. * Internally, the security server uses a simple * structure. This structure is private to the * security server and can be changed without affecting * clients of the security server. */ #ifndef _SEPOL_POLICYDB_CONTEXT_H_ #define _SEPOL_POLICYDB_CONTEXT_H_ #include #include #include #ifdef __cplusplus extern "C" { #endif /* * A security context consists of an authenticated user * identity, a role, a type and a MLS range. */ typedef struct context_struct { uint32_t user; uint32_t role; uint32_t type; mls_range_t range; } context_struct_t; static inline void mls_context_init(context_struct_t * c) { mls_range_init(&c->range); } static inline int mls_context_cpy(context_struct_t * dst, const context_struct_t * src) { if (mls_range_cpy(&dst->range, &src->range) < 0) return -1; return 0; } /* * Sets both levels in the MLS range of 'dst' to the low level of 'src'. */ static inline int mls_context_cpy_low(context_struct_t *dst, const context_struct_t *src) { int rc; dst->range.level[0].sens = src->range.level[0].sens; rc = ebitmap_cpy(&dst->range.level[0].cat, &src->range.level[0].cat); if (rc) goto out; dst->range.level[1].sens = src->range.level[0].sens; rc = ebitmap_cpy(&dst->range.level[1].cat, &src->range.level[0].cat); if (rc) ebitmap_destroy(&dst->range.level[0].cat); out: return rc; } /* * Sets both levels in the MLS range of 'dst' to the high level of 'src'. */ static inline int mls_context_cpy_high(context_struct_t *dst, const context_struct_t *src) { int rc; dst->range.level[0].sens = src->range.level[1].sens; rc = ebitmap_cpy(&dst->range.level[0].cat, &src->range.level[1].cat); if (rc) goto out; dst->range.level[1].sens = src->range.level[1].sens; rc = ebitmap_cpy(&dst->range.level[1].cat, &src->range.level[1].cat); if (rc) ebitmap_destroy(&dst->range.level[0].cat); out: return rc; } static inline int mls_context_glblub(context_struct_t *dst, const context_struct_t *c1, const context_struct_t *c2) { return mls_range_glblub(&dst->range, &c1->range, &c2->range); } static inline int mls_context_cmp(const context_struct_t * c1, const context_struct_t * c2) { return (mls_level_eq(&c1->range.level[0], &c2->range.level[0]) && mls_level_eq(&c1->range.level[1], &c2->range.level[1])); } static inline void mls_context_destroy(context_struct_t * c) { if (c == NULL) return; mls_range_destroy(&c->range); mls_context_init(c); } static inline void context_init(context_struct_t * c) { memset(c, 0, sizeof(*c)); } static inline int context_cpy(context_struct_t * dst, const context_struct_t * src) { dst->user = src->user; dst->role = src->role; dst->type = src->type; return mls_context_cpy(dst, src); } static inline void context_destroy(context_struct_t * c) { if (c == NULL) return; c->user = c->role = c->type = 0; mls_context_destroy(c); } static inline int context_cmp(const context_struct_t * c1, const context_struct_t * c2) { return ((c1->user == c2->user) && (c1->role == c2->role) && (c1->type == c2->type) && mls_context_cmp(c1, c2)); } #ifdef __cplusplus } #endif #endif libsepol-3.8.1/include/sepol/policydb/ebitmap.h000066400000000000000000000070141476211737200215140ustar00rootroot00000000000000/* Author : Stephen Smalley, */ /* FLASK */ /* * An extensible bitmap is a bitmap that supports an * arbitrary number of bits. Extensible bitmaps are * used to represent sets of values, such as types, * roles, categories, and classes. * * Each extensible bitmap is implemented as a linked * list of bitmap nodes, where each bitmap node has * an explicitly specified starting bit position within * the total bitmap. */ #ifndef _SEPOL_POLICYDB_EBITMAP_H_ #define _SEPOL_POLICYDB_EBITMAP_H_ #include #include #ifdef __cplusplus extern "C" { #endif #define MAPTYPE uint64_t /* portion of bitmap in each node */ #define MAPSIZE (sizeof(MAPTYPE) * 8) /* number of bits in node bitmap */ #define MAPBIT 1ULL /* a bit in the node bitmap */ typedef struct ebitmap_node { uint32_t startbit; /* starting position in the total bitmap */ MAPTYPE map; /* this node's portion of the bitmap */ struct ebitmap_node *next; } ebitmap_node_t; typedef struct ebitmap { ebitmap_node_t *node; /* first node in the bitmap */ uint32_t highbit; /* highest position in the total bitmap */ } ebitmap_t; #define ebitmap_is_empty(e) (((e)->node) == NULL) #define ebitmap_length(e) ((e)->node ? (e)->highbit : 0) #define ebitmap_startbit(e) ((e)->node ? (e)->node->startbit : 0) #define ebitmap_startnode(e) ((e)->node) static inline unsigned int ebitmap_start(const ebitmap_t * e, ebitmap_node_t ** n) { *n = e->node; return ebitmap_startbit(e); } static inline void ebitmap_init(ebitmap_t * e) { memset(e, 0, sizeof(*e)); } static inline unsigned int ebitmap_next(ebitmap_node_t ** n, unsigned int bit) { if ((bit == ((*n)->startbit + MAPSIZE - 1)) && (*n)->next) { *n = (*n)->next; return (*n)->startbit; } return (bit + 1); } static inline int ebitmap_node_get_bit(const ebitmap_node_t * n, unsigned int bit) { if (n->map & (MAPBIT << (bit - n->startbit))) return 1; return 0; } #define ebitmap_for_each_bit(e, n, bit) \ for (bit = ebitmap_start(e, &n); bit < ebitmap_length(e); bit = ebitmap_next(&n, bit)) \ #define ebitmap_for_each_positive_bit(e, n, bit) \ ebitmap_for_each_bit(e, n, bit) if (ebitmap_node_get_bit(n, bit)) \ extern int ebitmap_cmp(const ebitmap_t * e1, const ebitmap_t * e2); extern int ebitmap_or(ebitmap_t * dst, const ebitmap_t * e1, const ebitmap_t * e2); extern int ebitmap_union(ebitmap_t * dst, const ebitmap_t * e1); extern int ebitmap_and(ebitmap_t *dst, const ebitmap_t *e1, const ebitmap_t *e2); extern int ebitmap_xor(ebitmap_t *dst, const ebitmap_t *e1, const ebitmap_t *e2); extern int ebitmap_not(ebitmap_t *dst, const ebitmap_t *e1, unsigned int maxbit); extern int ebitmap_andnot(ebitmap_t *dst, const ebitmap_t *e1, const ebitmap_t *e2, unsigned int maxbit); extern unsigned int ebitmap_cardinality(const ebitmap_t *e1); extern int ebitmap_hamming_distance(const ebitmap_t * e1, const ebitmap_t * e2); extern int ebitmap_cpy(ebitmap_t * dst, const ebitmap_t * src); extern int ebitmap_contains(const ebitmap_t * e1, const ebitmap_t * e2); extern int ebitmap_match_any(const ebitmap_t *e1, const ebitmap_t *e2); extern int ebitmap_get_bit(const ebitmap_t * e, unsigned int bit); extern int ebitmap_set_bit(ebitmap_t * e, unsigned int bit, int value); extern int ebitmap_init_range(ebitmap_t * e, unsigned int minbit, unsigned int maxbit); extern unsigned int ebitmap_highest_set_bit(const ebitmap_t * e); extern void ebitmap_destroy(ebitmap_t * e); extern int ebitmap_read(ebitmap_t * e, void *fp); #ifdef __cplusplus } #endif #endif /* _EBITMAP_H_ */ /* FLASK */ libsepol-3.8.1/include/sepol/policydb/expand.h000066400000000000000000000071101476211737200213470ustar00rootroot00000000000000/* Authors: Jason Tang * Joshua Brindle * Karl MacMillan * * A set of utility functions that aid policy decision when dealing * with hierarchal items. * * Copyright (C) 2005 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _SEPOL_POLICYDB_EXPAND_H #define _SEPOL_POLICYDB_EXPAND_H #include #include #include #ifdef __cplusplus extern "C" { #endif /* * Expand only the avrules for a module. It is valid for this function * to expand base into itself (i.e. base == out); the typemap for * this special case should map type[i] to i+1. Likewise the boolmap * should map bool[i] to i + 1. This function optionally expands * neverallow rules. If neverallow rules are expanded, there is no * need to copy them and doing so could cause duplicate entries when * base == out. If the neverallow rules are not expanded, they are * just copied to the destination policy so that assertion checking * can be performed after expand. No assertion or hierarchy checking * is performed by this function. */ extern int expand_module_avrules(sepol_handle_t * handle, policydb_t * base, policydb_t * out, uint32_t * typemap, uint32_t * boolmap, uint32_t * rolemap, uint32_t * usermap, int verbose, int expand_neverallow); /* * Expand all parts of a module. Neverallow rules are not expanded (only * copied). It is not valid to expand base into itself. If check is non-zero, * performs hierarchy and assertion checking. */ extern int expand_module(sepol_handle_t * handle, policydb_t * base, policydb_t * out, int verbose, int check); extern int convert_type_ebitmap(ebitmap_t * src, ebitmap_t * dst, uint32_t * typemap); extern int expand_convert_type_set(policydb_t * p, uint32_t * typemap, type_set_t * set, ebitmap_t * types, unsigned char alwaysexpand); extern int type_set_expand(type_set_t * set, ebitmap_t * t, policydb_t * p, unsigned char alwaysexpand); extern int role_set_expand(role_set_t * x, ebitmap_t * r, policydb_t * out, policydb_t * base, uint32_t * rolemap); extern int mls_semantic_level_expand(mls_semantic_level_t *sl, mls_level_t *l, policydb_t *p, sepol_handle_t *h); extern int mls_semantic_range_expand(mls_semantic_range_t *sr, mls_range_t *r, policydb_t *p, sepol_handle_t *h); extern int expand_rule(sepol_handle_t * handle, policydb_t * source_pol, avrule_t * source_rule, avtab_t * dest_avtab, cond_av_list_t ** cond, cond_av_list_t ** other, int enabled); extern int expand_avtab(policydb_t * p, avtab_t * a, avtab_t * expa); extern int expand_cond_av_list(policydb_t * p, cond_av_list_t * l, cond_av_list_t ** newl, avtab_t * expa); #ifdef __cplusplus } #endif #endif libsepol-3.8.1/include/sepol/policydb/flask_types.h000066400000000000000000000030621476211737200224160ustar00rootroot00000000000000/* -*- linux-c -*- */ /* * Author : Stephen Smalley, */ #ifndef _SEPOL_POLICYDB_FLASK_TYPES_H_ #define _SEPOL_POLICYDB_FLASK_TYPES_H_ /* * The basic Flask types and constants. */ #include #include #ifdef __cplusplus extern "C" { #endif /* * A security context is a set of security attributes * associated with each subject and object controlled * by the security policy. The security context type * is defined as a variable-length string that can be * interpreted by any application or user with an * understanding of the security policy. */ typedef char *sepol_security_context_t; typedef const char *sepol_const_security_context_t; /* * An access vector (AV) is a collection of related permissions * for a pair of SIDs. The bits within an access vector * are interpreted differently depending on the class of * the object. The access vector interpretations are specified * in policy. */ typedef uint32_t sepol_access_vector_t; /* * Each object class is identified by a fixed-size value. * The set of security classes is specified in policy. */ typedef uint16_t sepol_security_class_t; #define SEPOL_SECCLASS_NULL 0x0000 /* no class */ #define SELINUX_MAGIC 0xf97cff8c #define SELINUX_MOD_MAGIC 0xf97cff8d typedef uint32_t sepol_security_id_t; #define SEPOL_SECSID_NULL 0 struct sepol_av_decision { sepol_access_vector_t allowed; sepol_access_vector_t decided; sepol_access_vector_t auditallow; sepol_access_vector_t auditdeny; uint32_t seqno; }; #ifdef __cplusplus } #endif #endif libsepol-3.8.1/include/sepol/policydb/hashtab.h000066400000000000000000000065321476211737200215110ustar00rootroot00000000000000/* Author : Stephen Smalley, */ /* FLASK */ /* * A hash table (hashtab) maintains associations between * key values and datum values. The type of the key values * and the type of the datum values is arbitrary. The * functions for hash computation and key comparison are * provided by the creator of the table. */ #ifndef _SEPOL_POLICYDB_HASHTAB_H_ #define _SEPOL_POLICYDB_HASHTAB_H_ #include #include #include #ifdef __cplusplus extern "C" { #endif typedef char *hashtab_key_t; /* generic key type */ typedef const char *const_hashtab_key_t; /* constant generic key type */ typedef void *hashtab_datum_t; /* generic datum type */ typedef struct hashtab_node *hashtab_ptr_t; typedef struct hashtab_node { hashtab_key_t key; hashtab_datum_t datum; hashtab_ptr_t next; } hashtab_node_t; typedef struct hashtab_val { hashtab_ptr_t *htable; /* hash table */ unsigned int size; /* number of slots in hash table */ uint32_t nel; /* number of elements in hash table */ unsigned int (*hash_value) (struct hashtab_val * h, const_hashtab_key_t key); /* hash function */ int (*keycmp) (struct hashtab_val * h, const_hashtab_key_t key1, const_hashtab_key_t key2); /* key comparison function */ } hashtab_val_t; typedef hashtab_val_t *hashtab_t; /* Creates a new hash table with the specified characteristics. Returns NULL if insufficient space is available or the new hash table otherwise. */ extern hashtab_t hashtab_create(unsigned int (*hash_value) (hashtab_t h, const_hashtab_key_t key), int (*keycmp) (hashtab_t h, const_hashtab_key_t key1, const_hashtab_key_t key2), unsigned int size); /* Inserts the specified (key, datum) pair into the specified hash table. Returns SEPOL_ENOMEM if insufficient space is available or SEPOL_EEXIST if there is already an entry with the same key or SEPOL_OK otherwise. */ extern int hashtab_insert(hashtab_t h, hashtab_key_t k, hashtab_datum_t d); /* Removes the entry with the specified key from the hash table. Applies the specified destroy function to (key,datum,args) for the entry. Returns SEPOL_ENOENT if no entry has the specified key or SEPOL_OK otherwise. */ extern int hashtab_remove(hashtab_t h, hashtab_key_t k, void (*destroy) (hashtab_key_t k, hashtab_datum_t d, void *args), void *args); /* Searches for the entry with the specified key in the hash table. Returns NULL if no entry has the specified key or the datum of the entry otherwise. */ extern hashtab_datum_t hashtab_search(hashtab_t h, const_hashtab_key_t k); /* Destroys the specified hash table. */ extern void hashtab_destroy(hashtab_t h); /* Applies the specified apply function to (key,datum,args) for each entry in the specified hash table. The order in which the function is applied to the entries is dependent upon the internal structure of the hash table. If apply returns a non-zero status, then hashtab_map will cease iterating through the hash table and will propagate the error return to its caller. */ extern int hashtab_map(hashtab_t h, int (*apply) (hashtab_key_t k, hashtab_datum_t d, void *args), void *args); extern void hashtab_hash_eval(hashtab_t h, const char *tag); #ifdef __cplusplus } #endif #endif libsepol-3.8.1/include/sepol/policydb/hierarchy.h000066400000000000000000000034321476211737200220510ustar00rootroot00000000000000/* Authors: Jason Tang * Joshua Brindle * Karl MacMillan * * A set of utility functions that aid policy decision when dealing * with hierarchal items. * * Copyright (C) 2005 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _SEPOL_POLICYDB_HIERARCHY_H_ #define _SEPOL_POLICYDB_HIERARCHY_H_ #include #include #ifdef __cplusplus extern "C" { #endif extern int hierarchy_add_bounds(sepol_handle_t *handle, policydb_t *p); extern void bounds_destroy_bad(avtab_ptr_t cur); extern int bounds_check_type(sepol_handle_t *handle, policydb_t *p, uint32_t child, uint32_t parent, avtab_ptr_t *bad, int *numbad); extern int bounds_check_users(sepol_handle_t *handle, policydb_t *p); extern int bounds_check_roles(sepol_handle_t *handle, policydb_t *p); extern int bounds_check_types(sepol_handle_t *handle, policydb_t *p); extern int hierarchy_check_constraints(sepol_handle_t * handle, policydb_t * p); #ifdef __cplusplus } #endif #endif libsepol-3.8.1/include/sepol/policydb/link.h000066400000000000000000000010051476211737200210220ustar00rootroot00000000000000/* Authors: Jason Tang * Joshua Brindle * Karl MacMillan */ #ifndef _SEPOL_POLICYDB_LINK_H #define _SEPOL_POLICYDB_LINK_H #include #include #include #include #ifdef __cplusplus extern "C" { #endif extern int link_modules(sepol_handle_t * handle, policydb_t * b, policydb_t ** mods, int len, int verbose); #ifdef __cplusplus } #endif #endif libsepol-3.8.1/include/sepol/policydb/mls_types.h000066400000000000000000000120441476211737200221110ustar00rootroot00000000000000/* Author : Stephen Smalley, */ /* * Updated: Trusted Computer Solutions, Inc. * * Support for enhanced MLS infrastructure. * * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* FLASK */ /* * Type definitions for the multi-level security (MLS) policy. */ #ifndef _SEPOL_POLICYDB_MLS_TYPES_H_ #define _SEPOL_POLICYDB_MLS_TYPES_H_ #include #include #include #include #include #include #ifdef __cplusplus extern "C" { #endif typedef struct mls_level { uint32_t sens; /* sensitivity */ ebitmap_t cat; /* category set */ } mls_level_t; typedef struct mls_range { mls_level_t level[2]; /* low == level[0], high == level[1] */ } mls_range_t; static inline int mls_range_glblub(struct mls_range *dst, const struct mls_range *r1, const struct mls_range *r2) { if (r1->level[1].sens < r2->level[0].sens || r2->level[1].sens < r1->level[0].sens) { /* These ranges have no common sensitivities */ return -EINVAL; } /* Take the greatest of the low */ dst->level[0].sens = MAX(r1->level[0].sens, r2->level[0].sens); /* Take the least of the high */ dst->level[1].sens = MIN(r1->level[1].sens, r2->level[1].sens); if (ebitmap_and(&dst->level[0].cat, &r1->level[0].cat, &r2->level[0].cat) < 0) { return -1; } if (ebitmap_and(&dst->level[1].cat, &r1->level[1].cat, &r2->level[1].cat) < 0) { return -1; } return 0; } static inline int mls_level_cpy(struct mls_level *dst, const struct mls_level *src) { dst->sens = src->sens; if (ebitmap_cpy(&dst->cat, &src->cat) < 0) return -1; return 0; } static inline void mls_level_init(struct mls_level *level) { memset(level, 0, sizeof(mls_level_t)); } static inline void mls_level_destroy(struct mls_level *level) { if (level == NULL) return; ebitmap_destroy(&level->cat); mls_level_init(level); } static inline int mls_level_eq(const struct mls_level *l1, const struct mls_level *l2) { return ((l1->sens == l2->sens) && ebitmap_cmp(&l1->cat, &l2->cat)); } static inline int mls_level_dom(const struct mls_level *l1, const struct mls_level *l2) { return ((l1->sens >= l2->sens) && ebitmap_contains(&l1->cat, &l2->cat)); } #define mls_level_incomp(l1, l2) \ (!mls_level_dom((l1), (l2)) && !mls_level_dom((l2), (l1))) #define mls_level_between(l1, l2, l3) \ (mls_level_dom((l1), (l2)) && mls_level_dom((l3), (l1))) #define mls_range_contains(r1, r2) \ (mls_level_dom(&(r2).level[0], &(r1).level[0]) && \ mls_level_dom(&(r1).level[1], &(r2).level[1])) static inline int mls_range_cpy(mls_range_t * dst, const mls_range_t * src) { if (mls_level_cpy(&dst->level[0], &src->level[0]) < 0) goto err; if (mls_level_cpy(&dst->level[1], &src->level[1]) < 0) goto err_destroy; return 0; err_destroy: mls_level_destroy(&dst->level[0]); err: return -1; } static inline void mls_range_init(struct mls_range *r) { mls_level_init(&r->level[0]); mls_level_init(&r->level[1]); } static inline void mls_range_destroy(struct mls_range *r) { mls_level_destroy(&r->level[0]); mls_level_destroy(&r->level[1]); } static inline int mls_range_eq(const struct mls_range *r1, const struct mls_range *r2) { return (mls_level_eq(&r1->level[0], &r2->level[0]) && mls_level_eq(&r1->level[1], &r2->level[1])); } typedef struct mls_semantic_cat { uint32_t low; /* first bit this struct represents */ uint32_t high; /* last bit represented - equals low for a single cat */ struct mls_semantic_cat *next; } mls_semantic_cat_t; typedef struct mls_semantic_level { uint32_t sens; mls_semantic_cat_t *cat; } mls_semantic_level_t; typedef struct mls_semantic_range { mls_semantic_level_t level[2]; } mls_semantic_range_t; extern void mls_semantic_cat_init(mls_semantic_cat_t *c); extern void mls_semantic_cat_destroy(mls_semantic_cat_t *c); extern void mls_semantic_level_init(mls_semantic_level_t *l); extern void mls_semantic_level_destroy(mls_semantic_level_t *l); extern int mls_semantic_level_cpy(mls_semantic_level_t *dst, const mls_semantic_level_t *src); extern void mls_semantic_range_init(mls_semantic_range_t *r); extern void mls_semantic_range_destroy(mls_semantic_range_t *r); extern int mls_semantic_range_cpy(mls_semantic_range_t *dst, const mls_semantic_range_t *src); #ifdef __cplusplus } #endif #endif libsepol-3.8.1/include/sepol/policydb/module.h000066400000000000000000000027741476211737200213700ustar00rootroot00000000000000/* Author: Karl MacMillan * * Copyright (C) 2004-2005 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _SEPOL_POLICYDB_MODULE_H_ #define _SEPOL_POLICYDB_MODULE_H_ #include #include #include #include #include #define SEPOL_MODULE_PACKAGE_MAGIC 0xf97cff8f #ifdef __cplusplus extern "C" { #endif struct sepol_module_package { sepol_policydb_t *policy; uint32_t version; char *file_contexts; size_t file_contexts_len; char *seusers; size_t seusers_len; char *user_extra; size_t user_extra_len; char *netfilter_contexts; size_t netfilter_contexts_len; }; extern int sepol_module_package_init(sepol_module_package_t * p); #ifdef __cplusplus } #endif #endif libsepol-3.8.1/include/sepol/policydb/polcaps.h000066400000000000000000000014411476211737200215320ustar00rootroot00000000000000#ifndef _SEPOL_POLICYDB_POLCAPS_H_ #define _SEPOL_POLICYDB_POLCAPS_H_ #ifdef __cplusplus extern "C" { #endif /* Policy capabilities */ enum { POLICYDB_CAP_NETPEER, POLICYDB_CAP_OPENPERM, POLICYDB_CAP_EXTSOCKCLASS, POLICYDB_CAP_ALWAYSNETWORK, POLICYDB_CAP_CGROUPSECLABEL, POLICYDB_CAP_NNP_NOSUID_TRANSITION, POLICYDB_CAP_GENFS_SECLABEL_SYMLINKS, POLICYDB_CAP_IOCTL_SKIP_CLOEXEC, POLICYDB_CAP_USERSPACE_INITIAL_CONTEXT, POLICYDB_CAP_NETLINK_XPERM, __POLICYDB_CAP_MAX }; #define POLICYDB_CAP_MAX (__POLICYDB_CAP_MAX - 1) /* Convert a capability name to number. */ extern int sepol_polcap_getnum(const char *name); /* Convert a capability number to name. */ extern const char *sepol_polcap_getname(unsigned int capnum); #ifdef __cplusplus } #endif #endif /* _SEPOL_POLICYDB_POLCAPS_H_ */ libsepol-3.8.1/include/sepol/policydb/policydb.h000066400000000000000000000652601476211737200217070ustar00rootroot00000000000000/* Author : Stephen Smalley, */ /* * Updated: Joshua Brindle * Karl MacMillan * Jason Tang * * Module support * * Updated: Trusted Computer Solutions, Inc. * * Support for enhanced MLS infrastructure. * * Updated: Frank Mayer and Karl MacMillan * * Added conditional policy language extensions * * Updated: Red Hat, Inc. James Morris * * Fine-grained netlink support * IPv6 support * Code cleanup * * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. * Copyright (C) 2003 - 2004 Tresys Technology, LLC * Copyright (C) 2003 - 2004 Red Hat, Inc. * Copyright (C) 2017 Mellanox Techonolgies Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* FLASK */ /* * A policy database (policydb) specifies the * configuration data for the security policy. */ #ifndef _SEPOL_POLICYDB_POLICYDB_H_ #define _SEPOL_POLICYDB_POLICYDB_H_ #include #include #include #include #include #include #include #include #include #define ERRMSG_LEN 1024 #define POLICYDB_SUCCESS 0 #define POLICYDB_ERROR -1 #define POLICYDB_UNSUPPORTED -2 #ifdef __cplusplus extern "C" { #endif #define IB_DEVICE_NAME_MAX 64 /* * A datum type is defined for each kind of symbol * in the configuration data: individual permissions, * common prefixes for access vectors, classes, * users, roles, types, sensitivities, categories, etc. */ /* type set preserves data needed by modules such as *, ~ and attributes */ typedef struct type_set { ebitmap_t types; ebitmap_t negset; #define TYPE_STAR 1 #define TYPE_COMP 2 uint32_t flags; } type_set_t; typedef struct role_set { ebitmap_t roles; #define ROLE_STAR 1 #define ROLE_COMP 2 uint32_t flags; } role_set_t; /* Permission attributes */ typedef struct perm_datum { symtab_datum_t s; } perm_datum_t; /* Attributes of a common prefix for access vectors */ typedef struct common_datum { symtab_datum_t s; symtab_t permissions; /* common permissions */ } common_datum_t; /* Class attributes */ typedef struct class_datum { symtab_datum_t s; char *comkey; /* common name */ common_datum_t *comdatum; /* common datum */ symtab_t permissions; /* class-specific permission symbol table */ constraint_node_t *constraints; /* constraints on class permissions */ constraint_node_t *validatetrans; /* special transition rules */ /* Options how a new object user and role should be decided */ #define DEFAULT_SOURCE 1 #define DEFAULT_TARGET 2 char default_user; char default_role; char default_type; /* Options how a new object range should be decided */ #define DEFAULT_SOURCE_LOW 1 #define DEFAULT_SOURCE_HIGH 2 #define DEFAULT_SOURCE_LOW_HIGH 3 #define DEFAULT_TARGET_LOW 4 #define DEFAULT_TARGET_HIGH 5 #define DEFAULT_TARGET_LOW_HIGH 6 #define DEFAULT_GLBLUB 7 char default_range; } class_datum_t; /* Role attributes */ typedef struct role_datum { symtab_datum_t s; ebitmap_t dominates; /* set of roles dominated by this role */ type_set_t types; /* set of authorized types for role */ ebitmap_t cache; /* This is an expanded set used for context validation during parsing */ uint32_t bounds; /* bounds role, if exist */ #define ROLE_ROLE 0 /* regular role in kernel policies */ #define ROLE_ATTRIB 1 /* attribute */ uint32_t flavor; ebitmap_t roles; /* roles with this attribute */ } role_datum_t; typedef struct role_trans { uint32_t role; /* current role */ uint32_t type; /* program executable type, or new object type */ uint32_t tclass; /* process class, or new object class */ uint32_t new_role; /* new role */ struct role_trans *next; } role_trans_t; typedef struct role_allow { uint32_t role; /* current role */ uint32_t new_role; /* new role */ struct role_allow *next; } role_allow_t; /* filename_trans rules */ typedef struct filename_trans_key { uint32_t ttype; uint32_t tclass; char *name; } filename_trans_key_t; typedef struct filename_trans_datum { ebitmap_t stypes; uint32_t otype; struct filename_trans_datum *next; } filename_trans_datum_t; /* Type attributes */ typedef struct type_datum { symtab_datum_t s; uint32_t primary; /* primary name? can be set to primary value if below is TYPE_ */ #define TYPE_TYPE 0 /* regular type or alias in kernel policies */ #define TYPE_ATTRIB 1 /* attribute */ #define TYPE_ALIAS 2 /* alias in modular policy */ uint32_t flavor; ebitmap_t types; /* types with this attribute */ #define TYPE_FLAGS_PERMISSIVE (1 << 0) #define TYPE_FLAGS_EXPAND_ATTR_TRUE (1 << 1) #define TYPE_FLAGS_EXPAND_ATTR_FALSE (1 << 2) #define TYPE_FLAGS_EXPAND_ATTR (TYPE_FLAGS_EXPAND_ATTR_TRUE | \ TYPE_FLAGS_EXPAND_ATTR_FALSE) uint32_t flags; uint32_t bounds; /* bounds type, if exist */ } type_datum_t; /* * Properties of type_datum * available on the policy version >= (MOD_)POLICYDB_VERSION_BOUNDARY */ #define TYPEDATUM_PROPERTY_PRIMARY 0x0001 #define TYPEDATUM_PROPERTY_ATTRIBUTE 0x0002 #define TYPEDATUM_PROPERTY_ALIAS 0x0004 /* userspace only */ #define TYPEDATUM_PROPERTY_PERMISSIVE 0x0008 /* userspace only */ /* User attributes */ typedef struct user_datum { symtab_datum_t s; role_set_t roles; /* set of authorized roles for user */ mls_semantic_range_t range; /* MLS range (min. - max.) for user */ mls_semantic_level_t dfltlevel; /* default login MLS level for user */ ebitmap_t cache; /* This is an expanded set used for context validation during parsing */ mls_range_t exp_range; /* expanded range used for validation */ mls_level_t exp_dfltlevel; /* expanded range used for validation */ uint32_t bounds; /* bounds user, if exist */ } user_datum_t; /* Sensitivity attributes */ typedef struct level_datum { mls_level_t *level; /* sensitivity and associated categories */ unsigned char isalias; /* is this sensitivity an alias for another? */ unsigned char notdefined; /* Only set to non-zero in checkpolicy */ } level_datum_t; /* Category attributes */ typedef struct cat_datum { symtab_datum_t s; unsigned char isalias; /* is this category an alias for another? */ } cat_datum_t; typedef struct range_trans { uint32_t source_type; uint32_t target_type; uint32_t target_class; } range_trans_t; /* Boolean data type */ typedef struct cond_bool_datum { symtab_datum_t s; int state; #define COND_BOOL_FLAGS_TUNABLE 0x01 /* is this a tunable? */ uint32_t flags; } cond_bool_datum_t; struct cond_node; typedef struct cond_node cond_list_t; struct cond_av_list; typedef struct class_perm_node { uint32_t tclass; uint32_t data; /* permissions or new type */ struct class_perm_node *next; } class_perm_node_t; #define xperm_test(x, p) (UINT32_C(1) & ((p)[(x) >> 5] >> ((x) & 0x1f))) #define xperm_set(x, p) ((p)[(x) >> 5] |= (UINT32_C(1) << ((x) & 0x1f))) #define xperm_clear(x, p) ((p)[(x) >> 5] &= ~(UINT32_C(1) << ((x) & 0x1f))) #define EXTENDED_PERMS_LEN 8 typedef struct av_extended_perms { #define AVRULE_XPERMS_IOCTLFUNCTION 0x01 #define AVRULE_XPERMS_IOCTLDRIVER 0x02 #define AVRULE_XPERMS_NLMSG 0x03 uint8_t specified; uint8_t driver; /* 256 bits of permissions */ uint32_t perms[EXTENDED_PERMS_LEN]; } av_extended_perms_t; typedef struct avrule { /* these typedefs are almost exactly the same as those in avtab.h - they are * here because of the need to include neverallow and dontaudit messages */ #define AVRULE_ALLOWED AVTAB_ALLOWED #define AVRULE_AUDITALLOW AVTAB_AUDITALLOW #define AVRULE_AUDITDENY AVTAB_AUDITDENY #define AVRULE_DONTAUDIT 0x0008 #define AVRULE_NEVERALLOW AVTAB_NEVERALLOW #define AVRULE_AV (AVRULE_ALLOWED | AVRULE_AUDITALLOW | AVRULE_AUDITDENY | AVRULE_DONTAUDIT | AVRULE_NEVERALLOW) #define AVRULE_TRANSITION AVTAB_TRANSITION #define AVRULE_MEMBER AVTAB_MEMBER #define AVRULE_CHANGE AVTAB_CHANGE #define AVRULE_TYPE (AVRULE_TRANSITION | AVRULE_MEMBER | AVRULE_CHANGE) #define AVRULE_XPERMS_ALLOWED AVTAB_XPERMS_ALLOWED #define AVRULE_XPERMS_AUDITALLOW AVTAB_XPERMS_AUDITALLOW #define AVRULE_XPERMS_DONTAUDIT AVTAB_XPERMS_DONTAUDIT #define AVRULE_XPERMS_NEVERALLOW AVTAB_XPERMS_NEVERALLOW #define AVRULE_XPERMS (AVRULE_XPERMS_ALLOWED | AVRULE_XPERMS_AUDITALLOW | \ AVRULE_XPERMS_DONTAUDIT | AVRULE_XPERMS_NEVERALLOW) uint32_t specified; #define RULE_SELF (1U << 0) #define RULE_NOTSELF (1U << 1) uint32_t flags; type_set_t stypes; type_set_t ttypes; class_perm_node_t *perms; av_extended_perms_t *xperms; unsigned long line; /* line number from policy.conf where * this rule originated */ /* source file name and line number (e.g. .te file) */ char *source_filename; unsigned long source_line; struct avrule *next; } avrule_t; typedef struct role_trans_rule { role_set_t roles; /* current role */ type_set_t types; /* program executable type, or new object type */ ebitmap_t classes; /* process class, or new object class */ uint32_t new_role; /* new role */ struct role_trans_rule *next; } role_trans_rule_t; typedef struct role_allow_rule { role_set_t roles; /* current role */ role_set_t new_roles; /* new roles */ struct role_allow_rule *next; } role_allow_rule_t; typedef struct filename_trans_rule { uint32_t flags; /* may have RULE_SELF set */ type_set_t stypes; type_set_t ttypes; uint32_t tclass; char *name; uint32_t otype; /* new type */ struct filename_trans_rule *next; } filename_trans_rule_t; typedef struct range_trans_rule { type_set_t stypes; type_set_t ttypes; ebitmap_t tclasses; mls_semantic_range_t trange; struct range_trans_rule *next; } range_trans_rule_t; /* * The configuration data includes security contexts for * initial SIDs, unlabeled file systems, TCP and UDP port numbers, * network interfaces, and nodes. This structure stores the * relevant data for one such entry. Entries of the same kind * (e.g. all initial SIDs) are linked together into a list. */ typedef struct ocontext { union { char *name; /* name of initial SID, fs, netif, fstype, path */ struct { uint8_t protocol; uint16_t low_port; uint16_t high_port; } port; /* TCP or UDP port information */ struct { uint32_t addr; /* network order */ uint32_t mask; /* network order */ } node; /* node information */ struct { uint32_t addr[4]; /* network order */ uint32_t mask[4]; /* network order */ } node6; /* IPv6 node information */ uint32_t device; uint16_t pirq; struct { uint64_t low_iomem; uint64_t high_iomem; } iomem; struct { uint32_t low_ioport; uint32_t high_ioport; } ioport; struct { uint64_t subnet_prefix; uint16_t low_pkey; uint16_t high_pkey; } ibpkey; struct { char *dev_name; uint8_t port; } ibendport; } u; union { uint32_t sclass; /* security class for genfs */ uint32_t behavior; /* labeling behavior for fs_use */ } v; context_struct_t context[2]; /* security context(s) */ sepol_security_id_t sid[2]; /* SID(s) */ struct ocontext *next; } ocontext_t; typedef struct genfs { char *fstype; struct ocontext *head; struct genfs *next; } genfs_t; /* symbol table array indices */ #define SYM_COMMONS 0 #define SYM_CLASSES 1 #define SYM_ROLES 2 #define SYM_TYPES 3 #define SYM_USERS 4 #define SYM_BOOLS 5 #define SYM_LEVELS 6 #define SYM_CATS 7 #define SYM_NUM 8 /* object context array indices */ #define OCON_ISID 0 /* initial SIDs */ #define OCON_FS 1 /* unlabeled file systems */ #define OCON_PORT 2 /* TCP and UDP port numbers */ #define OCON_NETIF 3 /* network interfaces */ #define OCON_NODE 4 /* nodes */ #define OCON_FSUSE 5 /* fs_use */ #define OCON_NODE6 6 /* IPv6 nodes */ #define OCON_IBPKEY 7 /* Infiniband PKEY */ #define OCON_IBENDPORT 8 /* Infiniband End Port */ /* object context array indices for Xen */ #define OCON_XEN_ISID 0 /* initial SIDs */ #define OCON_XEN_PIRQ 1 /* physical irqs */ #define OCON_XEN_IOPORT 2 /* io ports */ #define OCON_XEN_IOMEM 3 /* io memory */ #define OCON_XEN_PCIDEVICE 4 /* pci devices */ #define OCON_XEN_DEVICETREE 5 /* device tree node */ /* OCON_NUM needs to be the largest index in any platform's ocontext array */ #define OCON_NUM 9 /* section: module information */ /* scope_index_t holds all of the symbols that are in scope in a * particular situation. The bitmaps are indices (and thus must * subtract one) into the global policydb->scope array. */ typedef struct scope_index { ebitmap_t scope[SYM_NUM]; #define p_classes_scope scope[SYM_CLASSES] #define p_roles_scope scope[SYM_ROLES] #define p_types_scope scope[SYM_TYPES] #define p_users_scope scope[SYM_USERS] #define p_bools_scope scope[SYM_BOOLS] #define p_sens_scope scope[SYM_LEVELS] #define p_cat_scope scope[SYM_CATS] /* this array maps from class->value to the permissions within * scope. if bit (perm->value - 1) is set in map * class_perms_map[class->value - 1] then that permission is * enabled for this class within this decl. */ ebitmap_t *class_perms_map; /* total number of classes in class_perms_map array */ uint32_t class_perms_len; } scope_index_t; /* a list of declarations for a particular avrule_decl */ /* These two structs declare a block of policy that has TE and RBAC * statements and declarations. The root block (the global policy) * can never have an ELSE branch. */ typedef struct avrule_decl { uint32_t decl_id; uint32_t enabled; /* whether this block is enabled */ cond_list_t *cond_list; avrule_t *avrules; role_trans_rule_t *role_tr_rules; role_allow_rule_t *role_allow_rules; range_trans_rule_t *range_tr_rules; scope_index_t required; /* symbols needed to activate this block */ scope_index_t declared; /* symbols declared within this block */ /* type transition rules with a 'name' component */ filename_trans_rule_t *filename_trans_rules; /* for additive statements (type attribute, roles, and users) */ symtab_t symtab[SYM_NUM]; /* In a linked module this will contain the name of the module * from which this avrule_decl originated. */ char *module_name; struct avrule_decl *next; } avrule_decl_t; typedef struct avrule_block { avrule_decl_t *branch_list; avrule_decl_t *enabled; /* pointer to which branch is enabled. this is used in linking and never written to disk */ #define AVRULE_OPTIONAL 1 uint32_t flags; /* any flags for this block, currently just optional */ struct avrule_block *next; } avrule_block_t; /* Every identifier has its own scope datum. The datum describes if * the item is to be included into the final policy during * expansion. */ typedef struct scope_datum { /* Required for this decl */ #define SCOPE_REQ 1 /* Declared in this decl */ #define SCOPE_DECL 2 uint32_t scope; uint32_t *decl_ids; uint32_t decl_ids_len; /* decl_ids is a list of avrule_decl's that declare/require * this symbol. If scope==SCOPE_DECL then this is a list of * declarations. If the symbol may only be declared once * (types, bools) then decl_ids_len will be exactly 1. For * implicitly declared things (roles, users) then decl_ids_len * will be at least 1. */ } scope_datum_t; /* The policy database */ typedef struct policydb { #define POLICY_KERN SEPOL_POLICY_KERN #define POLICY_BASE SEPOL_POLICY_BASE #define POLICY_MOD SEPOL_POLICY_MOD uint32_t policy_type; char *name; char *version; int target_platform; /* Set when the policydb is modified such that writing is unsupported */ int unsupported_format; /* Whether this policydb is mls, should always be set */ int mls; /* symbol tables */ symtab_t symtab[SYM_NUM]; #define p_commons symtab[SYM_COMMONS] #define p_classes symtab[SYM_CLASSES] #define p_roles symtab[SYM_ROLES] #define p_types symtab[SYM_TYPES] #define p_users symtab[SYM_USERS] #define p_bools symtab[SYM_BOOLS] #define p_levels symtab[SYM_LEVELS] #define p_cats symtab[SYM_CATS] /* symbol names indexed by (value - 1) */ char **sym_val_to_name[SYM_NUM]; #define p_common_val_to_name sym_val_to_name[SYM_COMMONS] #define p_class_val_to_name sym_val_to_name[SYM_CLASSES] #define p_role_val_to_name sym_val_to_name[SYM_ROLES] #define p_type_val_to_name sym_val_to_name[SYM_TYPES] #define p_user_val_to_name sym_val_to_name[SYM_USERS] #define p_bool_val_to_name sym_val_to_name[SYM_BOOLS] #define p_sens_val_to_name sym_val_to_name[SYM_LEVELS] #define p_cat_val_to_name sym_val_to_name[SYM_CATS] /* class, role, and user attributes indexed by (value - 1) */ class_datum_t **class_val_to_struct; role_datum_t **role_val_to_struct; user_datum_t **user_val_to_struct; type_datum_t **type_val_to_struct; /* module stuff section -- used in parsing and for modules */ /* keep track of the scope for every identifier. these are * hash tables, where the key is the identifier name and value * a scope_datum_t. as a convenience, one may use the * p_*_macros (cf. struct scope_index_t declaration). */ symtab_t scope[SYM_NUM]; /* module rule storage */ avrule_block_t *global; /* avrule_decl index used for link/expand */ avrule_decl_t **decl_val_to_struct; /* compiled storage of rules - use for the kernel policy */ /* type enforcement access vectors and transitions */ avtab_t te_avtab; /* bools indexed by (value - 1) */ cond_bool_datum_t **bool_val_to_struct; /* type enforcement conditional access vectors and transitions */ avtab_t te_cond_avtab; /* linked list indexing te_cond_avtab by conditional */ cond_list_t *cond_list; /* role transitions */ role_trans_t *role_tr; /* role allows */ role_allow_t *role_allow; /* security contexts of initial SIDs, unlabeled file systems, TCP or UDP port numbers, network interfaces and nodes */ ocontext_t *ocontexts[OCON_NUM]; /* security contexts for files in filesystems that cannot support a persistent label mapping or use another fixed labeling behavior. */ genfs_t *genfs; /* range transitions table (range_trans_key -> mls_range) */ hashtab_t range_tr; /* file transitions with the last path component */ hashtab_t filename_trans; uint32_t filename_trans_count; ebitmap_t *type_attr_map; ebitmap_t *attr_type_map; /* not saved in the binary policy */ ebitmap_t policycaps; /* this bitmap is referenced by type NOT the typical type-1 used in other bitmaps. Someday the 0 bit may be used for global permissive */ ebitmap_t permissive_map; unsigned policyvers; unsigned handle_unknown; sepol_security_class_t process_class; sepol_security_class_t dir_class; sepol_access_vector_t process_trans; sepol_access_vector_t process_trans_dyntrans; } policydb_t; struct sepol_policydb { struct policydb p; }; extern int policydb_init(policydb_t * p); extern int policydb_from_image(sepol_handle_t * handle, void *data, size_t len, policydb_t * policydb); extern int policydb_to_image(sepol_handle_t * handle, policydb_t * policydb, void **newdata, size_t * newlen); extern int policydb_index_classes(policydb_t * p); extern int policydb_index_bools(policydb_t * p); extern int policydb_index_others(sepol_handle_t * handle, policydb_t * p, unsigned int verbose); extern int policydb_role_cache(hashtab_key_t key, hashtab_datum_t datum, void *arg); extern int policydb_user_cache(hashtab_key_t key, hashtab_datum_t datum, void *arg); extern int policydb_reindex_users(policydb_t * p); extern int policydb_optimize(policydb_t * p); extern void policydb_destroy(policydb_t * p); extern int policydb_load_isids(policydb_t * p, sidtab_t * s); extern int policydb_sort_ocontexts(policydb_t *p); extern int policydb_filetrans_insert(policydb_t *p, uint32_t stype, uint32_t ttype, uint32_t tclass, const char *name, char **name_alloc, uint32_t otype, uint32_t *present_otype); /* Deprecated */ extern int policydb_context_isvalid(const policydb_t * p, const context_struct_t * c); extern void symtabs_destroy(symtab_t * symtab); extern int scope_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p); extern void class_perm_node_init(class_perm_node_t * x); extern void type_set_init(type_set_t * x); extern void type_set_destroy(type_set_t * x); extern int type_set_cpy(type_set_t * dst, const type_set_t * src); extern int type_set_or_eq(type_set_t * dst, const type_set_t * other); extern void role_set_init(role_set_t * x); extern void role_set_destroy(role_set_t * x); extern void avrule_init(avrule_t * x); extern void avrule_destroy(avrule_t * x); extern void avrule_list_destroy(avrule_t * x); extern void role_trans_rule_init(role_trans_rule_t * x); extern void role_trans_rule_list_destroy(role_trans_rule_t * x); extern void filename_trans_rule_init(filename_trans_rule_t * x); extern void filename_trans_rule_list_destroy(filename_trans_rule_t * x); extern void role_datum_init(role_datum_t * x); extern void role_datum_destroy(role_datum_t * x); extern void role_allow_rule_init(role_allow_rule_t * x); extern void role_allow_rule_destroy(role_allow_rule_t * x); extern void role_allow_rule_list_destroy(role_allow_rule_t * x); extern void range_trans_rule_init(range_trans_rule_t *x); extern void range_trans_rule_destroy(range_trans_rule_t *x); extern void range_trans_rule_list_destroy(range_trans_rule_t *x); extern void type_datum_init(type_datum_t * x); extern void type_datum_destroy(type_datum_t * x); extern void user_datum_init(user_datum_t * x); extern void user_datum_destroy(user_datum_t * x); extern void level_datum_init(level_datum_t * x); extern void level_datum_destroy(level_datum_t * x); extern void cat_datum_init(cat_datum_t * x); extern void cat_datum_destroy(cat_datum_t * x); extern int check_assertion(policydb_t *p, const avrule_t *avrule); extern int check_assertions(sepol_handle_t * handle, policydb_t * p, const avrule_t * avrules); extern int symtab_insert(policydb_t * x, uint32_t sym, hashtab_key_t key, hashtab_datum_t datum, uint32_t scope, uint32_t avrule_decl_id, uint32_t * value); /* A policy "file" may be a memory region referenced by a (data, len) pair or a file referenced by a FILE pointer. */ typedef struct policy_file { #define PF_USE_MEMORY 0 #define PF_USE_STDIO 1 #define PF_LEN 2 /* total up length in len field */ unsigned type; char *data; size_t len; size_t size; FILE *fp; struct sepol_handle *handle; } policy_file_t; struct sepol_policy_file { struct policy_file pf; }; extern void policy_file_init(policy_file_t * x); extern int policydb_read(policydb_t * p, struct policy_file *fp, unsigned int verbose); extern int avrule_read_list(policydb_t * p, avrule_t ** avrules, struct policy_file *fp); extern int policydb_write(struct policydb *p, struct policy_file *pf); extern int policydb_set_target_platform(policydb_t *p, int platform); #define PERM_SYMTAB_SIZE 32 /* Identify specific policy version changes */ #define POLICYDB_VERSION_BASE 15 #define POLICYDB_VERSION_BOOL 16 #define POLICYDB_VERSION_IPV6 17 #define POLICYDB_VERSION_NLCLASS 18 #define POLICYDB_VERSION_VALIDATETRANS 19 #define POLICYDB_VERSION_MLS 19 #define POLICYDB_VERSION_AVTAB 20 #define POLICYDB_VERSION_RANGETRANS 21 #define POLICYDB_VERSION_POLCAP 22 #define POLICYDB_VERSION_PERMISSIVE 23 #define POLICYDB_VERSION_BOUNDARY 24 #define POLICYDB_VERSION_FILENAME_TRANS 25 #define POLICYDB_VERSION_ROLETRANS 26 #define POLICYDB_VERSION_NEW_OBJECT_DEFAULTS 27 #define POLICYDB_VERSION_DEFAULT_TYPE 28 #define POLICYDB_VERSION_CONSTRAINT_NAMES 29 #define POLICYDB_VERSION_XEN_DEVICETREE 30 /* Xen-specific */ #define POLICYDB_VERSION_XPERMS_IOCTL 30 /* Linux-specific */ #define POLICYDB_VERSION_INFINIBAND 31 /* Linux-specific */ #define POLICYDB_VERSION_GLBLUB 32 #define POLICYDB_VERSION_COMP_FTRANS 33 /* compressed filename transitions */ #define POLICYDB_VERSION_COND_XPERMS 34 /* extended permissions in conditional policies */ /* Range of policy versions we understand*/ #define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE #define POLICYDB_VERSION_MAX POLICYDB_VERSION_COND_XPERMS /* Module versions and specific changes*/ #define MOD_POLICYDB_VERSION_BASE 4 #define MOD_POLICYDB_VERSION_VALIDATETRANS 5 #define MOD_POLICYDB_VERSION_MLS 5 #define MOD_POLICYDB_VERSION_RANGETRANS 6 #define MOD_POLICYDB_VERSION_MLS_USERS 6 #define MOD_POLICYDB_VERSION_POLCAP 7 #define MOD_POLICYDB_VERSION_PERMISSIVE 8 #define MOD_POLICYDB_VERSION_BOUNDARY 9 #define MOD_POLICYDB_VERSION_BOUNDARY_ALIAS 10 #define MOD_POLICYDB_VERSION_FILENAME_TRANS 11 #define MOD_POLICYDB_VERSION_ROLETRANS 12 #define MOD_POLICYDB_VERSION_ROLEATTRIB 13 #define MOD_POLICYDB_VERSION_TUNABLE_SEP 14 #define MOD_POLICYDB_VERSION_NEW_OBJECT_DEFAULTS 15 #define MOD_POLICYDB_VERSION_DEFAULT_TYPE 16 #define MOD_POLICYDB_VERSION_CONSTRAINT_NAMES 17 #define MOD_POLICYDB_VERSION_XPERMS_IOCTL 18 #define MOD_POLICYDB_VERSION_INFINIBAND 19 #define MOD_POLICYDB_VERSION_GLBLUB 20 #define MOD_POLICYDB_VERSION_SELF_TYPETRANS 21 #define MOD_POLICYDB_VERSION_COND_XPERMS 22 #define MOD_POLICYDB_VERSION_MIN MOD_POLICYDB_VERSION_BASE #define MOD_POLICYDB_VERSION_MAX MOD_POLICYDB_VERSION_COND_XPERMS #define POLICYDB_CONFIG_MLS 1 /* macros to check policy feature */ /* TODO: add other features here */ #define policydb_has_boundary_feature(p) \ (((p)->policy_type == POLICY_KERN \ && (p)->policyvers >= POLICYDB_VERSION_BOUNDARY) || \ ((p)->policy_type != POLICY_KERN \ && (p)->policyvers >= MOD_POLICYDB_VERSION_BOUNDARY)) #define policydb_has_cond_xperms_feature(p) \ (((p)->policy_type == POLICY_KERN \ && (p)->policyvers >= POLICYDB_VERSION_COND_XPERMS) || \ ((p)->policy_type != POLICY_KERN \ && (p)->policyvers >= MOD_POLICYDB_VERSION_COND_XPERMS)) /* the config flags related to unknown classes/perms are bits 2 and 3 */ #define DENY_UNKNOWN SEPOL_DENY_UNKNOWN #define REJECT_UNKNOWN SEPOL_REJECT_UNKNOWN #define ALLOW_UNKNOWN SEPOL_ALLOW_UNKNOWN #define POLICYDB_CONFIG_UNKNOWN_MASK (DENY_UNKNOWN | REJECT_UNKNOWN | ALLOW_UNKNOWN) #define OBJECT_R "object_r" #define OBJECT_R_VAL 1 #define POLICYDB_MAGIC SELINUX_MAGIC #define POLICYDB_STRING "SE Linux" #define POLICYDB_XEN_STRING "XenFlask" #define POLICYDB_STRING_MAX_LENGTH 32 #define POLICYDB_MOD_MAGIC SELINUX_MOD_MAGIC #define POLICYDB_MOD_STRING "SE Linux Module" #ifdef __cplusplus } #endif #endif /* _POLICYDB_H_ */ /* FLASK */ libsepol-3.8.1/include/sepol/policydb/services.h000066400000000000000000000207441476211737200217230ustar00rootroot00000000000000 /* -*- linux-c -*- */ /* * Author : Stephen Smalley, */ #ifndef _SEPOL_POLICYDB_SERVICES_H_ #define _SEPOL_POLICYDB_SERVICES_H_ /* * Security server interface. */ #include #include #include #ifdef __cplusplus extern "C" { #endif /* Set the policydb and sidtab structures to be used by the service functions. If not set, then these default to private structures within libsepol that can only be initialized and accessed via the service functions themselves. Setting the structures explicitly allows a program to directly manipulate them, e.g. checkpolicy populates the structures directly from a source policy rather than from a binary policy. */ extern int sepol_set_policydb(policydb_t * p); extern int sepol_set_sidtab(sidtab_t * s); /* Load the security policy. This initializes the policydb and sidtab based on the provided binary policy. */ extern int sepol_load_policy(void *data, size_t len); /* * Compute access vectors based on a SID pair for * the permissions in a particular class. */ extern int sepol_compute_av(sepol_security_id_t ssid, /* IN */ sepol_security_id_t tsid, /* IN */ sepol_security_class_t tclass, /* IN */ sepol_access_vector_t requested, /* IN */ struct sepol_av_decision *avd); /* OUT */ /* Same as above, but also return the reason(s) for any denials of the requested permissions. */ #define SEPOL_COMPUTEAV_TE 0x1U #define SEPOL_COMPUTEAV_CONS 0x2U #define SEPOL_COMPUTEAV_RBAC 0x4U #define SEPOL_COMPUTEAV_BOUNDS 0x8U extern int sepol_compute_av_reason(sepol_security_id_t ssid, sepol_security_id_t tsid, sepol_security_class_t tclass, sepol_access_vector_t requested, struct sepol_av_decision *avd, unsigned int *reason); /* * Same as above, but also returns the constraint expression calculations * whether allowed or denied in a buffer. This buffer is allocated by * this call and must be free'd by the caller using free(3). The constraint * buffer will contain any constraints in infix notation. * If the SHOW_GRANTED flag is set it will show granted and denied * constraints. The default is to show only denied constraints. */ #define SHOW_GRANTED 1 extern int sepol_compute_av_reason_buffer(sepol_security_id_t ssid, sepol_security_id_t tsid, sepol_security_class_t tclass, sepol_access_vector_t requested, struct sepol_av_decision *avd, unsigned int *reason, char **reason_buf, unsigned int flags); /* * Returns the mls/validatetrans constraint expression calculations in * a buffer that must be free'd by the caller using free(3). * If the SHOW_GRANTED flag is set it will show granted and denied * mls/validatetrans (the default is to show only those denied). */ extern int sepol_validate_transition_reason_buffer(sepol_security_id_t oldsid, sepol_security_id_t newsid, sepol_security_id_t tasksid, sepol_security_class_t tclass, char **reason_buf, unsigned int flags); /* * Return a class ID associated with the class string representation * specified by `class_name'. */ extern int sepol_string_to_security_class(const char *class_name, sepol_security_class_t *tclass); /* * Return a permission av bit associated with tclass and the string * representation of the `perm_name'. */ extern int sepol_string_to_av_perm(sepol_security_class_t tclass, const char *perm_name, sepol_access_vector_t *av); /* * Return a string representation of the permission av bit associated with * tclass. * Returns a pointer to an internal buffer, overridden by the next call to * this function or sepol_av_to_string(). */ extern const char *sepol_av_perm_to_string(sepol_security_class_t tclass, sepol_access_vector_t av); /* * Compute a SID to use for labeling a new object in the * class `tclass' based on a SID pair. */ extern int sepol_transition_sid(sepol_security_id_t ssid, /* IN */ sepol_security_id_t tsid, /* IN */ sepol_security_class_t tclass, /* IN */ sepol_security_id_t * out_sid); /* OUT */ /* * Compute a SID to use when selecting a member of a * polyinstantiated object of class `tclass' based on * a SID pair. */ extern int sepol_member_sid(sepol_security_id_t ssid, /* IN */ sepol_security_id_t tsid, /* IN */ sepol_security_class_t tclass, /* IN */ sepol_security_id_t * out_sid); /* OUT */ /* * Compute a SID to use for relabeling an object in the * class `tclass' based on a SID pair. */ extern int sepol_change_sid(sepol_security_id_t ssid, /* IN */ sepol_security_id_t tsid, /* IN */ sepol_security_class_t tclass, /* IN */ sepol_security_id_t * out_sid); /* OUT */ /* * Write the security context string representation of * the context associated with `sid' into a dynamically * allocated string of the correct size. Set `*scontext' * to point to this string and set `*scontext_len' to * the length of the string. */ extern int sepol_sid_to_context(sepol_security_id_t sid, /* IN */ sepol_security_context_t * scontext, /* OUT */ size_t * scontext_len); /* OUT */ /* * Return a SID associated with the security context that * has the string representation specified by `scontext'. */ extern int sepol_context_to_sid(sepol_const_security_context_t scontext, /* IN */ size_t scontext_len, /* IN */ sepol_security_id_t * out_sid); /* OUT */ /* * Generate the set of SIDs for legal security contexts * for a given user that can be reached by `fromsid'. * Set `*sids' to point to a dynamically allocated * array containing the set of SIDs. Set `*nel' to the * number of elements in the array. */ extern int sepol_get_user_sids(sepol_security_id_t callsid, char *username, sepol_security_id_t ** sids, uint32_t * nel); /* * Return the SIDs to use for an unlabeled file system * that is being mounted from the device with the * the kdevname `name'. The `fs_sid' SID is returned for * the file system and the `file_sid' SID is returned * for all files within that file system. */ extern int sepol_fs_sid(char *dev, /* IN */ sepol_security_id_t * fs_sid, /* OUT */ sepol_security_id_t * file_sid); /* OUT */ /* * Return the SID of the port specified by * `domain', `type', `protocol', and `port'. */ extern int sepol_port_sid(uint16_t domain, uint16_t type, uint8_t protocol, uint16_t port, sepol_security_id_t * out_sid); /* * Return the SID of the ibpkey specified by * `subnet prefix', and `pkey'. */ extern int sepol_ibpkey_sid(uint64_t subnet_prefix_p, uint16_t pkey, sepol_security_id_t *out_sid); /* * Return the SID of the ibendport specified by * `dev_name', and `port'. */ extern int sepol_ibendport_sid(char *dev_name, uint8_t port, sepol_security_id_t *out_sid); /* * Return the SIDs to use for a network interface * with the name `name'. The `if_sid' SID is returned for * the interface and the `msg_sid' SID is returned as * the default SID for messages received on the * interface. */ extern int sepol_netif_sid(char *name, sepol_security_id_t * if_sid, sepol_security_id_t * msg_sid); /* * Return the SID of the node specified by the address * `addr' where `addrlen' is the length of the address * in bytes and `domain' is the communications domain or * address family in which the address should be interpreted. */ extern int sepol_node_sid(uint16_t domain, void *addr, size_t addrlen, sepol_security_id_t * out_sid); /* * Return a value indicating how to handle labeling for the * the specified filesystem type, and optionally return a SID * for the filesystem object. */ #define SECURITY_FS_USE_XATTR 1 /* use xattr */ #define SECURITY_FS_USE_TRANS 2 /* use transition SIDs, e.g. devpts/tmpfs */ #define SECURITY_FS_USE_TASK 3 /* use task SIDs, e.g. pipefs/sockfs */ #define SECURITY_FS_USE_GENFS 4 /* use the genfs support */ #define SECURITY_FS_USE_NONE 5 /* no labeling support */ extern int sepol_fs_use(const char *fstype, /* IN */ unsigned int *behavior, /* OUT */ sepol_security_id_t * sid); /* OUT */ /* * Return the SID to use for a file in a filesystem * that cannot support a persistent label mapping or use another * fixed labeling behavior like transition SIDs or task SIDs. */ extern int sepol_genfs_sid(const char *fstype, /* IN */ const char *name, /* IN */ sepol_security_class_t sclass, /* IN */ sepol_security_id_t * sid); /* OUT */ #ifdef __cplusplus } #endif #endif libsepol-3.8.1/include/sepol/policydb/sidtab.h000066400000000000000000000037051476211737200213440ustar00rootroot00000000000000/* Author : Stephen Smalley, */ /* FLASK */ /* * A security identifier table (sidtab) is a hash table * of security context structures indexed by SID value. */ #ifndef _SEPOL_POLICYDB_SIDTAB_H_ #define _SEPOL_POLICYDB_SIDTAB_H_ #include #ifdef __cplusplus extern "C" { #endif typedef struct sidtab_node { sepol_security_id_t sid; /* security identifier */ context_struct_t context; /* security context structure */ struct sidtab_node *next; } sidtab_node_t; typedef struct sidtab_node *sidtab_ptr_t; #define SIDTAB_HASH_BITS 7 #define SIDTAB_HASH_BUCKETS (1 << SIDTAB_HASH_BITS) #define SIDTAB_HASH_MASK (SIDTAB_HASH_BUCKETS-1) #define SIDTAB_SIZE SIDTAB_HASH_BUCKETS typedef struct { sidtab_ptr_t *htable; unsigned int nel; /* number of elements */ unsigned int next_sid; /* next SID to allocate */ unsigned char shutdown; } sidtab_t; extern int sepol_sidtab_init(sidtab_t * s); extern int sepol_sidtab_insert(sidtab_t * s, sepol_security_id_t sid, context_struct_t * context); extern context_struct_t *sepol_sidtab_search(sidtab_t * s, sepol_security_id_t sid); extern int sepol_sidtab_map(sidtab_t * s, int (*apply) (sepol_security_id_t sid, context_struct_t * context, void *args), void *args); extern void sepol_sidtab_map_remove_on_error(sidtab_t * s, int (*apply) (sepol_security_id_t s, context_struct_t * context, void *args), void *args); extern int sepol_sidtab_context_to_sid(sidtab_t * s, /* IN */ context_struct_t * context, /* IN */ sepol_security_id_t * sid); /* OUT */ extern void sepol_sidtab_hash_eval(sidtab_t * h, char *tag); extern void sepol_sidtab_destroy(sidtab_t * s); extern void sepol_sidtab_set(sidtab_t * dst, sidtab_t * src); extern void sepol_sidtab_shutdown(sidtab_t * s); #ifdef __cplusplus } #endif #endif /* _SIDTAB_H_ */ /* FLASK */ libsepol-3.8.1/include/sepol/policydb/symtab.h000066400000000000000000000021331476211737200213670ustar00rootroot00000000000000 /* Author : Stephen Smalley, */ /* FLASK */ /* * A symbol table (symtab) maintains associations between symbol * strings and datum values. The type of the datum values * is arbitrary. The symbol table type is implemented * using the hash table type (hashtab). */ #ifndef _SEPOL_POLICYDB_SYMTAB_H_ #define _SEPOL_POLICYDB_SYMTAB_H_ #include #ifdef __cplusplus extern "C" { #endif /* The symtab_datum struct stores the common information for * all symtab datums. It should the first element in every * struct that will be used in a symtab to allow the specific * datum types to be freely cast to this type. * * The values start at 1 - 0 is never a valid value. */ typedef struct symtab_datum { uint32_t value; } symtab_datum_t; typedef struct { hashtab_t table; /* hash table (keyed on a string) */ uint32_t nprim; /* number of primary names in table */ } symtab_t; extern int symtab_init(symtab_t *, unsigned int size); extern void symtab_destroy(symtab_t *); #ifdef __cplusplus } #endif #endif /* _SYMTAB_H_ */ /* FLASK */ libsepol-3.8.1/include/sepol/policydb/util.h000066400000000000000000000027721476211737200210560ustar00rootroot00000000000000/* Authors: Karl MacMillan * * A set of utility functions that aid policy decision when dealing * with hierarchal namespaces. * * Copyright (C) 2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __SEPOL_UTIL_H__ #define __SEPOL_UTIL_H__ #include #ifdef __cplusplus extern "C" { #endif extern int add_i_to_a(uint32_t i, uint32_t * cnt, uint32_t ** a); extern char *sepol_av_to_string(const policydb_t *policydbp, sepol_security_class_t tclass, sepol_access_vector_t av); char *sepol_extended_perms_to_string(const avtab_extended_perms_t *xperms); /* * The tokenize function may be used to * replace sscanf */ extern int tokenize(const char *line_buf, char delim, int num_args, ...); #ifdef __cplusplus } #endif #endif libsepol-3.8.1/include/sepol/port_record.h000066400000000000000000000037371476211737200206200ustar00rootroot00000000000000#ifndef _SEPOL_PORT_RECORD_H_ #define _SEPOL_PORT_RECORD_H_ #include #include #ifdef __cplusplus extern "C" { #endif struct sepol_port; struct sepol_port_key; typedef struct sepol_port sepol_port_t; typedef struct sepol_port_key sepol_port_key_t; #define SEPOL_PROTO_UDP 0 #define SEPOL_PROTO_TCP 1 #define SEPOL_PROTO_DCCP 2 #define SEPOL_PROTO_SCTP 3 /* Key */ extern int sepol_port_compare(const sepol_port_t * port, const sepol_port_key_t * key); extern int sepol_port_compare2(const sepol_port_t * port, const sepol_port_t * port2); extern int sepol_port_key_create(sepol_handle_t * handle, int low, int high, int proto, sepol_port_key_t ** key_ptr); extern void sepol_port_key_unpack(const sepol_port_key_t * key, int *low, int *high, int *proto); extern int sepol_port_key_extract(sepol_handle_t * handle, const sepol_port_t * port, sepol_port_key_t ** key_ptr); extern void sepol_port_key_free(sepol_port_key_t * key); /* Protocol */ extern int sepol_port_get_proto(const sepol_port_t * port); extern void sepol_port_set_proto(sepol_port_t * port, int proto); extern const char *sepol_port_get_proto_str(int proto); /* Port */ extern int sepol_port_get_low(const sepol_port_t * port); extern int sepol_port_get_high(const sepol_port_t * port); extern void sepol_port_set_port(sepol_port_t * port, int port_num); extern void sepol_port_set_range(sepol_port_t * port, int low, int high); /* Context */ extern sepol_context_t *sepol_port_get_con(const sepol_port_t * port); extern int sepol_port_set_con(sepol_handle_t * handle, sepol_port_t * port, sepol_context_t * con); /* Create/Clone/Destroy */ extern int sepol_port_create(sepol_handle_t * handle, sepol_port_t ** port_ptr); extern int sepol_port_clone(sepol_handle_t * handle, const sepol_port_t * port, sepol_port_t ** port_ptr); extern void sepol_port_free(sepol_port_t * port); #ifdef __cplusplus } #endif #endif libsepol-3.8.1/include/sepol/ports.h000066400000000000000000000024401476211737200174330ustar00rootroot00000000000000#ifndef _SEPOL_PORTS_H_ #define _SEPOL_PORTS_H_ #include #include #include #ifdef __cplusplus extern "C" { #endif /* Return the number of ports */ extern int sepol_port_count(sepol_handle_t * handle, const sepol_policydb_t * p, unsigned int *response); /* Check if a port exists */ extern int sepol_port_exists(sepol_handle_t * handle, const sepol_policydb_t * policydb, const sepol_port_key_t * key, int *response); /* Query a port - returns the port, or NULL if not found */ extern int sepol_port_query(sepol_handle_t * handle, const sepol_policydb_t * policydb, const sepol_port_key_t * key, sepol_port_t ** response); /* Modify a port, or add it, if the key is not found */ extern int sepol_port_modify(sepol_handle_t * handle, sepol_policydb_t * policydb, const sepol_port_key_t * key, const sepol_port_t * data); /* Iterate the ports * The handler may return: * -1 to signal an error condition, * 1 to signal successful exit * 0 to signal continue */ extern int sepol_port_iterate(sepol_handle_t * handle, const sepol_policydb_t * policydb, int (*fn) (const sepol_port_t * port, void *fn_arg), void *arg); #ifdef __cplusplus } #endif #endif libsepol-3.8.1/include/sepol/sepol.h000066400000000000000000000015361476211737200174130ustar00rootroot00000000000000#ifndef _SEPOL_H_ #define _SEPOL_H_ #include #include #ifdef __cplusplus extern "C" { #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* Set internal policydb from a file for subsequent service calls. */ extern int sepol_set_policydb_from_file(FILE * fp); #ifdef __cplusplus } #endif #endif libsepol-3.8.1/include/sepol/user_record.h000066400000000000000000000045201476211737200206010ustar00rootroot00000000000000#ifndef _SEPOL_USER_RECORD_H_ #define _SEPOL_USER_RECORD_H_ #include #include #ifdef __cplusplus extern "C" { #endif struct sepol_user; struct sepol_user_key; typedef struct sepol_user sepol_user_t; typedef struct sepol_user_key sepol_user_key_t; /* Key */ extern int sepol_user_key_create(sepol_handle_t * handle, const char *name, sepol_user_key_t ** key); extern void sepol_user_key_unpack(const sepol_user_key_t * key, const char **name); extern int sepol_user_key_extract(sepol_handle_t * handle, const sepol_user_t * user, sepol_user_key_t ** key_ptr); extern void sepol_user_key_free(sepol_user_key_t * key); extern int sepol_user_compare(const sepol_user_t * user, const sepol_user_key_t * key); extern int sepol_user_compare2(const sepol_user_t * user, const sepol_user_t * user2); /* Name */ extern const char *sepol_user_get_name(const sepol_user_t * user); extern int sepol_user_set_name(sepol_handle_t * handle, sepol_user_t * user, const char *name); /* MLS */ extern const char *sepol_user_get_mlslevel(const sepol_user_t * user); extern int sepol_user_set_mlslevel(sepol_handle_t * handle, sepol_user_t * user, const char *mls_level); extern const char *sepol_user_get_mlsrange(const sepol_user_t * user); extern int sepol_user_set_mlsrange(sepol_handle_t * handle, sepol_user_t * user, const char *mls_range); /* Role management */ extern int sepol_user_get_num_roles(const sepol_user_t * user); extern int sepol_user_add_role(sepol_handle_t * handle, sepol_user_t * user, const char *role); extern void sepol_user_del_role(sepol_user_t * user, const char *role); extern int sepol_user_has_role(const sepol_user_t * user, const char *role); extern int sepol_user_get_roles(sepol_handle_t * handle, const sepol_user_t * user, const char ***roles_arr, unsigned int *num_roles); extern int sepol_user_set_roles(sepol_handle_t * handle, sepol_user_t * user, const char **roles_arr, unsigned int num_roles); /* Create/Clone/Destroy */ extern int sepol_user_create(sepol_handle_t * handle, sepol_user_t ** user_ptr); extern int sepol_user_clone(sepol_handle_t * handle, const sepol_user_t * user, sepol_user_t ** user_ptr); extern void sepol_user_free(sepol_user_t * user); #ifdef __cplusplus } #endif #endif libsepol-3.8.1/include/sepol/users.h000066400000000000000000000024701476211737200174300ustar00rootroot00000000000000#ifndef _SEPOL_USERS_H_ #define _SEPOL_USERS_H_ #include #include #include #include #ifdef __cplusplus extern "C" { #endif /* Modify the user, or add it, if the key is not found */ extern int sepol_user_modify(sepol_handle_t * handle, sepol_policydb_t * policydb, const sepol_user_key_t * key, const sepol_user_t * data); /* Return the number of users */ extern int sepol_user_count(sepol_handle_t * handle, const sepol_policydb_t * p, unsigned int *response); /* Check if the specified user exists */ extern int sepol_user_exists(sepol_handle_t * handle, const sepol_policydb_t * policydb, const sepol_user_key_t * key, int *response); /* Query a user - returns the user or NULL if not found */ extern int sepol_user_query(sepol_handle_t * handle, const sepol_policydb_t * p, const sepol_user_key_t * key, sepol_user_t ** response); /* Iterate the users * The handler may return: * -1 to signal an error condition, * 1 to signal successful exit * 0 to signal continue */ extern int sepol_user_iterate(sepol_handle_t * handle, const sepol_policydb_t * policydb, int (*fn) (const sepol_user_t * user, void *fn_arg), void *arg); #ifdef __cplusplus } #endif #endif libsepol-3.8.1/man/000077500000000000000000000000001476211737200141215ustar00rootroot00000000000000libsepol-3.8.1/man/Makefile000066400000000000000000000014101476211737200155550ustar00rootroot00000000000000# Installation directories. LINGUAS ?= PREFIX ?= /usr MANDIR ?= $(PREFIX)/share/man MAN3SUBDIR ?= man3 MAN8SUBDIR ?= man8 MAN3DIR ?= $(MANDIR)/$(MAN3SUBDIR) MAN8DIR ?= $(MANDIR)/$(MAN8SUBDIR) all: install: all mkdir -p $(DESTDIR)$(MAN3DIR) mkdir -p $(DESTDIR)$(MAN8DIR) install -m 644 man3/*.3 $(DESTDIR)$(MAN3DIR) install -m 644 man8/*.8 $(DESTDIR)$(MAN8DIR) for lang in $(LINGUAS) ; do \ if [ -e $${lang}/man3 ] ; then \ mkdir -p $(DESTDIR)$(MANDIR)/$${lang}/$(MAN3SUBDIR) ; \ install -m 644 $${lang}/man3/*.3 $(DESTDIR)$(MANDIR)/$${lang}/$(MAN3SUBDIR) ; \ fi ; \ if [ -e $${lang}/man8 ] ; then \ mkdir -p $(DESTDIR)$(MANDIR)/$${lang}/$(MAN8SUBDIR) ; \ install -m 644 $${lang}/man8/*.8 $(DESTDIR)$(MANDIR)/$${lang}/$(MAN8SUBDIR) ; \ fi ; \ done libsepol-3.8.1/man/man3/000077500000000000000000000000001476211737200147575ustar00rootroot00000000000000libsepol-3.8.1/man/man3/sepol_check_context.3000066400000000000000000000015561476211737200210750ustar00rootroot00000000000000.TH "sepol_check_context" "3" "15 March 2005" "stephen.smalley.work@gmail.com" "SE Linux binary policy API documentation" .SH "NAME" sepol_check_context \- Check the validity of a security context against a binary policy. .SH "SYNOPSIS" .B #include .sp .BI "int sepol_check_context(const char *" context ");" .sp .BI "int sepol_set_policydb_from_file(FILE *" fp ");" .SH "DESCRIPTION" .B sepol_check_context checks the validity of a security context against a binary policy previously loaded from a file via .B sepol_set_policydb_from_file. It is used by .B setfiles -c to validate a file contexts configuration against the binary policy upon policy builds. For validating a context against the active policy on a SELinux system, use .B security_check_context from libselinux instead. .SH "RETURN VALUE" Returns 0 on success or \-1 with errno set otherwise. libsepol-3.8.1/man/man8/000077500000000000000000000000001476211737200147645ustar00rootroot00000000000000libsepol-3.8.1/man/man8/chkcon.8000066400000000000000000000031601476211737200163220ustar00rootroot00000000000000.\" Hey, Emacs! This is an -*- nroff -*- source file. .\" Copyright (c) 1997 Manoj Srivastava .\" .\" This is free documentation; you can redistribute it and/or .\" modify it under the terms of the GNU General Public License as .\" published by the Free Software Foundation; either version 2 of .\" the License, or (at your option) any later version. .\" .\" The GNU General Public License's references to "object code" .\" and "executables" are to be interpreted as the output of any .\" document formatting or typesetting system, including .\" intermediate and printed output. .\" .\" This manual is distributed in the hope that it will be useful, .\" but WITHOUT ANY WARRANTY; without even the implied warranty of .\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the .\" GNU General Public License for more details. .\" .\" You should have received a copy of the GNU General Public .\" License along with this manual; if not, write to the Free .\" Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, .\" USA. .\" .TH CHKCON 8 "Mar 12 2005" "SELinux" "SELinux Command Line documentation" .SH NAME chkcon \- determine if a security context is valid for a given binary policy .SH SYNOPSIS chkcon policy_file context .SH DESCRIPTION This utility validates (the string representation of) a security context specified by the argument .I context against configuration data read in from a policy database binary representation file specified by the argument .I policy_file. .SH FILES policy file .SH AUTHOR This manual page (and just the manual page) was written by Manoj Srivastava . libsepol-3.8.1/man/man8/genpolbools.8000066400000000000000000000010511476211737200173750ustar00rootroot00000000000000.TH "genpolbools" "8" "11 August 2004" "stephen.smalley.work@gmail.com" "SELinux Command Line documentation" .SH "NAME" genpolbools \- Rewrite a binary policy with different boolean settings .SH "SYNOPSIS" .B genpolbools oldpolicy booleans newpolicy .SH "DESCRIPTION" .B genpolbools rewrites an existing binary policy with different boolean settings, generating a new binary policy. The booleans file specifies the different boolean settings using name=value lines, where value can be 0 or false to disable the boolean or 1 or true to enable it. libsepol-3.8.1/man/man8/genpolusers.8000066400000000000000000000031331476211737200174230ustar00rootroot00000000000000.\" Hey, Emacs! This is an -*- nroff -*- source file. .\" Copyright (c) 1997 Manoj Srivastava .\" .\" This is free documentation; you can redistribute it and/or .\" modify it under the terms of the GNU General Public License as .\" published by the Free Software Foundation; either version 2 of .\" the License, or (at your option) any later version. .\" .\" The GNU General Public License's references to "object code" .\" and "executables" are to be interpreted as the output of any .\" document formatting or typesetting system, including .\" intermediate and printed output. .\" .\" This manual is distributed in the hope that it will be useful, .\" but WITHOUT ANY WARRANTY; without even the implied warranty of .\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the .\" GNU General Public License for more details. .\" .\" You should have received a copy of the GNU General Public .\" License along with this manual; if not, write to the Free .\" Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, .\" USA. .\" .TH GENPOLUSERS 8 "Mar 12 2005" "SELinux" "SELinux Command Line documentation" .SH NAME genpolusers \- Generate new binary policy with updated user configuration .SH SYNOPSIS genpolusers in-policy usersdir out-policy .SH DESCRIPTION Given an existing binary policy file .I in\-policy, generate a new binary policy .I out\-policy with an updated user configuration based on any .B system.users and .B local.users files in the specified .I usersdir. .SH AUTHOR This manual page (and just the manual page) was written by Manoj Srivastava . libsepol-3.8.1/src/000077500000000000000000000000001476211737200141355ustar00rootroot00000000000000libsepol-3.8.1/src/Makefile000066400000000000000000000057611476211737200156060ustar00rootroot00000000000000# Installation directories. PREFIX ?= /usr INCLUDEDIR ?= $(PREFIX)/include LIBDIR ?= $(PREFIX)/lib SHLIBDIR ?= /lib RANLIB ?= ranlib CILDIR ?= ../cil VERSION = $(shell cat ../VERSION) LIBVERSION = 2 LEX = flex CIL_GENERATED = $(CILDIR)/src/cil_lexer.c LIBA=libsepol.a TARGET=libsepol.so LIBPC=libsepol.pc LIBMAP=libsepol.map LIBSO=$(TARGET).$(LIBVERSION) OBJS= $(patsubst %.c,%.o,$(sort $(wildcard *.c))) LOBJS= $(patsubst %.c,%.lo,$(sort $(wildcard *.c))) CFLAGS ?= -Werror -Wall -W -Wundef -Wshadow -Wmissing-format-attribute -O2 -fno-semantic-interposition override CFLAGS += -I. -I../include -D_GNU_SOURCE ifneq ($(DISABLE_CIL),y) OBJS += $(sort $(patsubst %.c,%.o,$(sort $(wildcard $(CILDIR)/src/*.c)) $(CIL_GENERATED))) LOBJS += $(sort $(patsubst %.c,%.lo,$(sort $(wildcard $(CILDIR)/src/*.c)) $(CIL_GENERATED))) override CFLAGS += -I$(CILDIR)/include endif # check for reallocarray(3) availability H := \# ifeq (yes,$(shell printf '${H}include \nint main(void){return reallocarray(NULL,0,0)==NULL;}' | $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -Werror=implicit-function-declaration -x c -o /dev/null - >/dev/null 2>&1 && echo yes)) override CFLAGS += -DHAVE_REALLOCARRAY endif LD_SONAME_FLAGS=-soname,$(LIBSO),--version-script=$(LIBMAP),-z,defs LN=ln OS := $(shell uname) ifeq ($(OS), Darwin) LD_SONAME_FLAGS=-install_name,$(LIBSO) LDFLAGS += -undefined dynamic_lookup LN=gln endif all: $(LIBA) $(LIBSO) $(LIBPC) $(LIBA): $(OBJS) $(AR) rcs $@ $^ $(RANLIB) $@ $(LIBSO): $(LOBJS) $(LIBMAP) $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -shared -o $@ $(LOBJS) -Wl,$(LD_SONAME_FLAGS) ln -sf $@ $(TARGET) $(LIBPC): $(LIBPC).in ../VERSION sed -e 's/@VERSION@/$(VERSION)/; s:@prefix@:$(PREFIX):; s:@libdir@:$(LIBDIR):; s:@includedir@:$(INCLUDEDIR):' < $< > $@ $(LIBMAP): $(LIBMAP).in ifneq ($(DISABLE_CIL),y) cp $< $@ else sed -e '/^\s*cil_/d' < $< > $@ endif ifneq ($(DISABLE_CIL),y) $(CILDIR)/src/cil_lexer.o: $(CILDIR)/src/cil_lexer.c $(CC) $(filter-out -Werror, $(CPPFLAGS) $(CFLAGS)) -fPIC -c -o $@ $< $(CILDIR)/src/cil_lexer.lo: $(CILDIR)/src/cil_lexer.c $(CC) $(filter-out -Werror, $(CPPFLAGS) $(CFLAGS)) -fPIC -DSHARED -c -o $@ $< $(CILDIR)/src/cil_lexer.c: $(CILDIR)/src/cil_lexer.l $(LEX) -o $@ $< endif %.o: %.c $(CC) $(CPPFLAGS) $(CFLAGS) -fPIC -c -o $@ $< %.lo: %.c $(CC) $(CPPFLAGS) $(CFLAGS) -fPIC -DSHARED -c -o $@ $< install: all test -d $(DESTDIR)$(LIBDIR) || install -m 755 -d $(DESTDIR)$(LIBDIR) install -m 644 $(LIBA) $(DESTDIR)$(LIBDIR) test -d $(DESTDIR)$(SHLIBDIR) || install -m 755 -d $(DESTDIR)$(SHLIBDIR) install -m 755 $(LIBSO) $(DESTDIR)$(SHLIBDIR) test -d $(DESTDIR)$(LIBDIR)/pkgconfig || install -m 755 -d $(DESTDIR)$(LIBDIR)/pkgconfig install -m 644 $(LIBPC) $(DESTDIR)$(LIBDIR)/pkgconfig $(LN) -sf --relative $(DESTDIR)$(SHLIBDIR)/$(LIBSO) $(DESTDIR)$(LIBDIR)/$(TARGET) relabel: /sbin/restorecon $(DESTDIR)$(SHLIBDIR)/$(LIBSO) clean: -rm -f $(LIBPC) $(LIBMAP) $(OBJS) $(LOBJS) $(LIBA) $(LIBSO) $(TARGET) $(CIL_GENERATED) indent: ../../scripts/Lindent $(wildcard *.[ch]) libsepol-3.8.1/src/assertion.c000066400000000000000000000617201476211737200163160ustar00rootroot00000000000000/* Authors: Joshua Brindle * * Assertion checker for avtab entries, taken from * checkpolicy.c by Stephen Smalley * * Copyright (C) 2005 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include "private.h" #include "debug.h" struct avtab_match_args { sepol_handle_t *handle; policydb_t *p; const avrule_t *narule; unsigned long errors; bool conditional; }; static const char* policy_name(const policydb_t *p) { return p->name ?: "policy.conf"; } static void report_failure(sepol_handle_t *handle, const policydb_t *p, const avrule_t *narule, unsigned int stype, unsigned int ttype, const class_perm_node_t *curperm, uint32_t perms) { char *permstr = sepol_av_to_string(p, curperm->tclass, perms); if (narule->source_filename) { ERR(handle, "neverallow on line %lu of %s (or line %lu of %s) violated by allow %s %s:%s {%s };", narule->source_line, narule->source_filename, narule->line, policy_name(p), p->p_type_val_to_name[stype], p->p_type_val_to_name[ttype], p->p_class_val_to_name[curperm->tclass - 1], permstr ?: ""); } else if (narule->line) { ERR(handle, "neverallow on line %lu violated by allow %s %s:%s {%s };", narule->line, p->p_type_val_to_name[stype], p->p_type_val_to_name[ttype], p->p_class_val_to_name[curperm->tclass - 1], permstr ?: ""); } else { ERR(handle, "neverallow violated by allow %s %s:%s {%s };", p->p_type_val_to_name[stype], p->p_type_val_to_name[ttype], p->p_class_val_to_name[curperm->tclass - 1], permstr ?: ""); } free(permstr); } static bool match_any_class_permissions(const class_perm_node_t *cp, uint32_t class, uint32_t data) { for (; cp; cp = cp->next) { if ((cp->tclass == class) && (cp->data & data)) return true; } return false; } static bool extended_permissions_and(const uint32_t *perms1, const uint32_t *perms2) { size_t i; for (i = 0; i < EXTENDED_PERMS_LEN; i++) { if (perms1[i] & perms2[i]) return true; } return false; } static bool check_extended_permissions(const av_extended_perms_t *neverallow, const avtab_extended_perms_t *allow) { bool rc = false; if ((neverallow->specified == AVRULE_XPERMS_IOCTLFUNCTION) && (allow->specified == AVTAB_XPERMS_IOCTLFUNCTION)) { if (neverallow->driver == allow->driver) rc = extended_permissions_and(neverallow->perms, allow->perms); } else if ((neverallow->specified == AVRULE_XPERMS_IOCTLFUNCTION) && (allow->specified == AVTAB_XPERMS_IOCTLDRIVER)) { rc = xperm_test(neverallow->driver, allow->perms); } else if ((neverallow->specified == AVRULE_XPERMS_IOCTLDRIVER) && (allow->specified == AVTAB_XPERMS_IOCTLFUNCTION)) { rc = xperm_test(allow->driver, neverallow->perms); } else if ((neverallow->specified == AVRULE_XPERMS_IOCTLDRIVER) && (allow->specified == AVTAB_XPERMS_IOCTLDRIVER)) { rc = extended_permissions_and(neverallow->perms, allow->perms); } else if ((neverallow->specified == AVRULE_XPERMS_NLMSG) && (allow->specified == AVTAB_XPERMS_NLMSG)) { if (neverallow->driver == allow->driver) rc = extended_permissions_and(neverallow->perms, allow->perms); } return rc; } /* Compute which allowed extended permissions violate the neverallow rule */ static void extended_permissions_violated(avtab_extended_perms_t *result, const av_extended_perms_t *neverallow, const avtab_extended_perms_t *allow) { size_t i; if ((neverallow->specified == AVRULE_XPERMS_IOCTLFUNCTION) && (allow->specified == AVTAB_XPERMS_IOCTLFUNCTION)) { result->specified = AVTAB_XPERMS_IOCTLFUNCTION; result->driver = allow->driver; for (i = 0; i < EXTENDED_PERMS_LEN; i++) result->perms[i] = neverallow->perms[i] & allow->perms[i]; } else if ((neverallow->specified == AVRULE_XPERMS_IOCTLFUNCTION) && (allow->specified == AVTAB_XPERMS_IOCTLDRIVER)) { result->specified = AVTAB_XPERMS_IOCTLFUNCTION; result->driver = neverallow->driver; memcpy(result->perms, neverallow->perms, sizeof(result->perms)); } else if ((neverallow->specified == AVRULE_XPERMS_IOCTLDRIVER) && (allow->specified == AVTAB_XPERMS_IOCTLFUNCTION)) { result->specified = AVTAB_XPERMS_IOCTLFUNCTION; result->driver = allow->driver; memcpy(result->perms, allow->perms, sizeof(result->perms)); } else if ((neverallow->specified == AVRULE_XPERMS_IOCTLDRIVER) && (allow->specified == AVTAB_XPERMS_IOCTLDRIVER)) { result->specified = AVTAB_XPERMS_IOCTLDRIVER; for (i = 0; i < EXTENDED_PERMS_LEN; i++) result->perms[i] = neverallow->perms[i] & allow->perms[i]; } else if ((neverallow->specified == AVRULE_XPERMS_NLMSG) && (allow->specified == AVTAB_XPERMS_NLMSG)) { result->specified = AVTAB_XPERMS_NLMSG; result->driver = allow->driver; for (i = 0; i < EXTENDED_PERMS_LEN; i++) result->perms[i] = neverallow->perms[i] & allow->perms[i]; } } static bool match_node_key(const struct avtab_node *node, const avtab_key_t *key) { return node->key.source_type == key->source_type && node->key.target_type == key->target_type && node->key.target_class == key->target_class; } /* Same scenarios of interest as check_assertion_extended_permissions */ static int report_assertion_extended_permissions(sepol_handle_t *handle, policydb_t *p, const avrule_t *narule, unsigned int stype, unsigned int ttype, const class_perm_node_t *curperm, uint32_t perms, const avtab_key_t *k, bool conditional) { avtab_ptr_t node; avtab_key_t tmp_key; avtab_extended_perms_t *xperms; avtab_extended_perms_t error; const ebitmap_t *sattr = &p->type_attr_map[stype]; const ebitmap_t *tattr = &p->type_attr_map[ttype]; ebitmap_node_t *snode, *tnode; unsigned int i, j; bool found_xperm = false, found_cond_conflict = false; int errors = 0; memcpy(&tmp_key, k, sizeof(avtab_key_t)); tmp_key.specified = AVTAB_XPERMS_ALLOWED; ebitmap_for_each_positive_bit(sattr, snode, i) { tmp_key.source_type = i + 1; ebitmap_for_each_positive_bit(tattr, tnode, j) { tmp_key.target_type = j + 1; for (node = avtab_search_node(&p->te_avtab, &tmp_key); node; node = avtab_search_node_next(node, tmp_key.specified)) { xperms = node->datum.xperms; if ((xperms->specified != AVTAB_XPERMS_IOCTLFUNCTION) && (xperms->specified != AVTAB_XPERMS_IOCTLDRIVER) && (xperms->specified != AVTAB_XPERMS_NLMSG)) continue; found_xperm = true; /* failure on the extended permission check_extended_permissions */ if (check_extended_permissions(narule->xperms, xperms)) { char *permstring; extended_permissions_violated(&error, narule->xperms, xperms); permstring = sepol_extended_perms_to_string(&error); ERR(handle, "neverallowxperm on line %lu of %s (or line %lu of %s) violated by\n" " allowxperm %s %s:%s %s;", narule->source_line, narule->source_filename, narule->line, policy_name(p), p->p_type_val_to_name[i], p->p_type_val_to_name[j], p->p_class_val_to_name[curperm->tclass - 1], permstring ?: ""); free(permstring); errors++; } } for (const cond_list_t *cl = p->cond_list; cl; cl = cl->next) { bool found_true_base = false, found_true_xperm = false; bool found_false_base = false, found_false_xperm = false; for (const cond_av_list_t *cal = cl->true_list; cal; cal = cal->next) { node = cal->node; /* node->next is not from the same condition */ if (!node) continue; if (!match_node_key(node, &tmp_key)) continue; if (match_any_class_permissions(narule->perms, node->key.target_class, node->datum.data)) { found_true_base = true; continue; } if (!(node->key.specified & AVTAB_XPERMS_ALLOWED)) continue; xperms = node->datum.xperms; if ((xperms->specified != AVTAB_XPERMS_IOCTLFUNCTION) && (xperms->specified != AVTAB_XPERMS_IOCTLDRIVER) && (xperms->specified != AVTAB_XPERMS_NLMSG)) continue; found_true_xperm = true; /* failure on the extended permission check_extended_permissions */ if (check_extended_permissions(narule->xperms, xperms)) { char *permstring; extended_permissions_violated(&error, narule->xperms, xperms); permstring = sepol_extended_perms_to_string(&error); ERR(handle, "neverallowxperm on line %lu of %s (or line %lu of %s) violated by\n" " allowxperm %s %s:%s %s;", narule->source_line, narule->source_filename, narule->line, policy_name(p), p->p_type_val_to_name[i], p->p_type_val_to_name[j], p->p_class_val_to_name[curperm->tclass - 1], permstring ?: ""); free(permstring); errors++; } } for (const cond_av_list_t *cal = cl->false_list; cal; cal = cal->next) { node = cal->node; /* node->next is not from the same condition */ if (!node) continue; if (!match_node_key(node, &tmp_key)) continue; if (match_any_class_permissions(narule->perms, node->key.target_class, node->datum.data)) { found_false_base = true; continue; } if (!(node->key.specified & AVTAB_XPERMS_ALLOWED)) continue; xperms = node->datum.xperms; if ((xperms->specified != AVTAB_XPERMS_IOCTLFUNCTION) && (xperms->specified != AVTAB_XPERMS_IOCTLDRIVER) && (xperms->specified != AVTAB_XPERMS_NLMSG)) continue; found_false_xperm = true; /* failure on the extended permission check_extended_permissions */ if (check_extended_permissions(narule->xperms, xperms)) { char *permstring; extended_permissions_violated(&error, narule->xperms, xperms); permstring = sepol_extended_perms_to_string(&error); ERR(handle, "neverallowxperm on line %lu of %s (or line %lu of %s) violated by\n" " allowxperm %s %s:%s %s;", narule->source_line, narule->source_filename, narule->line, policy_name(p), p->p_type_val_to_name[i], p->p_type_val_to_name[j], p->p_class_val_to_name[curperm->tclass - 1], permstring ?: ""); free(permstring); errors++; } } if (found_true_xperm && found_false_xperm) found_xperm = true; else if (conditional && ((found_true_base && !found_true_xperm) || (found_false_base && !found_false_xperm))) found_cond_conflict = true; } } } if ((!found_xperm && !conditional) || found_cond_conflict) { /* failure on the regular permissions */ char *permstr = sepol_av_to_string(p, curperm->tclass, perms); ERR(handle, "neverallowxperm on line %lu of %s (or line %lu of %s) violated by\n" " allow %s %s:%s {%s };", narule->source_line, narule->source_filename, narule->line, policy_name(p), p->p_type_val_to_name[stype], p->p_type_val_to_name[ttype], p->p_class_val_to_name[curperm->tclass - 1], permstr ?: ""); free(permstr); errors++; } return errors; } static int report_assertion_avtab_matches(avtab_key_t *k, avtab_datum_t *d, void *args) { int rc = 0; struct avtab_match_args *a = (struct avtab_match_args *)args; sepol_handle_t *handle = a->handle; policydb_t *p = a->p; const avrule_t *narule = a->narule; const class_perm_node_t *cp; uint32_t perms; ebitmap_t src_matches, tgt_matches, self_matches; ebitmap_node_t *snode, *tnode; unsigned int i, j; const bool is_narule_self = (narule->flags & RULE_SELF) != 0; const bool is_narule_notself = (narule->flags & RULE_NOTSELF) != 0; if ((k->specified & AVTAB_ALLOWED) == 0) return 0; if (!match_any_class_permissions(narule->perms, k->target_class, d->data)) return 0; ebitmap_init(&src_matches); ebitmap_init(&tgt_matches); ebitmap_init(&self_matches); rc = ebitmap_and(&src_matches, &narule->stypes.types, &p->attr_type_map[k->source_type - 1]); if (rc < 0) goto oom; if (ebitmap_is_empty(&src_matches)) goto exit; if (is_narule_notself) { if (ebitmap_is_empty(&narule->ttypes.types)) { /* avrule tgt is of the form ~self */ rc = ebitmap_cpy(&tgt_matches, &p->attr_type_map[k->target_type -1]); } else { /* avrule tgt is of the form {ATTR -self} */ rc = ebitmap_and(&tgt_matches, &narule->ttypes.types, &p->attr_type_map[k->target_type - 1]); } if (rc) goto oom; } else { rc = ebitmap_and(&tgt_matches, &narule->ttypes.types, &p->attr_type_map[k->target_type -1]); if (rc < 0) goto oom; if (is_narule_self) { rc = ebitmap_and(&self_matches, &src_matches, &p->attr_type_map[k->target_type - 1]); if (rc < 0) goto oom; if (!ebitmap_is_empty(&self_matches)) { rc = ebitmap_union(&tgt_matches, &self_matches); if (rc < 0) goto oom; } } } if (ebitmap_is_empty(&tgt_matches)) goto exit; for (cp = narule->perms; cp; cp = cp->next) { perms = cp->data & d->data; if ((cp->tclass != k->target_class) || !perms) { continue; } ebitmap_for_each_positive_bit(&src_matches, snode, i) { ebitmap_for_each_positive_bit(&tgt_matches, tnode, j) { if (is_narule_self && i != j) continue; if (is_narule_notself && i == j) continue; if (narule->specified == AVRULE_XPERMS_NEVERALLOW) { a->errors += report_assertion_extended_permissions(handle,p, narule, i, j, cp, perms, k, a->conditional); } else { a->errors++; report_failure(handle, p, narule, i, j, cp, perms); } } } } oom: exit: ebitmap_destroy(&src_matches); ebitmap_destroy(&tgt_matches); ebitmap_destroy(&self_matches); return rc; } static int report_assertion_failures(sepol_handle_t *handle, policydb_t *p, const avrule_t *narule) { int rc; struct avtab_match_args args = { .handle = handle, .p = p, .narule = narule, .errors = 0, }; args.conditional = false; rc = avtab_map(&p->te_avtab, report_assertion_avtab_matches, &args); if (rc < 0) goto oom; args.conditional = true; rc = avtab_map(&p->te_cond_avtab, report_assertion_avtab_matches, &args); if (rc < 0) goto oom; return args.errors; oom: return rc; } /* * Look up the extended permissions in avtab and verify that neverallowed * permissions are not granted. */ static bool check_assertion_extended_permissions_avtab(const avrule_t *narule, unsigned int stype, unsigned int ttype, const avtab_key_t *k, policydb_t *p, bool conditional) { avtab_ptr_t node; avtab_key_t tmp_key; const avtab_extended_perms_t *xperms; const av_extended_perms_t *neverallow_xperms = narule->xperms; const ebitmap_t *sattr = &p->type_attr_map[stype]; const ebitmap_t *tattr = &p->type_attr_map[ttype]; ebitmap_node_t *snode, *tnode; unsigned int i, j; bool found_xperm = false, found_cond_conflict = false; memcpy(&tmp_key, k, sizeof(avtab_key_t)); tmp_key.specified = AVTAB_XPERMS_ALLOWED; ebitmap_for_each_positive_bit(sattr, snode, i) { tmp_key.source_type = i + 1; ebitmap_for_each_positive_bit(tattr, tnode, j) { tmp_key.target_type = j + 1; for (node = avtab_search_node(&p->te_avtab, &tmp_key); node; node = avtab_search_node_next(node, tmp_key.specified)) { xperms = node->datum.xperms; if ((xperms->specified != AVTAB_XPERMS_IOCTLFUNCTION) && (xperms->specified != AVTAB_XPERMS_IOCTLDRIVER) && (xperms->specified != AVTAB_XPERMS_NLMSG)) continue; found_xperm = true; if (check_extended_permissions(neverallow_xperms, xperms)) return true; } for (const cond_list_t *cl = p->cond_list; cl; cl = cl->next) { bool found_true_base = false, found_true_xperm = false; bool found_false_base = false, found_false_xperm = false; for (const cond_av_list_t *cal = cl->true_list; cal; cal = cal->next) { node = cal->node; /* node->next is not from the same condition */ if (!node) continue; if (!match_node_key(node, &tmp_key)) continue; if ((node->key.specified & AVTAB_ALLOWED) && match_any_class_permissions(narule->perms, node->key.target_class, node->datum.data)) { found_true_base = true; continue; } if (!(node->key.specified & AVTAB_XPERMS_ALLOWED)) continue; xperms = node->datum.xperms; if ((xperms->specified != AVTAB_XPERMS_IOCTLFUNCTION) && (xperms->specified != AVTAB_XPERMS_IOCTLDRIVER) && (xperms->specified != AVTAB_XPERMS_NLMSG)) continue; found_true_xperm = true; if (check_extended_permissions(neverallow_xperms, xperms)) return true; } for (const cond_av_list_t *cal = cl->false_list; cal; cal = cal->next) { node = cal->node; /* node->next is not from the same condition */ if (!node) continue; if (!match_node_key(node, &tmp_key)) continue; if ((node->key.specified & AVTAB_ALLOWED) && match_any_class_permissions(narule->perms, node->key.target_class, node->datum.data)) { found_false_base = true; continue; } if (!(node->key.specified & AVTAB_XPERMS_ALLOWED)) continue; xperms = node->datum.xperms; if ((xperms->specified != AVTAB_XPERMS_IOCTLFUNCTION) && (xperms->specified != AVTAB_XPERMS_IOCTLDRIVER) && (xperms->specified != AVTAB_XPERMS_NLMSG)) continue; found_false_xperm = true; if (check_extended_permissions(neverallow_xperms, xperms)) return true; } if (found_true_xperm && found_false_xperm) found_xperm = true; else if (conditional && ((found_true_base && !found_true_xperm) || (found_false_base && !found_false_xperm))) found_cond_conflict = true; } } } return (!conditional && !found_xperm) || found_cond_conflict; } /* * When the ioctl permission is granted on an avtab entry that matches an * avrule neverallowxperm entry, enumerate over the matching * source/target/class sets to determine if the extended permissions exist * and if the neverallowed ioctls are granted. * * Four scenarios of interest: * 1. PASS - the ioctl permission is not granted for this source/target/class * This case is handled in check_assertion_avtab_match * 2. PASS - The ioctl permission is granted AND the extended permission * is NOT granted * 3. FAIL - The ioctl permission is granted AND no extended permissions * exist * 4. FAIL - The ioctl permission is granted AND the extended permission is * granted */ static int check_assertion_extended_permissions(const avrule_t *narule, const avtab_key_t *k, policydb_t *p, bool conditional) { ebitmap_t src_matches, tgt_matches, self_matches; unsigned int i, j; ebitmap_node_t *snode, *tnode; const bool is_narule_self = (narule->flags & RULE_SELF) != 0; const bool is_narule_notself = (narule->flags & RULE_NOTSELF) != 0; int rc; ebitmap_init(&src_matches); ebitmap_init(&tgt_matches); ebitmap_init(&self_matches); rc = ebitmap_and(&src_matches, &narule->stypes.types, &p->attr_type_map[k->source_type - 1]); if (rc < 0) goto oom; if (ebitmap_is_empty(&src_matches)) { rc = 0; goto exit; } if (is_narule_notself) { if (ebitmap_is_empty(&narule->ttypes.types)) { /* avrule tgt is of the form ~self */ rc = ebitmap_cpy(&tgt_matches, &p->attr_type_map[k->target_type -1]); } else { /* avrule tgt is of the form {ATTR -self} */ rc = ebitmap_and(&tgt_matches, &narule->ttypes.types, &p->attr_type_map[k->target_type - 1]); } if (rc < 0) goto oom; } else { rc = ebitmap_and(&tgt_matches, &narule->ttypes.types, &p->attr_type_map[k->target_type -1]); if (rc < 0) goto oom; if (is_narule_self) { rc = ebitmap_and(&self_matches, &src_matches, &p->attr_type_map[k->target_type - 1]); if (rc < 0) goto oom; if (!ebitmap_is_empty(&self_matches)) { rc = ebitmap_union(&tgt_matches, &self_matches); if (rc < 0) goto oom; } } } if (ebitmap_is_empty(&tgt_matches)) { rc = 0; goto exit; } ebitmap_for_each_positive_bit(&src_matches, snode, i) { ebitmap_for_each_positive_bit(&tgt_matches, tnode, j) { if (is_narule_self && i != j) continue; if (is_narule_notself && i == j) continue; if (check_assertion_extended_permissions_avtab(narule, i, j, k, p, conditional)) { rc = 1; goto exit; } } } rc = 0; oom: exit: ebitmap_destroy(&src_matches); ebitmap_destroy(&tgt_matches); ebitmap_destroy(&self_matches); return rc; } static int check_assertion_notself_match(const avtab_key_t *k, const avrule_t *narule, policydb_t *p) { ebitmap_t src_matches, tgt_matches; unsigned int num_src_matches, num_tgt_matches; int rc; ebitmap_init(&src_matches); ebitmap_init(&tgt_matches); rc = ebitmap_and(&src_matches, &narule->stypes.types, &p->attr_type_map[k->source_type - 1]); if (rc < 0) goto oom; if (ebitmap_is_empty(&narule->ttypes.types)) { /* avrule tgt is of the form ~self */ rc = ebitmap_cpy(&tgt_matches, &p->attr_type_map[k->target_type - 1]); } else { /* avrule tgt is of the form {ATTR -self} */ rc = ebitmap_and(&tgt_matches, &narule->ttypes.types, &p->attr_type_map[k->target_type - 1]); } if (rc < 0) goto oom; num_src_matches = ebitmap_cardinality(&src_matches); num_tgt_matches = ebitmap_cardinality(&tgt_matches); if (num_src_matches == 0 || num_tgt_matches == 0) { rc = 0; goto nomatch; } if (num_src_matches == 1 && num_tgt_matches == 1) { ebitmap_t matches; unsigned int num_matches; rc = ebitmap_and(&matches, &src_matches, &tgt_matches); if (rc < 0) { ebitmap_destroy(&matches); goto oom; } num_matches = ebitmap_cardinality(&matches); ebitmap_destroy(&matches); if (num_matches == 1) { /* The only non-match is of the form TYPE TYPE */ rc = 0; goto nomatch; } } rc = 1; oom: nomatch: ebitmap_destroy(&src_matches); ebitmap_destroy(&tgt_matches); return rc; } static int check_assertion_self_match(const avtab_key_t *k, const avrule_t *narule, policydb_t *p) { ebitmap_t src_matches; int rc; /* The key's target must match something in the matches of the avrule's source * and the key's source. */ rc = ebitmap_and(&src_matches, &narule->stypes.types, &p->attr_type_map[k->source_type - 1]); if (rc < 0) goto oom; if (!ebitmap_match_any(&src_matches, &p->attr_type_map[k->target_type - 1])) { rc = 0; goto nomatch; } rc = 1; oom: nomatch: ebitmap_destroy(&src_matches); return rc; } static int check_assertion_avtab_match(avtab_key_t *k, avtab_datum_t *d, void *args) { int rc; struct avtab_match_args *a = (struct avtab_match_args *)args; policydb_t *p = a->p; const avrule_t *narule = a->narule; if ((k->specified & AVTAB_ALLOWED) == 0) goto nomatch; if (!match_any_class_permissions(narule->perms, k->target_class, d->data)) goto nomatch; if (!ebitmap_match_any(&narule->stypes.types, &p->attr_type_map[k->source_type - 1])) goto nomatch; if (narule->flags & RULE_NOTSELF) { rc = check_assertion_notself_match(k, narule, p); if (rc < 0) goto oom; if (rc == 0) goto nomatch; } else { /* neverallow may have tgts even if it uses SELF */ if (!ebitmap_match_any(&narule->ttypes.types, &p->attr_type_map[k->target_type -1])) { if (narule->flags == RULE_SELF) { rc = check_assertion_self_match(k, narule, p); if (rc < 0) goto oom; if (rc == 0) goto nomatch; } else { goto nomatch; } } } if (narule->specified == AVRULE_XPERMS_NEVERALLOW) { rc = check_assertion_extended_permissions(narule, k, p, a->conditional); if (rc < 0) goto oom; if (rc == 0) goto nomatch; } return 1; nomatch: return 0; oom: return rc; } int check_assertion(policydb_t *p, const avrule_t *narule) { int rc; struct avtab_match_args args = { .handle = NULL, .p = p, .narule = narule, .errors = 0, }; args.conditional = false; rc = avtab_map(&p->te_avtab, check_assertion_avtab_match, &args); if (rc == 0) { args.conditional = true; rc = avtab_map(&p->te_cond_avtab, check_assertion_avtab_match, &args); } return rc; } int check_assertions(sepol_handle_t * handle, policydb_t * p, const avrule_t * narules) { int rc; const avrule_t *a; unsigned long errors = 0; for (a = narules; a != NULL; a = a->next) { if (!(a->specified & (AVRULE_NEVERALLOW | AVRULE_XPERMS_NEVERALLOW))) continue; rc = check_assertion(p, a); if (rc < 0) { ERR(handle, "Error occurred while checking neverallows"); return -1; } if (rc) { rc = report_assertion_failures(handle, p, a); if (rc < 0) { ERR(handle, "Error occurred while checking neverallows"); return -1; } errors += rc; } } if (errors) ERR(handle, "%lu neverallow failures occurred", errors); return errors ? -1 : 0; } libsepol-3.8.1/src/avrule_block.c000066400000000000000000000124671476211737200167630ustar00rootroot00000000000000/* Authors: Jason Tang * * Functions that manipulate a logical block (conditional, optional, * or global scope) for a policy module. * * Copyright (C) 2005 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include /* It is anticipated that there be less declarations within an avrule * block than the global policy. Thus the symbol table sizes are * smaller than those listed in policydb.c */ static const unsigned int symtab_sizes[SYM_NUM] = { 2, 4, 8, 32, 16, 4, 2, 2, }; avrule_block_t *avrule_block_create(void) { avrule_block_t *block; if ((block = calloc(1, sizeof(*block))) == NULL) { return NULL; } return block; } avrule_decl_t *avrule_decl_create(uint32_t decl_id) { avrule_decl_t *decl; int i; if ((decl = calloc(1, sizeof(*decl))) == NULL) { return NULL; } decl->decl_id = decl_id; for (i = 0; i < SYM_NUM; i++) { if (symtab_init(&decl->symtab[i], symtab_sizes[i])) { avrule_decl_destroy(decl); return NULL; } } for (i = 0; i < SYM_NUM; i++) { ebitmap_init(&decl->required.scope[i]); ebitmap_init(&decl->declared.scope[i]); } return decl; } /* note that unlike the other destroy functions, this one does /NOT/ * destroy the pointer itself */ static void scope_index_destroy(scope_index_t * scope) { unsigned int i; if (scope == NULL) { return; } for (i = 0; i < SYM_NUM; i++) { ebitmap_destroy(scope->scope + i); } if (scope->class_perms_map) { for (i = 0; i < scope->class_perms_len; i++) { ebitmap_destroy(scope->class_perms_map + i); } } free(scope->class_perms_map); } void avrule_decl_destroy(avrule_decl_t * x) { if (x == NULL) { return; } cond_list_destroy(x->cond_list); avrule_list_destroy(x->avrules); role_trans_rule_list_destroy(x->role_tr_rules); filename_trans_rule_list_destroy(x->filename_trans_rules); role_allow_rule_list_destroy(x->role_allow_rules); range_trans_rule_list_destroy(x->range_tr_rules); scope_index_destroy(&x->required); scope_index_destroy(&x->declared); symtabs_destroy(x->symtab); free(x->module_name); free(x); } void avrule_block_destroy(avrule_block_t * x) { avrule_decl_t *decl; if (x == NULL) { return; } decl = x->branch_list; while (decl != NULL) { avrule_decl_t *next_decl = decl->next; avrule_decl_destroy(decl); decl = next_decl; } free(x); } void avrule_block_list_destroy(avrule_block_t * x) { while (x != NULL) { avrule_block_t *next = x->next; avrule_block_destroy(x); x = next; } } /* Get a conditional node from a avrule_decl with the same expression. * If that expression does not exist then create one. */ cond_list_t *get_decl_cond_list(policydb_t * p, avrule_decl_t * decl, cond_list_t * cond) { cond_list_t *result; int was_created; result = cond_node_find(p, cond, decl->cond_list, &was_created); if (result != NULL && was_created) { result->next = decl->cond_list; decl->cond_list = result; } return result; } /* Look up an identifier in a policy's scoping table. If it is there, * marked as SCOPE_DECL, and any of its declaring block has been enabled, * then return 1. Otherwise return 0. Can only be called after the * decl_val_to_struct index has been created */ int is_id_enabled(const char *id, const policydb_t * p, int symbol_table) { const scope_datum_t *scope = (scope_datum_t *) hashtab_search(p->scope[symbol_table].table, id); const avrule_decl_t *decl; uint32_t len; if (scope == NULL) { return 0; } if (scope->scope != SCOPE_DECL) { return 0; } len = scope->decl_ids_len; if (len < 1) { return 0; } if (symbol_table == SYM_ROLES || symbol_table == SYM_USERS) { uint32_t i; for (i = 0; i < len; i++) { decl = p->decl_val_to_struct[scope->decl_ids[i] - 1]; if (decl != NULL && decl->enabled) { return 1; } } } else { decl = p->decl_val_to_struct[scope->decl_ids[len-1] - 1]; if (decl != NULL && decl->enabled) { return 1; } } return 0; } /* Check if a particular permission is present within the given class. * Whether the class is enabled is NOT checked. * Returns 1 if permission is present, 0 otherwise */ int is_perm_existent(const class_datum_t *cladatum, const char *perm_id) { const perm_datum_t *perm; perm = hashtab_search(cladatum->permissions.table, perm_id); if (perm == NULL && cladatum->comdatum != 0) { /* permission was not in this class. before giving * up, check the class's parent */ perm = hashtab_search(cladatum->comdatum->permissions.table, perm_id); } if (perm == NULL) { return 0; } return 1; } libsepol-3.8.1/src/avtab.c000066400000000000000000000364701476211737200154100ustar00rootroot00000000000000 /* Author : Stephen Smalley, */ /* * Updated: Yuichi Nakamura * Tuned number of hash slots for avtab to reduce memory usage */ /* Updated: Frank Mayer * and Karl MacMillan * * Added conditional policy language extensions * * Updated: Red Hat, Inc. James Morris * * Code cleanup * * Updated: Karl MacMillan * * Copyright (C) 2003 Tresys Technology, LLC * Copyright (C) 2003,2007 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* FLASK */ /* * Implementation of the access vector table type. */ #include #include #include #include #include "debug.h" #include "private.h" /* Based on MurmurHash3, written by Austin Appleby and placed in the * public domain. */ ignore_unsigned_overflow_ static inline int avtab_hash(struct avtab_key *keyp, uint32_t mask) { static const uint32_t c1 = 0xcc9e2d51; static const uint32_t c2 = 0x1b873593; static const uint32_t r1 = 15; static const uint32_t r2 = 13; static const uint32_t m = 5; static const uint32_t n = 0xe6546b64; uint32_t hash = 0; #define mix(input) do { \ 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; \ } while (0) mix(keyp->target_class); mix(keyp->target_type); mix(keyp->source_type); #undef mix hash ^= hash >> 16; hash *= 0x85ebca6b; hash ^= hash >> 13; hash *= 0xc2b2ae35; hash ^= hash >> 16; return hash & mask; } static avtab_ptr_t avtab_insert_node(avtab_t * h, int hvalue, avtab_ptr_t prev, avtab_key_t * key, avtab_datum_t * datum) { avtab_ptr_t newnode; avtab_extended_perms_t *xperms; newnode = (avtab_ptr_t) malloc(sizeof(struct avtab_node)); if (newnode == NULL) return NULL; memset(newnode, 0, sizeof(struct avtab_node)); newnode->key = *key; if (key->specified & AVTAB_XPERMS) { xperms = calloc(1, sizeof(avtab_extended_perms_t)); if (xperms == NULL) { free(newnode); return NULL; } if (datum->xperms) /* else caller populates xperms */ *xperms = *(datum->xperms); newnode->datum.xperms = xperms; /* data is usually ignored with xperms, except in the case of * neverallow checking, which requires permission bits to be set. * So copy data so it is set in the avtab */ newnode->datum.data = datum->data; } else { newnode->datum = *datum; } if (prev) { newnode->next = prev->next; prev->next = newnode; } else { newnode->next = h->htable[hvalue]; h->htable[hvalue] = newnode; } h->nel++; return newnode; } int avtab_insert(avtab_t * h, avtab_key_t * key, avtab_datum_t * datum) { int hvalue; avtab_ptr_t prev, cur, newnode; uint16_t specified = key->specified & ~(AVTAB_ENABLED | AVTAB_ENABLED_OLD); if (!h || !h->htable) return SEPOL_ENOMEM; hvalue = avtab_hash(key, h->mask); for (prev = NULL, cur = h->htable[hvalue]; cur; prev = cur, cur = cur->next) { if (key->source_type == cur->key.source_type && key->target_type == cur->key.target_type && key->target_class == cur->key.target_class && (specified & cur->key.specified)) { /* Extended permissions are not necessarily unique */ if (specified & AVTAB_XPERMS) break; return SEPOL_EEXIST; } if (key->source_type < cur->key.source_type) break; if (key->source_type == cur->key.source_type && key->target_type < cur->key.target_type) break; if (key->source_type == cur->key.source_type && key->target_type == cur->key.target_type && key->target_class < cur->key.target_class) break; } newnode = avtab_insert_node(h, hvalue, prev, key, datum); if (!newnode) return SEPOL_ENOMEM; return 0; } /* Unlike avtab_insert(), this function allow multiple insertions of the same * key/specified mask into the table, as needed by the conditional avtab. * It also returns a pointer to the node inserted. */ avtab_ptr_t avtab_insert_nonunique(avtab_t * h, avtab_key_t * key, avtab_datum_t * datum) { int hvalue; avtab_ptr_t prev, cur, newnode; uint16_t specified = key->specified & ~(AVTAB_ENABLED | AVTAB_ENABLED_OLD); if (!h || !h->htable) return NULL; hvalue = avtab_hash(key, h->mask); for (prev = NULL, cur = h->htable[hvalue]; cur; prev = cur, cur = cur->next) { if (key->source_type == cur->key.source_type && key->target_type == cur->key.target_type && key->target_class == cur->key.target_class && (specified & cur->key.specified)) break; if (key->source_type < cur->key.source_type) break; if (key->source_type == cur->key.source_type && key->target_type < cur->key.target_type) break; if (key->source_type == cur->key.source_type && key->target_type == cur->key.target_type && key->target_class < cur->key.target_class) break; } newnode = avtab_insert_node(h, hvalue, prev, key, datum); return newnode; } avtab_datum_t *avtab_search(avtab_t * h, avtab_key_t * key) { int hvalue; avtab_ptr_t cur; uint16_t specified = key->specified & ~(AVTAB_ENABLED | AVTAB_ENABLED_OLD); if (!h || !h->htable) return NULL; hvalue = avtab_hash(key, h->mask); for (cur = h->htable[hvalue]; cur; cur = cur->next) { if (key->source_type == cur->key.source_type && key->target_type == cur->key.target_type && key->target_class == cur->key.target_class && (specified & cur->key.specified)) return &cur->datum; if (key->source_type < cur->key.source_type) break; if (key->source_type == cur->key.source_type && key->target_type < cur->key.target_type) break; if (key->source_type == cur->key.source_type && key->target_type == cur->key.target_type && key->target_class < cur->key.target_class) break; } return NULL; } /* This search function returns a node pointer, and can be used in * conjunction with avtab_search_next_node() */ avtab_ptr_t avtab_search_node(avtab_t * h, avtab_key_t * key) { int hvalue; avtab_ptr_t cur; uint16_t specified = key->specified & ~(AVTAB_ENABLED | AVTAB_ENABLED_OLD); if (!h || !h->htable) return NULL; hvalue = avtab_hash(key, h->mask); for (cur = h->htable[hvalue]; cur; cur = cur->next) { if (key->source_type == cur->key.source_type && key->target_type == cur->key.target_type && key->target_class == cur->key.target_class && (specified & cur->key.specified)) return cur; if (key->source_type < cur->key.source_type) break; if (key->source_type == cur->key.source_type && key->target_type < cur->key.target_type) break; if (key->source_type == cur->key.source_type && key->target_type == cur->key.target_type && key->target_class < cur->key.target_class) break; } return NULL; } avtab_ptr_t avtab_search_node_next(avtab_ptr_t node, int specified) { avtab_ptr_t cur; if (!node) return NULL; specified &= ~(AVTAB_ENABLED | AVTAB_ENABLED_OLD); for (cur = node->next; cur; cur = cur->next) { if (node->key.source_type == cur->key.source_type && node->key.target_type == cur->key.target_type && node->key.target_class == cur->key.target_class && (specified & cur->key.specified)) return cur; if (node->key.source_type < cur->key.source_type) break; if (node->key.source_type == cur->key.source_type && node->key.target_type < cur->key.target_type) break; if (node->key.source_type == cur->key.source_type && node->key.target_type == cur->key.target_type && node->key.target_class < cur->key.target_class) break; } return NULL; } void avtab_destroy(avtab_t * h) { unsigned int i; avtab_ptr_t cur, temp; if (!h || !h->htable) return; for (i = 0; i < h->nslot; i++) { cur = h->htable[i]; while (cur != NULL) { if (cur->key.specified & AVTAB_XPERMS) { free(cur->datum.xperms); } temp = cur; cur = cur->next; free(temp); } h->htable[i] = NULL; } free(h->htable); h->htable = NULL; h->nslot = 0; h->mask = 0; } int avtab_map(const avtab_t * h, int (*apply) (avtab_key_t * k, avtab_datum_t * d, void *args), void *args) { unsigned int i; int ret; avtab_ptr_t cur; if (!h) return 0; for (i = 0; i < h->nslot; i++) { cur = h->htable[i]; while (cur != NULL) { ret = apply(&cur->key, &cur->datum, args); if (ret) return ret; cur = cur->next; } } return 0; } int avtab_init(avtab_t * h) { h->htable = NULL; h->nel = 0; return 0; } int avtab_alloc(avtab_t *h, uint32_t nrules) { uint32_t mask = 0; uint32_t shift = 0; uint32_t work = nrules; uint32_t nslot = 0; if (nrules == 0) goto out; while (work) { work = work >> 1; shift++; } if (shift > 2) shift = shift - 2; nslot = UINT32_C(1) << shift; if (nslot > MAX_AVTAB_HASH_BUCKETS) nslot = MAX_AVTAB_HASH_BUCKETS; mask = nslot - 1; h->htable = calloc(nslot, sizeof(avtab_ptr_t)); if (!h->htable) return -1; out: h->nel = 0; h->nslot = nslot; h->mask = mask; return 0; } void avtab_hash_eval(avtab_t * h, char *tag) { unsigned int i, chain_len, slots_used, max_chain_len; avtab_ptr_t cur; slots_used = 0; max_chain_len = 0; for (i = 0; i < h->nslot; i++) { cur = h->htable[i]; if (cur) { slots_used++; chain_len = 0; while (cur) { chain_len++; cur = cur->next; } if (chain_len > max_chain_len) max_chain_len = chain_len; } } printf ("%s: %d entries and %d/%d buckets used, longest chain length %d\n", tag, h->nel, slots_used, h->nslot, max_chain_len); } /* Ordering of datums in the original avtab format in the policy file. */ static const uint16_t spec_order[] = { AVTAB_ALLOWED, AVTAB_AUDITDENY, AVTAB_AUDITALLOW, AVTAB_TRANSITION, AVTAB_CHANGE, AVTAB_MEMBER, AVTAB_XPERMS_ALLOWED, AVTAB_XPERMS_AUDITALLOW, AVTAB_XPERMS_DONTAUDIT }; int avtab_read_item(struct policy_file *fp, uint32_t vers, avtab_t * a, int (*insertf) (avtab_t * a, avtab_key_t * k, avtab_datum_t * d, void *p), void *p) { uint8_t buf8; uint16_t buf16[4], enabled; uint32_t buf32[8], items, items2, val; avtab_key_t key; avtab_datum_t datum; avtab_extended_perms_t xperms; unsigned int i; int rc; memset(&key, 0, sizeof(avtab_key_t)); memset(&datum, 0, sizeof(avtab_datum_t)); memset(&xperms, 0, sizeof(avtab_extended_perms_t)); if (vers < POLICYDB_VERSION_AVTAB) { rc = next_entry(buf32, fp, sizeof(uint32_t)); if (rc < 0) { ERR(fp->handle, "truncated entry"); return -1; } items2 = le32_to_cpu(buf32[0]); if (items2 < 5 || items2 > ARRAY_SIZE(buf32)) { ERR(fp->handle, "invalid item count"); return -1; } rc = next_entry(buf32, fp, sizeof(uint32_t) * items2); if (rc < 0) { ERR(fp->handle, "truncated entry"); return -1; } items = 0; val = le32_to_cpu(buf32[items++]); key.source_type = (uint16_t) val; if (key.source_type != val) { ERR(fp->handle, "truncated source type"); return -1; } val = le32_to_cpu(buf32[items++]); key.target_type = (uint16_t) val; if (key.target_type != val) { ERR(fp->handle, "truncated target type"); return -1; } val = le32_to_cpu(buf32[items++]); key.target_class = (uint16_t) val; if (key.target_class != val) { ERR(fp->handle, "truncated target class"); return -1; } val = le32_to_cpu(buf32[items++]); enabled = (val & AVTAB_ENABLED_OLD) ? AVTAB_ENABLED : 0; if (!(val & (AVTAB_AV | AVTAB_TYPE))) { ERR(fp->handle, "null entry"); return -1; } if ((val & AVTAB_AV) && (val & AVTAB_TYPE)) { ERR(fp->handle, "entry has both access " "vectors and types"); return -1; } for (i = 0; i < ARRAY_SIZE(spec_order); i++) { if (val & spec_order[i]) { if (items >= items2) { /* items is index, items2 is total number */ ERR(fp->handle, "entry has too many items (%d/%d)", items + 1, items2); return -1; } key.specified = spec_order[i] | enabled; datum.data = le32_to_cpu(buf32[items++]); rc = insertf(a, &key, &datum, p); if (rc) return rc; } } if (items != items2) { ERR(fp->handle, "entry only had %d items, " "expected %d", items2, items); return -1; } return 0; } rc = next_entry(buf16, fp, sizeof(uint16_t) * 4); if (rc < 0) { ERR(fp->handle, "truncated entry"); return -1; } items = 0; key.source_type = le16_to_cpu(buf16[items++]); key.target_type = le16_to_cpu(buf16[items++]); key.target_class = le16_to_cpu(buf16[items++]); key.specified = le16_to_cpu(buf16[items++]); if (key.specified & ~(AVTAB_AV | AVTAB_TYPE | AVTAB_XPERMS | AVTAB_ENABLED)) { ERR(fp->handle, "invalid specifier"); return -1; } if (__builtin_popcount(key.specified & ~AVTAB_ENABLED) != 1) { ERR(fp->handle, "not exactly one specifier"); return -1; } if ((vers < POLICYDB_VERSION_XPERMS_IOCTL) && (key.specified & AVTAB_XPERMS)) { ERR(fp->handle, "policy version %u does not support extended " "permissions rules and one was specified", vers); return -1; } else if (key.specified & AVTAB_XPERMS) { rc = next_entry(&buf8, fp, sizeof(uint8_t)); if (rc < 0) { ERR(fp->handle, "truncated entry"); return -1; } xperms.specified = buf8; rc = next_entry(&buf8, fp, sizeof(uint8_t)); if (rc < 0) { ERR(fp->handle, "truncated entry"); return -1; } xperms.driver = buf8; rc = next_entry(buf32, fp, sizeof(uint32_t)*8); if (rc < 0) { ERR(fp->handle, "truncated entry"); return -1; } for (i = 0; i < ARRAY_SIZE(xperms.perms); i++) xperms.perms[i] = le32_to_cpu(buf32[i]); datum.xperms = &xperms; } else { rc = next_entry(buf32, fp, sizeof(uint32_t)); if (rc < 0) { ERR(fp->handle, "truncated entry"); return -1; } datum.data = le32_to_cpu(*buf32); } return insertf(a, &key, &datum, p); } static int avtab_insertf(avtab_t * a, avtab_key_t * k, avtab_datum_t * d, void *p __attribute__ ((unused))) { return avtab_insert(a, k, d); } int avtab_read(avtab_t * a, struct policy_file *fp, uint32_t vers) { unsigned int i; int rc; uint32_t buf[1]; uint32_t nel; rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) { ERR(fp->handle, "truncated table"); goto bad; } nel = le32_to_cpu(buf[0]); if (zero_or_saturated(nel) || exceeds_available_bytes(fp, nel, sizeof(uint32_t) * 3)) { ERR(fp->handle, "table is empty"); goto bad; } rc = avtab_alloc(a, nel); if (rc) { ERR(fp->handle, "out of memory"); goto bad; } for (i = 0; i < nel; i++) { rc = avtab_read_item(fp, vers, a, avtab_insertf, NULL); if (rc) { if (rc == SEPOL_ENOMEM) ERR(fp->handle, "out of memory"); if (rc == SEPOL_EEXIST) ERR(fp->handle, "duplicate entry"); ERR(fp->handle, "failed on entry %d of %u", i, nel); goto bad; } } return 0; bad: avtab_destroy(a); return -1; } libsepol-3.8.1/src/boolean_internal.h000066400000000000000000000002151476211737200176170ustar00rootroot00000000000000#ifndef _SEPOL_BOOLEAN_INTERNAL_H_ #define _SEPOL_BOOLEAN_INTERNAL_H_ #include #include #endif libsepol-3.8.1/src/boolean_record.c000066400000000000000000000062011476211737200172550ustar00rootroot00000000000000#include #include #include #include "boolean_internal.h" #include "debug.h" struct sepol_bool { /* This boolean's name */ char *name; /* Its value */ int value; }; struct sepol_bool_key { /* This boolean's name */ char *name; }; int sepol_bool_key_create(sepol_handle_t * handle, const char *name, sepol_bool_key_t ** key_ptr) { sepol_bool_key_t *tmp_key = (sepol_bool_key_t *) malloc(sizeof(struct sepol_bool_key)); if (!tmp_key) { ERR(handle, "out of memory, " "could not create boolean key"); return STATUS_ERR; } tmp_key->name = strdup(name); if (!tmp_key->name) { ERR(handle, "out of memory, " "could not create boolean key"); free(tmp_key); return STATUS_ERR; } *key_ptr = tmp_key; return STATUS_SUCCESS; } void sepol_bool_key_unpack(const sepol_bool_key_t * key, const char **name) { *name = key->name; } int sepol_bool_key_extract(sepol_handle_t * handle, const sepol_bool_t * boolean, sepol_bool_key_t ** key_ptr) { if (sepol_bool_key_create(handle, boolean->name, key_ptr) < 0) { ERR(handle, "could not extract key from boolean %s", boolean->name); return STATUS_ERR; } return STATUS_SUCCESS; } void sepol_bool_key_free(sepol_bool_key_t * key) { if (!key) return; free(key->name); free(key); } int sepol_bool_compare(const sepol_bool_t * boolean, const sepol_bool_key_t * key) { return strcmp(boolean->name, key->name); } int sepol_bool_compare2(const sepol_bool_t * boolean, const sepol_bool_t * boolean2) { return strcmp(boolean->name, boolean2->name); } /* Name */ const char *sepol_bool_get_name(const sepol_bool_t * boolean) { return boolean->name; } int sepol_bool_set_name(sepol_handle_t * handle, sepol_bool_t * boolean, const char *name) { char *tmp_name = strdup(name); if (!tmp_name) { ERR(handle, "out of memory, could not set boolean name"); return STATUS_ERR; } free(boolean->name); boolean->name = tmp_name; return STATUS_SUCCESS; } /* Value */ int sepol_bool_get_value(const sepol_bool_t * boolean) { return boolean->value; } void sepol_bool_set_value(sepol_bool_t * boolean, int value) { boolean->value = value; } /* Create */ int sepol_bool_create(sepol_handle_t * handle, sepol_bool_t ** bool_ptr) { sepol_bool_t *boolean = (sepol_bool_t *) malloc(sizeof(sepol_bool_t)); if (!boolean) { ERR(handle, "out of memory, " "could not create boolean record"); return STATUS_ERR; } boolean->name = NULL; boolean->value = 0; *bool_ptr = boolean; return STATUS_SUCCESS; } /* Deep copy clone */ int sepol_bool_clone(sepol_handle_t * handle, const sepol_bool_t * boolean, sepol_bool_t ** bool_ptr) { sepol_bool_t *new_bool = NULL; if (sepol_bool_create(handle, &new_bool) < 0) goto err; if (sepol_bool_set_name(handle, new_bool, boolean->name) < 0) goto err; new_bool->value = boolean->value; *bool_ptr = new_bool; return STATUS_SUCCESS; err: ERR(handle, "could not clone boolean record"); sepol_bool_free(new_bool); return STATUS_ERR; } /* Destroy */ void sepol_bool_free(sepol_bool_t * boolean) { if (!boolean) return; free(boolean->name); free(boolean); } libsepol-3.8.1/src/booleans.c000066400000000000000000000107041476211737200161050ustar00rootroot00000000000000#include #include #include "handle.h" #include "private.h" #include "debug.h" #include #include #include #include #include "boolean_internal.h" static int bool_update(sepol_handle_t * handle, policydb_t * policydb, const sepol_bool_key_t * key, const sepol_bool_t * data) { const char *cname; char *name; int value; cond_bool_datum_t *datum; sepol_bool_key_unpack(key, &cname); name = strdup(cname); value = sepol_bool_get_value(data); if (!name) goto omem; datum = hashtab_search(policydb->p_bools.table, name); if (!datum) { ERR(handle, "boolean %s no longer in policy", name); goto err; } if (value != 0 && value != 1) { ERR(handle, "illegal value %d for boolean %s", value, name); goto err; } free(name); datum->state = value; return STATUS_SUCCESS; omem: ERR(handle, "out of memory"); err: free(name); ERR(handle, "could not update boolean %s", cname); return STATUS_ERR; } static int bool_to_record(sepol_handle_t * handle, const policydb_t * policydb, int bool_idx, sepol_bool_t ** record) { const char *name = policydb->p_bool_val_to_name[bool_idx]; cond_bool_datum_t *booldatum = policydb->bool_val_to_struct[bool_idx]; int value = booldatum->state; sepol_bool_t *tmp_record = NULL; if (sepol_bool_create(handle, &tmp_record) < 0) goto err; if (sepol_bool_set_name(handle, tmp_record, name) < 0) goto err; sepol_bool_set_value(tmp_record, value); *record = tmp_record; return STATUS_SUCCESS; err: ERR(handle, "could not convert boolean %s to record", name); sepol_bool_free(tmp_record); return STATUS_ERR; } int sepol_bool_set(sepol_handle_t * handle, sepol_policydb_t * p, const sepol_bool_key_t * key, const sepol_bool_t * data) { policydb_t *policydb = &p->p; const char *name; sepol_bool_key_unpack(key, &name); if (bool_update(handle, policydb, key, data) < 0) goto err; if (evaluate_conds(policydb) < 0) { ERR(handle, "error while re-evaluating conditionals"); goto err; } return STATUS_SUCCESS; err: ERR(handle, "could not set boolean %s", name); return STATUS_ERR; } int sepol_bool_count(sepol_handle_t * handle __attribute__ ((unused)), const sepol_policydb_t * p, unsigned int *response) { const policydb_t *policydb = &p->p; *response = policydb->p_bools.nprim; return STATUS_SUCCESS; } int sepol_bool_exists(sepol_handle_t * handle, const sepol_policydb_t * p, const sepol_bool_key_t * key, int *response) { const policydb_t *policydb = &p->p; const char *cname; char *name = NULL; sepol_bool_key_unpack(key, &cname); name = strdup(cname); if (!name) { ERR(handle, "out of memory, could not check " "if user %s exists", cname); return STATUS_ERR; } *response = (hashtab_search(policydb->p_bools.table, name) != NULL); free(name); return STATUS_SUCCESS; } int sepol_bool_query(sepol_handle_t * handle, const sepol_policydb_t * p, const sepol_bool_key_t * key, sepol_bool_t ** response) { const policydb_t *policydb = &p->p; cond_bool_datum_t *booldatum = NULL; const char *cname; char *name = NULL; sepol_bool_key_unpack(key, &cname); name = strdup(cname); if (!name) goto omem; booldatum = hashtab_search(policydb->p_bools.table, name); if (!booldatum) { *response = NULL; free(name); return STATUS_SUCCESS; } if (bool_to_record(handle, policydb, booldatum->s.value - 1, response) < 0) goto err; free(name); return STATUS_SUCCESS; omem: ERR(handle, "out of memory"); err: ERR(handle, "could not query boolean %s", cname); free(name); return STATUS_ERR; } int sepol_bool_iterate(sepol_handle_t * handle, const sepol_policydb_t * p, int (*fn) (const sepol_bool_t * boolean, void *fn_arg), void *arg) { const policydb_t *policydb = &p->p; unsigned int nbools = policydb->p_bools.nprim; sepol_bool_t *boolean = NULL; unsigned int i; /* For each boolean */ for (i = 0; i < nbools; i++) { int status; if (bool_to_record(handle, policydb, i, &boolean) < 0) goto err; /* Invoke handler */ status = fn(boolean, arg); if (status < 0) goto err; sepol_bool_free(boolean); boolean = NULL; /* Handler requested exit */ if (status > 0) break; } return STATUS_SUCCESS; err: ERR(handle, "could not iterate over booleans"); sepol_bool_free(boolean); return STATUS_ERR; } libsepol-3.8.1/src/conditional.c000066400000000000000000000505511476211737200166120ustar00rootroot00000000000000/* Authors: Karl MacMillan * Frank Mayer * David Caplan * * Copyright (C) 2003 - 2005 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include "private.h" #include "debug.h" /* move all type rules to top of t/f lists to help kernel on evaluation */ static void cond_optimize(cond_av_list_t ** l) { cond_av_list_t *top, *p, *cur; top = p = cur = *l; while (cur) { if ((cur->node->key.specified & AVTAB_TYPE) && (top != cur)) { p->next = cur->next; cur->next = top; top = cur; cur = p->next; } else { p = cur; cur = cur->next; } } *l = top; } /* reorder t/f lists for kernel */ void cond_optimize_lists(cond_list_t * cl) { cond_list_t *n; for (n = cl; n != NULL; n = n->next) { cond_optimize(&n->true_list); cond_optimize(&n->false_list); } } static int bool_present(unsigned int target, unsigned int bools[], unsigned int num_bools) { unsigned int i = 0; int ret = 1; if (num_bools > COND_MAX_BOOLS) { return 0; } while (i < num_bools && target != bools[i]) i++; if (i == num_bools) ret = 0; /* got to end w/o match */ return ret; } static int same_bools(cond_node_t * a, cond_node_t * b) { unsigned int i, x; x = a->nbools; /* same number of bools? */ if (x != b->nbools) return 0; /* make sure all the bools in a are also in b */ for (i = 0; i < x; i++) if (!bool_present(a->bool_ids[i], b->bool_ids, x)) return 0; return 1; } /* * Determine if two conditional expressions are equal. */ int cond_expr_equal(cond_node_t * a, cond_node_t * b) { cond_expr_t *cur_a, *cur_b; if (a == NULL || b == NULL) return 0; if (a->nbools != b->nbools) return 0; /* if exprs have <= COND_MAX_BOOLS we can check the precompute values * for the expressions. */ if (a->nbools <= COND_MAX_BOOLS && b->nbools <= COND_MAX_BOOLS) { if (!same_bools(a, b)) return 0; return (a->expr_pre_comp == b->expr_pre_comp); } /* for long expressions we check for exactly the same expression */ cur_a = a->expr; cur_b = b->expr; while (1) { if (cur_a == NULL && cur_b == NULL) return 1; else if (cur_a == NULL || cur_b == NULL) return 0; if (cur_a->expr_type != cur_b->expr_type) return 0; if (cur_a->expr_type == COND_BOOL) { if (cur_a->boolean != cur_b->boolean) return 0; } cur_a = cur_a->next; cur_b = cur_b->next; } return 1; } /* Create a new conditional node, optionally copying * the conditional expression from an existing node. * If node is NULL then a new node will be created * with no conditional expression. */ cond_node_t *cond_node_create(policydb_t * p, cond_node_t * node) { cond_node_t *new_node; unsigned int i; new_node = (cond_node_t *)malloc(sizeof(cond_node_t)); if (!new_node) { return NULL; } memset(new_node, 0, sizeof(cond_node_t)); if (node) { new_node->expr = cond_copy_expr(node->expr); if (!new_node->expr) { free(new_node); return NULL; } new_node->cur_state = cond_evaluate_expr(p, new_node->expr); new_node->nbools = node->nbools; for (i = 0; i < min(node->nbools, COND_MAX_BOOLS); i++) new_node->bool_ids[i] = node->bool_ids[i]; new_node->expr_pre_comp = node->expr_pre_comp; new_node->flags = node->flags; } return new_node; } /* Find a conditional (the needle) within a list of existing ones (the * haystack) that has a matching expression. If found, return a * pointer to the existing node, setting 'was_created' to 0. * Otherwise create a new one and return it, setting 'was_created' to * 1. */ cond_node_t *cond_node_find(policydb_t * p, cond_node_t * needle, cond_node_t * haystack, int *was_created) { while (haystack) { if (cond_expr_equal(needle, haystack)) { *was_created = 0; return haystack; } haystack = haystack->next; } *was_created = 1; return cond_node_create(p, needle); } /* return either a pre-existing matching node or create a new node */ cond_node_t *cond_node_search(policydb_t * p, cond_node_t * list, cond_node_t * cn) { int was_created; cond_node_t *result = cond_node_find(p, cn, list, &was_created); if (result != NULL && was_created) { /* add conditional node to policy list */ result->next = p->cond_list; p->cond_list = result; } return result; } /* * cond_evaluate_expr evaluates a conditional expr * in reverse polish notation. It returns true (1), false (0), * or undefined (-1). Undefined occurs when the expression * exceeds the stack depth of COND_EXPR_MAXDEPTH. */ int cond_evaluate_expr(policydb_t * p, cond_expr_t * expr) { cond_expr_t *cur; int s[COND_EXPR_MAXDEPTH]; int sp = -1; s[0] = -1; for (cur = expr; cur != NULL; cur = cur->next) { switch (cur->expr_type) { case COND_BOOL: if (sp == (COND_EXPR_MAXDEPTH - 1)) return -1; sp++; s[sp] = p->bool_val_to_struct[cur->boolean - 1]->state; break; case COND_NOT: if (sp < 0) return -1; s[sp] = !s[sp]; break; case COND_OR: if (sp < 1) return -1; sp--; s[sp] |= s[sp + 1]; break; case COND_AND: if (sp < 1) return -1; sp--; s[sp] &= s[sp + 1]; break; case COND_XOR: if (sp < 1) return -1; sp--; s[sp] ^= s[sp + 1]; break; case COND_EQ: if (sp < 1) return -1; sp--; s[sp] = (s[sp] == s[sp + 1]); break; case COND_NEQ: if (sp < 1) return -1; sp--; s[sp] = (s[sp] != s[sp + 1]); break; default: return -1; } } return s[0]; } cond_expr_t *cond_copy_expr(cond_expr_t * expr) { cond_expr_t *cur, *head, *tail, *new_expr; tail = head = NULL; cur = expr; while (cur) { new_expr = (cond_expr_t *) malloc(sizeof(cond_expr_t)); if (!new_expr) goto free_head; memset(new_expr, 0, sizeof(cond_expr_t)); new_expr->expr_type = cur->expr_type; new_expr->boolean = cur->boolean; if (!head) head = new_expr; if (tail) tail->next = new_expr; tail = new_expr; cur = cur->next; } return head; free_head: while (head) { tail = head->next; free(head); head = tail; } return NULL; } /* * evaluate_cond_node evaluates the conditional stored in * a cond_node_t and if the result is different than the * current state of the node it sets the rules in the true/false * list appropriately. If the result of the expression is undefined * all of the rules are disabled for safety. */ static int evaluate_cond_node(policydb_t * p, cond_node_t * node) { int new_state; cond_av_list_t *cur; new_state = cond_evaluate_expr(p, node->expr); if (new_state != node->cur_state) { node->cur_state = new_state; if (new_state == -1) WARN(NULL, "expression result was undefined - disabling all rules."); /* turn the rules on or off */ for (cur = node->true_list; cur != NULL; cur = cur->next) { if (new_state <= 0) { cur->node->key.specified &= ~AVTAB_ENABLED; } else { cur->node->key.specified |= AVTAB_ENABLED; } } for (cur = node->false_list; cur != NULL; cur = cur->next) { /* -1 or 1 */ if (new_state) { cur->node->key.specified &= ~AVTAB_ENABLED; } else { cur->node->key.specified |= AVTAB_ENABLED; } } } return 0; } /* precompute and simplify an expression if possible. If left with !expression, change * to expression and switch t and f. precompute expression for expressions with limited * number of bools. */ int cond_normalize_expr(policydb_t * p, cond_node_t * cn) { cond_expr_t *ne, *e; cond_av_list_t *tmp; unsigned int i, j, orig_value[COND_MAX_BOOLS]; int k; uint32_t test = 0x0; avrule_t *tmp2; cn->nbools = 0; memset(cn->bool_ids, 0, sizeof(cn->bool_ids)); cn->expr_pre_comp = 0x0; /* take care of !expr case */ ne = NULL; e = cn->expr; /* because it's RPN look at last element */ while (e->next != NULL) { ne = e; e = e->next; } if (e->expr_type == COND_NOT) { if (ne) { ne->next = NULL; } else { /* ne should never be NULL */ ERR(NULL, "Found expr with no bools and only a ! - this should never happen."); return -1; } /* swap the true and false lists */ tmp = cn->true_list; cn->true_list = cn->false_list; cn->false_list = tmp; tmp2 = cn->avtrue_list; cn->avtrue_list = cn->avfalse_list; cn->avfalse_list = tmp2; /* free the "not" node in the list */ free(e); } /* find all the bools in the expression */ for (e = cn->expr; e != NULL; e = e->next) { switch (e->expr_type) { case COND_BOOL: /* see if we've already seen this bool */ if (!bool_present(e->boolean, cn->bool_ids, cn->nbools)) { /* count em all but only record up to COND_MAX_BOOLS */ if (cn->nbools < COND_MAX_BOOLS) cn->bool_ids[cn->nbools++] = e->boolean; else cn->nbools++; } break; default: break; } } /* only precompute for exprs with <= COND_AX_BOOLS */ if (cn->nbools <= COND_MAX_BOOLS) { /* save the default values for the bools so we can play with them */ for (i = 0; i < cn->nbools; i++) { orig_value[i] = p->bool_val_to_struct[cn->bool_ids[i] - 1]->state; } /* loop through all possible combinations of values for bools in expression */ for (test = 0x0; test < (UINT32_C(1) << cn->nbools); test++) { /* temporarily set the value for all the bools in the * expression using the corr. bit in test */ for (j = 0; j < cn->nbools; j++) { p->bool_val_to_struct[cn->bool_ids[j] - 1]->state = (test & (UINT32_C(1) << j)) ? 1 : 0; } k = cond_evaluate_expr(p, cn->expr); if (k == -1) { ERR(NULL, "While testing expression, expression result " "was undefined - this should never happen."); return -1; } /* set the bit if expression evaluates true */ if (k) cn->expr_pre_comp |= UINT32_C(1) << test; } /* restore bool default values */ for (i = 0; i < cn->nbools; i++) p->bool_val_to_struct[cn->bool_ids[i] - 1]->state = orig_value[i]; } return 0; } int evaluate_conds(policydb_t * p) { int ret; cond_node_t *cur; for (cur = p->cond_list; cur != NULL; cur = cur->next) { ret = evaluate_cond_node(p, cur); if (ret) return ret; } return 0; } int cond_policydb_init(policydb_t * p) { p->bool_val_to_struct = NULL; p->cond_list = NULL; if (avtab_init(&p->te_cond_avtab)) return -1; return 0; } void cond_av_list_destroy(cond_av_list_t * list) { cond_av_list_t *cur, *next; for (cur = list; cur != NULL; cur = next) { next = cur->next; /* the avtab_ptr_t node is destroy by the avtab */ free(cur); } } void cond_expr_destroy(cond_expr_t * expr) { cond_expr_t *cur_expr, *next_expr; if (!expr) return; for (cur_expr = expr; cur_expr != NULL; cur_expr = next_expr) { next_expr = cur_expr->next; free(cur_expr); } } void cond_node_destroy(cond_node_t * node) { if (!node) return; cond_expr_destroy(node->expr); avrule_list_destroy(node->avtrue_list); avrule_list_destroy(node->avfalse_list); cond_av_list_destroy(node->true_list); cond_av_list_destroy(node->false_list); } void cond_list_destroy(cond_list_t * list) { cond_node_t *next, *cur; if (list == NULL) return; for (cur = list; cur != NULL; cur = next) { next = cur->next; cond_node_destroy(cur); free(cur); } } void cond_policydb_destroy(policydb_t * p) { if (p->bool_val_to_struct != NULL) free(p->bool_val_to_struct); avtab_destroy(&p->te_cond_avtab); cond_list_destroy(p->cond_list); } int cond_init_bool_indexes(policydb_t * p) { if (p->bool_val_to_struct) free(p->bool_val_to_struct); p->bool_val_to_struct = (cond_bool_datum_t **) calloc(p->p_bools.nprim, sizeof(cond_bool_datum_t *)); if (!p->bool_val_to_struct) return -1; return 0; } int cond_destroy_bool(hashtab_key_t key, hashtab_datum_t datum, void *p __attribute__ ((unused))) { if (key) free(key); free(datum); return 0; } int cond_index_bool(hashtab_key_t key, hashtab_datum_t datum, void *datap) { policydb_t *p; cond_bool_datum_t *booldatum; booldatum = datum; p = datap; if (!booldatum->s.value || booldatum->s.value > p->p_bools.nprim) return -EINVAL; if (p->p_bool_val_to_name[booldatum->s.value - 1] != NULL) return -EINVAL; p->p_bool_val_to_name[booldatum->s.value - 1] = key; p->bool_val_to_struct[booldatum->s.value - 1] = booldatum; return 0; } static int bool_isvalid(cond_bool_datum_t * b) { if (!(b->state == 0 || b->state == 1)) return 0; return 1; } int cond_read_bool(policydb_t * p, hashtab_t h, struct policy_file *fp) { char *key = 0; cond_bool_datum_t *booldatum; uint32_t buf[3], len; int rc; booldatum = malloc(sizeof(cond_bool_datum_t)); if (!booldatum) return -1; memset(booldatum, 0, sizeof(cond_bool_datum_t)); rc = next_entry(buf, fp, sizeof(uint32_t) * 3); if (rc < 0) goto err; booldatum->s.value = le32_to_cpu(buf[0]); booldatum->state = le32_to_cpu(buf[1]); if (!bool_isvalid(booldatum)) goto err; len = le32_to_cpu(buf[2]); if (str_read(&key, fp, len)) goto err; if (p->policy_type != POLICY_KERN && p->policyvers >= MOD_POLICYDB_VERSION_TUNABLE_SEP) { rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) goto err; booldatum->flags = le32_to_cpu(buf[0]); } if (hashtab_insert(h, key, booldatum)) goto err; return 0; err: cond_destroy_bool(key, booldatum, 0); return -1; } struct cond_insertf_data { struct policydb *p; cond_av_list_t *other; cond_av_list_t *head; cond_av_list_t *tail; }; static int cond_insertf(avtab_t * a __attribute__ ((unused)), avtab_key_t * k, avtab_datum_t * d, void *ptr) { struct cond_insertf_data *data = ptr; struct policydb *p = data->p; cond_av_list_t *other = data->other, *list, *cur; avtab_ptr_t node_ptr; uint8_t found; /* * For type rules we have to make certain there aren't any * conflicting rules by searching the te_avtab and the * cond_te_avtab. */ if (k->specified & AVTAB_TYPE) { if (avtab_search(&p->te_avtab, k)) { WARN(NULL, "security: type rule already exists outside of a conditional."); return -1; } /* * If we are reading the false list other will be a pointer to * the true list. We can have duplicate entries if there is only * 1 other entry and it is in our true list. * * If we are reading the true list (other == NULL) there shouldn't * be any other entries. */ if (other) { node_ptr = avtab_search_node(&p->te_cond_avtab, k); if (node_ptr) { if (avtab_search_node_next (node_ptr, k->specified)) { ERR(NULL, "security: too many conflicting type rules."); return -1; } found = 0; for (cur = other; cur != NULL; cur = cur->next) { if (cur->node == node_ptr) { found = 1; break; } } if (!found) { ERR(NULL, "security: conflicting type rules."); return -1; } } } else { if (avtab_search(&p->te_cond_avtab, k)) { ERR(NULL, "security: conflicting type rules when adding type rule for true."); return -1; } } } node_ptr = avtab_insert_nonunique(&p->te_cond_avtab, k, d); if (!node_ptr) { ERR(NULL, "security: could not insert rule."); return -1; } node_ptr->parse_context = (void *)1; list = malloc(sizeof(cond_av_list_t)); if (!list) return -1; memset(list, 0, sizeof(cond_av_list_t)); list->node = node_ptr; if (!data->head) data->head = list; else data->tail->next = list; data->tail = list; return 0; } static int cond_read_av_list(policydb_t * p, void *fp, cond_av_list_t ** ret_list, cond_av_list_t * other) { unsigned int i; int rc; uint32_t buf[1], len; struct cond_insertf_data data; *ret_list = NULL; rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) return -1; len = le32_to_cpu(buf[0]); if (len == 0) { return 0; } data.p = p; data.other = other; data.head = NULL; data.tail = NULL; for (i = 0; i < len; i++) { rc = avtab_read_item(fp, p->policyvers, &p->te_cond_avtab, cond_insertf, &data); if (rc) { cond_av_list_destroy(data.head); return rc; } } *ret_list = data.head; return 0; } static int expr_isvalid(policydb_t * p, cond_expr_t * expr) { if (expr->expr_type <= 0 || expr->expr_type > COND_LAST) { WARN(NULL, "security: conditional expressions uses unknown operator."); return 0; } if (expr->boolean > p->p_bools.nprim) { WARN(NULL, "security: conditional expressions uses unknown bool."); return 0; } return 1; } static int cond_read_node(policydb_t * p, cond_node_t * node, void *fp) { uint32_t buf[2], i, len; int rc; cond_expr_t *expr = NULL, *last = NULL; rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) goto err; node->cur_state = le32_to_cpu(buf[0]); rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) goto err; /* expr */ len = le32_to_cpu(buf[0]); for (i = 0; i < len; i++) { rc = next_entry(buf, fp, sizeof(uint32_t) * 2); if (rc < 0) goto err; expr = malloc(sizeof(cond_expr_t)); if (!expr) { goto err; } memset(expr, 0, sizeof(cond_expr_t)); expr->expr_type = le32_to_cpu(buf[0]); expr->boolean = le32_to_cpu(buf[1]); if (!expr_isvalid(p, expr)) { free(expr); goto err; } if (i == 0) { node->expr = expr; } else { last->next = expr; } last = expr; } if (p->policy_type == POLICY_KERN) { if (cond_read_av_list(p, fp, &node->true_list, NULL) != 0) goto err; if (cond_read_av_list(p, fp, &node->false_list, node->true_list) != 0) goto err; } else { if (avrule_read_list(p, &node->avtrue_list, fp)) goto err; if (avrule_read_list(p, &node->avfalse_list, fp)) goto err; } if (p->policy_type != POLICY_KERN && p->policyvers >= MOD_POLICYDB_VERSION_TUNABLE_SEP) { rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) goto err; node->flags = le32_to_cpu(buf[0]); } return 0; err: cond_node_destroy(node); free(node); return -1; } int cond_read_list(policydb_t * p, cond_list_t ** list, void *fp) { cond_node_t *node, *last = NULL; uint32_t buf[1], i, len; int rc; rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) return -1; len = le32_to_cpu(buf[0]); rc = avtab_alloc(&p->te_cond_avtab, p->te_avtab.nel); if (rc) goto err; for (i = 0; i < len; i++) { node = malloc(sizeof(cond_node_t)); if (!node) goto err; memset(node, 0, sizeof(cond_node_t)); if (cond_read_node(p, node, fp) != 0) goto err; if (i == 0) { *list = node; } else { last->next = node; } last = node; } return 0; err: return -1; } /* Determine whether additional permissions are granted by the conditional * av table, and if so, add them to the result */ void cond_compute_av(avtab_t * ctab, avtab_key_t * key, struct sepol_av_decision *avd) { avtab_ptr_t node; if (!ctab || !key || !avd) return; for (node = avtab_search_node(ctab, key); node != NULL; node = avtab_search_node_next(node, key->specified)) { if ((uint16_t) (AVTAB_ALLOWED | AVTAB_ENABLED) == (node->key.specified & (AVTAB_ALLOWED | AVTAB_ENABLED))) avd->allowed |= node->datum.data; if ((uint16_t) (AVTAB_AUDITDENY | AVTAB_ENABLED) == (node->key.specified & (AVTAB_AUDITDENY | AVTAB_ENABLED))) /* Since a '0' in an auditdeny mask represents a * permission we do NOT want to audit (dontaudit), we use * the '&' operand to ensure that all '0's in the mask * are retained (much unlike the allow and auditallow cases). */ avd->auditdeny &= node->datum.data; if ((uint16_t) (AVTAB_AUDITALLOW | AVTAB_ENABLED) == (node->key.specified & (AVTAB_AUDITALLOW | AVTAB_ENABLED))) avd->auditallow |= node->datum.data; } return; } avtab_datum_t *cond_av_list_search(avtab_key_t * key, cond_av_list_t * cond_list) { cond_av_list_t *cur_av; for (cur_av = cond_list; cur_av != NULL; cur_av = cur_av->next) { if (cur_av->node->key.source_type == key->source_type && cur_av->node->key.target_type == key->target_type && cur_av->node->key.target_class == key->target_class) return &cur_av->node->datum; } return NULL; } libsepol-3.8.1/src/constraint.c000066400000000000000000000030151476211737200164640ustar00rootroot00000000000000/* Authors: Jason Tang * * Copyright (C) 2005 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include int constraint_expr_init(constraint_expr_t * expr) { memset(expr, 0, sizeof(*expr)); ebitmap_init(&expr->names); if ((expr->type_names = malloc(sizeof(*expr->type_names))) == NULL) { return -1; } type_set_init(expr->type_names); return 0; } void constraint_expr_destroy(constraint_expr_t * expr) { constraint_expr_t *next; while (expr != NULL) { next = expr->next; ebitmap_destroy(&expr->names); type_set_destroy(expr->type_names); free(expr->type_names); free(expr); expr = next; } } libsepol-3.8.1/src/context.c000066400000000000000000000200761476211737200157720ustar00rootroot00000000000000#include #include #include #include #include #include "context_internal.h" #include "debug.h" #include "context.h" #include "handle.h" #include "mls.h" #include "private.h" /* ----- Compatibility ---- */ int policydb_context_isvalid(const policydb_t * p, const context_struct_t * c) { return context_is_valid(p, c); } int sepol_check_context(const char *context) { return sepol_context_to_sid(context, strlen(context) + 1, NULL); } /* ---- End compatibility --- */ /* * Return 1 if the fields in the security context * structure `c' are valid. Return 0 otherwise. */ int context_is_valid(const policydb_t * p, const context_struct_t * c) { role_datum_t *role; user_datum_t *usrdatum; ebitmap_t types, roles; ebitmap_init(&types); ebitmap_init(&roles); if (!c->role || c->role > p->p_roles.nprim) return 0; if (!c->user || c->user > p->p_users.nprim) return 0; if (!c->type || c->type > p->p_types.nprim) return 0; if (c->role != OBJECT_R_VAL) { /* * Role must be authorized for the type. */ role = p->role_val_to_struct[c->role - 1]; if (!role || !ebitmap_get_bit(&role->cache, c->type - 1)) /* role may not be associated with type */ return 0; /* * User must be authorized for the role. */ usrdatum = p->user_val_to_struct[c->user - 1]; if (!usrdatum) return 0; if (!ebitmap_get_bit(&usrdatum->cache, c->role - 1)) /* user may not be associated with role */ return 0; } if (!mls_context_isvalid(p, c)) return 0; return 1; } /* * Write the security context string representation of * the context structure `context' into a dynamically * allocated string of the correct size. Set `*scontext' * to point to this string and set `*scontext_len' to * the length of the string. */ int context_to_string(sepol_handle_t * handle, const policydb_t * policydb, const context_struct_t * context, char **result, size_t * result_len) { char *scontext = NULL; size_t scontext_len = 0; char *ptr; /* Compute the size of the context. */ scontext_len += strlen(policydb->p_user_val_to_name[context->user - 1]) + 1; scontext_len += strlen(policydb->p_role_val_to_name[context->role - 1]) + 1; scontext_len += strlen(policydb->p_type_val_to_name[context->type - 1]); scontext_len += mls_compute_context_len(policydb, context); /* We must null terminate the string */ scontext_len += 1; /* Allocate space for the context; caller must free this space. */ scontext = malloc(scontext_len); if (!scontext) goto omem; scontext[scontext_len - 1] = '\0'; /* * Copy the user name, role name and type name into the context. */ ptr = scontext; sprintf(ptr, "%s:%s:%s", policydb->p_user_val_to_name[context->user - 1], policydb->p_role_val_to_name[context->role - 1], policydb->p_type_val_to_name[context->type - 1]); ptr += strlen(policydb->p_user_val_to_name[context->user - 1]) + 1 + strlen(policydb->p_role_val_to_name[context->role - 1]) + 1 + strlen(policydb->p_type_val_to_name[context->type - 1]); mls_sid_to_context(policydb, context, &ptr); *result = scontext; *result_len = scontext_len; return STATUS_SUCCESS; omem: ERR(handle, "out of memory, could not convert " "context to string"); free(scontext); return STATUS_ERR; } /* * Create a context structure from the given record */ int context_from_record(sepol_handle_t * handle, const policydb_t * policydb, context_struct_t ** cptr, const sepol_context_t * record) { context_struct_t *scontext = NULL; user_datum_t *usrdatum; role_datum_t *roldatum; type_datum_t *typdatum; /* Hashtab keys are not constant - suppress warnings */ char *user = strdup(sepol_context_get_user(record)); char *role = strdup(sepol_context_get_role(record)); char *type = strdup(sepol_context_get_type(record)); const char *mls = sepol_context_get_mls(record); scontext = (context_struct_t *) malloc(sizeof(context_struct_t)); if (!user || !role || !type || !scontext) { ERR(handle, "out of memory"); goto err; } context_init(scontext); /* User */ usrdatum = (user_datum_t *) hashtab_search(policydb->p_users.table, (hashtab_key_t) user); if (!usrdatum) { ERR(handle, "user %s is not defined", user); goto err_destroy; } scontext->user = usrdatum->s.value; /* Role */ roldatum = (role_datum_t *) hashtab_search(policydb->p_roles.table, (hashtab_key_t) role); if (!roldatum) { ERR(handle, "role %s is not defined", role); goto err_destroy; } scontext->role = roldatum->s.value; /* Type */ typdatum = (type_datum_t *) hashtab_search(policydb->p_types.table, (hashtab_key_t) type); if (!typdatum || typdatum->flavor == TYPE_ATTRIB) { ERR(handle, "type %s is not defined", type); goto err_destroy; } scontext->type = typdatum->s.value; /* MLS */ if (mls && !policydb->mls) { ERR(handle, "MLS is disabled, but MLS context \"%s\" found", mls); goto err_destroy; } else if (!mls && policydb->mls) { ERR(handle, "MLS is enabled, but no MLS context found"); goto err_destroy; } if (mls && (mls_from_string(handle, policydb, mls, scontext) < 0)) goto err_destroy; /* Validity check */ if (!context_is_valid(policydb, scontext)) { if (mls) { ERR(handle, "invalid security context: \"%s:%s:%s:%s\"", user, role, type, mls); } else { ERR(handle, "invalid security context: \"%s:%s:%s\"", user, role, type); } goto err_destroy; } *cptr = scontext; free(user); free(type); free(role); return STATUS_SUCCESS; err_destroy: errno = EINVAL; context_destroy(scontext); err: free(scontext); free(user); free(type); free(role); ERR(handle, "could not create context structure"); return STATUS_ERR; } /* * Create a record from the given context structure */ int context_to_record(sepol_handle_t * handle, const policydb_t * policydb, const context_struct_t * context, sepol_context_t ** record) { sepol_context_t *tmp_record = NULL; char *mls = NULL; if (sepol_context_create(handle, &tmp_record) < 0) goto err; if (sepol_context_set_user(handle, tmp_record, policydb->p_user_val_to_name[context->user - 1]) < 0) goto err; if (sepol_context_set_role(handle, tmp_record, policydb->p_role_val_to_name[context->role - 1]) < 0) goto err; if (sepol_context_set_type(handle, tmp_record, policydb->p_type_val_to_name[context->type - 1]) < 0) goto err; if (policydb->mls) { if (mls_to_string(handle, policydb, context, &mls) < 0) goto err; if (sepol_context_set_mls(handle, tmp_record, mls) < 0) goto err; } free(mls); *record = tmp_record; return STATUS_SUCCESS; err: ERR(handle, "could not create context record"); sepol_context_free(tmp_record); free(mls); return STATUS_ERR; } /* * Create a context structure from the provided string. */ int context_from_string(sepol_handle_t * handle, const policydb_t * policydb, context_struct_t ** cptr, const char *con_str, size_t con_str_len) { char *con_cpy = NULL; sepol_context_t *ctx_record = NULL; if (zero_or_saturated(con_str_len)) { ERR(handle, "Invalid context length"); goto err; } /* sepol_context_from_string expects a NULL-terminated string */ con_cpy = malloc(con_str_len + 1); if (!con_cpy) { ERR(handle, "out of memory"); goto err; } memcpy(con_cpy, con_str, con_str_len); con_cpy[con_str_len] = '\0'; if (sepol_context_from_string(handle, con_cpy, &ctx_record) < 0) goto err; /* Now create from the data structure */ if (context_from_record(handle, policydb, cptr, ctx_record) < 0) goto err; free(con_cpy); sepol_context_free(ctx_record); return STATUS_SUCCESS; err: ERR(handle, "could not create context structure"); free(con_cpy); sepol_context_free(ctx_record); return STATUS_ERR; } int sepol_context_check(sepol_handle_t * handle, const sepol_policydb_t * policydb, const sepol_context_t * context) { context_struct_t *con = NULL; int ret = context_from_record(handle, &policydb->p, &con, context); context_destroy(con); free(con); return ret; } libsepol-3.8.1/src/context.h000066400000000000000000000023471476211737200160000ustar00rootroot00000000000000#ifndef _SEPOL_INTERNAL_CONTEXT_H_ #define _SEPOL_INTERNAL_CONTEXT_H_ #include #include "context_internal.h" #include #include #include /* Create a context structure from high level representation */ extern int context_from_record(sepol_handle_t * handle, const policydb_t * policydb, context_struct_t ** cptr, const sepol_context_t * data); extern int context_to_record(sepol_handle_t * handle, const policydb_t * policydb, const context_struct_t * context, sepol_context_t ** record); /* Create a context structure from string representation */ extern int context_from_string(sepol_handle_t * handle, const policydb_t * policydb, context_struct_t ** cptr, const char *con_str, size_t con_str_len); /* Check if the provided context is valid for this policy */ extern int context_is_valid(const policydb_t * policydb, const context_struct_t * context); /* Extract the context as string */ extern int context_to_string(sepol_handle_t * handle, const policydb_t * policydb, const context_struct_t * context, char **result, size_t * result_len); #endif libsepol-3.8.1/src/context_internal.h000066400000000000000000000002141476211737200176630ustar00rootroot00000000000000#ifndef _SEPOL_CONTEXT_INTERNAL_H_ #define _SEPOL_CONTEXT_INTERNAL_H_ #include #include #endif libsepol-3.8.1/src/context_record.c000066400000000000000000000135511476211737200173300ustar00rootroot00000000000000#include #include #include #include #include "context_internal.h" #include "debug.h" #include "private.h" struct sepol_context { /* Selinux user */ char *user; /* Selinux role */ char *role; /* Selinux type */ char *type; /* MLS */ char *mls; }; /* User */ const char *sepol_context_get_user(const sepol_context_t * con) { return con->user; } int sepol_context_set_user(sepol_handle_t * handle, sepol_context_t * con, const char *user) { char *tmp_user = strdup(user); if (!tmp_user) { ERR(handle, "out of memory, could not set " "context user to %s", user); return STATUS_ERR; } free(con->user); con->user = tmp_user; return STATUS_SUCCESS; } /* Role */ const char *sepol_context_get_role(const sepol_context_t * con) { return con->role; } int sepol_context_set_role(sepol_handle_t * handle, sepol_context_t * con, const char *role) { char *tmp_role = strdup(role); if (!tmp_role) { ERR(handle, "out of memory, could not set " "context role to %s", role); return STATUS_ERR; } free(con->role); con->role = tmp_role; return STATUS_SUCCESS; } /* Type */ const char *sepol_context_get_type(const sepol_context_t * con) { return con->type; } int sepol_context_set_type(sepol_handle_t * handle, sepol_context_t * con, const char *type) { char *tmp_type = strdup(type); if (!tmp_type) { ERR(handle, "out of memory, could not set " "context type to %s", type); return STATUS_ERR; } free(con->type); con->type = tmp_type; return STATUS_SUCCESS; } /* MLS */ const char *sepol_context_get_mls(const sepol_context_t * con) { return con->mls; } int sepol_context_set_mls(sepol_handle_t * handle, sepol_context_t * con, const char *mls) { char *tmp_mls = strdup(mls); if (!tmp_mls) { ERR(handle, "out of memory, could not set " "MLS fields to %s", mls); return STATUS_ERR; } free(con->mls); con->mls = tmp_mls; return STATUS_SUCCESS; } /* Create */ int sepol_context_create(sepol_handle_t * handle, sepol_context_t ** con_ptr) { sepol_context_t *con = (sepol_context_t *) malloc(sizeof(sepol_context_t)); if (!con) { ERR(handle, "out of memory, could not create context"); return STATUS_ERR; } con->user = NULL; con->role = NULL; con->type = NULL; con->mls = NULL; *con_ptr = con; return STATUS_SUCCESS; } /* Deep copy clone */ int sepol_context_clone(sepol_handle_t * handle, const sepol_context_t * con, sepol_context_t ** con_ptr) { sepol_context_t *new_con = NULL; if (!con) { *con_ptr = NULL; return 0; } if (sepol_context_create(handle, &new_con) < 0) goto err; if (!(new_con->user = strdup(con->user))) goto omem; if (!(new_con->role = strdup(con->role))) goto omem; if (!(new_con->type = strdup(con->type))) goto omem; if (con->mls && !(new_con->mls = strdup(con->mls))) goto omem; *con_ptr = new_con; return STATUS_SUCCESS; omem: ERR(handle, "out of memory"); err: ERR(handle, "could not clone context record"); sepol_context_free(new_con); return STATUS_ERR; } /* Destroy */ void sepol_context_free(sepol_context_t * con) { if (!con) return; free(con->user); free(con->role); free(con->type); free(con->mls); free(con); } int sepol_context_from_string(sepol_handle_t * handle, const char *str, sepol_context_t ** con) { char *tmp = NULL, *low, *high; sepol_context_t *tmp_con = NULL; if (!strcmp(str, "<>")) { *con = NULL; return STATUS_SUCCESS; } if (sepol_context_create(handle, &tmp_con) < 0) goto err; /* Working copy context */ tmp = strdup(str); if (!tmp) { ERR(handle, "out of memory"); goto err; } low = tmp; /* Then, break it into its components */ /* User */ if (!(high = strchr(low, ':'))) goto mcontext; else *high++ = '\0'; if (sepol_context_set_user(handle, tmp_con, low) < 0) goto err; low = high; /* Role */ if (!(high = strchr(low, ':'))) goto mcontext; else *high++ = '\0'; if (sepol_context_set_role(handle, tmp_con, low) < 0) goto err; low = high; /* Type, and possibly MLS */ if (!(high = strchr(low, ':'))) { if (sepol_context_set_type(handle, tmp_con, low) < 0) goto err; } else { *high++ = '\0'; if (sepol_context_set_type(handle, tmp_con, low) < 0) goto err; low = high; if (sepol_context_set_mls(handle, tmp_con, low) < 0) goto err; } free(tmp); *con = tmp_con; return STATUS_SUCCESS; mcontext: errno = EINVAL; ERR(handle, "malformed context \"%s\"", str); err: ERR(handle, "could not construct context from string"); free(tmp); sepol_context_free(tmp_con); return STATUS_ERR; } int sepol_context_to_string(sepol_handle_t * handle, const sepol_context_t * con, char **str_ptr) { int rc; char *str = NULL; size_t total_sz = 0, i; const size_t sizes[] = { strlen(con->user), /* user length */ strlen(con->role), /* role length */ strlen(con->type), /* type length */ (con->mls) ? strlen(con->mls) : 0, /* mls length */ ((con->mls) ? 3 : 2) + 1 /* mls has extra ":" also null byte */ }; for (i = 0; i < ARRAY_SIZE(sizes); i++) { if (__builtin_add_overflow(total_sz, sizes[i], &total_sz)) { ERR(handle, "invalid size, overflow at position: %zu", i); goto err; } } str = (char *)malloc(total_sz); if (!str) { ERR(handle, "out of memory"); goto err; } if (con->mls) { rc = snprintf(str, total_sz, "%s:%s:%s:%s", con->user, con->role, con->type, con->mls); } else { rc = snprintf(str, total_sz, "%s:%s:%s", con->user, con->role, con->type); } /* * rc is >= 0 on the size_t cast and is safe to promote * to an unsigned value. */ if (rc < 0 || (size_t)rc >= total_sz) { ERR(handle, "print error"); goto err; } *str_ptr = str; return STATUS_SUCCESS; err: ERR(handle, "could not convert context to string"); free(str); return STATUS_ERR; } libsepol-3.8.1/src/debug.c000066400000000000000000000030711476211737200153700ustar00rootroot00000000000000#include #include #include #include "handle.h" #include "debug.h" /* Deprecated */ struct sepol_handle sepol_compat_handle = { .msg_callback = sepol_msg_default_handler, .msg_callback_arg = NULL, }; void sepol_debug(int on) { sepol_compat_handle.msg_callback = (on) ? sepol_msg_default_handler : NULL; } /* End deprecated */ int sepol_msg_get_level(sepol_handle_t * handle) { return handle->msg_level; } const char *sepol_msg_get_channel(sepol_handle_t * handle) { return handle->msg_channel; } const char *sepol_msg_get_fname(sepol_handle_t * handle) { return handle->msg_fname; } #ifdef __GNUC__ __attribute__ ((format(printf, 3, 4))) #endif void sepol_msg_default_handler(void *varg __attribute__ ((unused)), sepol_handle_t * handle, const char *fmt, ...) { FILE *stream = NULL; va_list ap; switch (sepol_msg_get_level(handle)) { case SEPOL_MSG_ERR: case SEPOL_MSG_WARN: stream = stderr; break; case SEPOL_MSG_INFO: default: stream = stdout; break; } fprintf(stream, "%s.%s: ", sepol_msg_get_channel(handle), sepol_msg_get_fname(handle)); va_start(ap, fmt); vfprintf(stream, fmt, ap); va_end(ap); fprintf(stream, "\n"); } extern void sepol_msg_set_callback(sepol_handle_t * handle, #ifdef __GNUC__ __attribute__ ((format(printf, 3, 4))) #endif void (*msg_callback) (void *varg, sepol_handle_t * handle, const char *fmt, ...), void *msg_callback_arg) { handle->msg_callback = msg_callback; handle->msg_callback_arg = msg_callback_arg; } libsepol-3.8.1/src/debug.h000066400000000000000000000044071476211737200154010ustar00rootroot00000000000000/* * Copyright (C) 2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _SEPOL_INTERNAL_DEBUG_H_ #define _SEPOL_INTERNAL_DEBUG_H_ #include #include #include "handle.h" #define STATUS_SUCCESS 0 #define STATUS_ERR -1 #define STATUS_NODATA 1 /* FIXME: this needs to become a real function. Declaring variables * in a macro is _evil_ as it can shadow other variables in local scope. * The variable h has been renamed to _sepol_h to reduce this chance, but * it is still wrong. */ #define msg_write(handle_arg, level_arg, \ channel_arg, func_arg, ...) do { \ sepol_handle_t *_sepol_h = (handle_arg) ?: &sepol_compat_handle; \ if (_sepol_h->msg_callback) { \ _sepol_h->msg_fname = func_arg; \ _sepol_h->msg_channel = channel_arg; \ _sepol_h->msg_level = level_arg; \ \ _sepol_h->msg_callback( \ _sepol_h->msg_callback_arg, \ _sepol_h, __VA_ARGS__); \ } \ } while(0) #define ERR(handle, ...) \ msg_write(handle, SEPOL_MSG_ERR, "libsepol", \ __FUNCTION__, __VA_ARGS__) #define INFO(handle, ...) \ msg_write(handle, SEPOL_MSG_INFO, "libsepol", \ __FUNCTION__, __VA_ARGS__) #define WARN(handle, ...) \ msg_write(handle, SEPOL_MSG_WARN, "libsepol", \ __FUNCTION__, __VA_ARGS__) #ifdef __GNUC__ __attribute__ ((format(printf, 3, 4))) #endif extern void sepol_msg_default_handler(void *varg, sepol_handle_t * msg, const char *fmt, ...); extern struct sepol_handle sepol_compat_handle; #endif libsepol-3.8.1/src/ebitmap.c000066400000000000000000000275611476211737200157350ustar00rootroot00000000000000 /* Author : Stephen Smalley, */ /* FLASK */ /* * Implementation of the extensible bitmap type. */ #include #include #include #include "debug.h" #include "private.h" int ebitmap_or(ebitmap_t * dst, const ebitmap_t * e1, const ebitmap_t * e2) { const ebitmap_node_t *n1, *n2; ebitmap_node_t *new = NULL, **prev; ebitmap_init(dst); prev = &dst->node; n1 = e1->node; n2 = e2->node; while (n1 || n2) { new = (ebitmap_node_t *) malloc(sizeof(ebitmap_node_t)); if (!new) { ebitmap_destroy(dst); return -ENOMEM; } if (n1 && n2 && n1->startbit == n2->startbit) { new->startbit = n1->startbit; new->map = n1->map | n2->map; n1 = n1->next; n2 = n2->next; } else if (!n2 || (n1 && n1->startbit < n2->startbit)) { new->startbit = n1->startbit; new->map = n1->map; n1 = n1->next; } else { new->startbit = n2->startbit; new->map = n2->map; n2 = n2->next; } new->next = NULL; *prev = new; prev = &new->next; } dst->highbit = (e1->highbit > e2->highbit) ? e1->highbit : e2->highbit; return 0; } int ebitmap_union(ebitmap_t * dst, const ebitmap_t * e1) { ebitmap_t tmp; if (ebitmap_or(&tmp, dst, e1)) return -1; ebitmap_destroy(dst); dst->node = tmp.node; dst->highbit = tmp.highbit; return 0; } int ebitmap_and(ebitmap_t *dst, const ebitmap_t *e1, const ebitmap_t *e2) { const ebitmap_node_t *n1, *n2; ebitmap_node_t *new = NULL, **prev; ebitmap_init(dst); prev = &dst->node; n1 = e1->node; n2 = e2->node; while (n1 && n2) { if (n1->startbit == n2->startbit) { if (n1->map & n2->map) { new = malloc(sizeof(ebitmap_node_t)); if (!new) { ebitmap_destroy(dst); return -ENOMEM; } new->startbit = n1->startbit; new->map = n1->map & n2->map; new->next = NULL; *prev = new; prev = &new->next; } n1 = n1->next; n2 = n2->next; } else if (n1->startbit > n2->startbit) { n2 = n2->next; } else { n1 = n1->next; } } if (new) dst->highbit = new->startbit + MAPSIZE; return 0; } int ebitmap_xor(ebitmap_t *dst, const ebitmap_t *e1, const ebitmap_t *e2) { const ebitmap_node_t *n1, *n2; ebitmap_node_t *new = NULL, **prev; uint32_t startbit; MAPTYPE map; ebitmap_init(dst); prev = &dst->node; n1 = e1->node; n2 = e2->node; while (n1 || n2) { if (n1 && n2 && n1->startbit == n2->startbit) { startbit = n1->startbit; map = n1->map ^ n2->map; n1 = n1->next; n2 = n2->next; } else if (!n2 || (n1 && n1->startbit < n2->startbit)) { startbit = n1->startbit; map = n1->map; n1 = n1->next; } else { startbit = n2->startbit; map = n2->map; n2 = n2->next; } if (map != 0) { new = malloc(sizeof(ebitmap_node_t)); if (!new) { ebitmap_destroy(dst); return -ENOMEM; } new->startbit = startbit; new->map = map; new->next = NULL; *prev = new; prev = &new->next; } } if (new) dst->highbit = new->startbit + MAPSIZE; return 0; } int ebitmap_not(ebitmap_t *dst, const ebitmap_t *e1, unsigned int maxbit) { const ebitmap_node_t *n; ebitmap_node_t *new = NULL, **prev; uint32_t startbit, cur_startbit; MAPTYPE map; ebitmap_init(dst); prev = &dst->node; n = e1->node; for (cur_startbit = 0; cur_startbit < maxbit; cur_startbit += MAPSIZE) { if (n && n->startbit == cur_startbit) { startbit = n->startbit; map = ~n->map; n = n->next; } else { startbit = cur_startbit; map = ~((MAPTYPE) 0); } if (maxbit - cur_startbit < MAPSIZE) map &= (((MAPTYPE)1) << (maxbit - cur_startbit)) - 1; if (map != 0) { new = malloc(sizeof(ebitmap_node_t)); if (!new) { ebitmap_destroy(dst); return -ENOMEM; } new->startbit = startbit; new->map = map; new->next = NULL; *prev = new; prev = &new->next; } } if (new) dst->highbit = new->startbit + MAPSIZE; return 0; } int ebitmap_andnot(ebitmap_t *dst, const ebitmap_t *e1, const ebitmap_t *e2, unsigned int maxbit) { int rc; ebitmap_t e3; ebitmap_init(dst); rc = ebitmap_not(&e3, e2, maxbit); if (rc < 0) return rc; rc = ebitmap_and(dst, e1, &e3); ebitmap_destroy(&e3); if (rc < 0) return rc; return 0; } unsigned int ebitmap_cardinality(const ebitmap_t *e1) { unsigned int count = 0; const ebitmap_node_t *n; for (n = e1->node; n; n = n->next) { count += __builtin_popcountll(n->map); } return count; } int ebitmap_hamming_distance(const ebitmap_t * e1, const ebitmap_t * e2) { int rc; ebitmap_t tmp; int distance; if (ebitmap_cmp(e1, e2)) return 0; rc = ebitmap_xor(&tmp, e1, e2); if (rc < 0) return -1; distance = ebitmap_cardinality(&tmp); ebitmap_destroy(&tmp); return distance; } int ebitmap_cmp(const ebitmap_t * e1, const ebitmap_t * e2) { const ebitmap_node_t *n1, *n2; if (e1->highbit != e2->highbit) return 0; n1 = e1->node; n2 = e2->node; while (n1 && n2 && (n1->startbit == n2->startbit) && (n1->map == n2->map)) { n1 = n1->next; n2 = n2->next; } if (n1 || n2) return 0; return 1; } int ebitmap_cpy(ebitmap_t * dst, const ebitmap_t * src) { const ebitmap_node_t *n; ebitmap_node_t *new = NULL, **prev; ebitmap_init(dst); n = src->node; prev = &dst->node; while (n) { new = (ebitmap_node_t *) malloc(sizeof(ebitmap_node_t)); if (!new) { ebitmap_destroy(dst); return -ENOMEM; } new->startbit = n->startbit; new->map = n->map; new->next = NULL; *prev = new; prev = &new->next; n = n->next; } dst->highbit = src->highbit; return 0; } int ebitmap_contains(const ebitmap_t * e1, const ebitmap_t * e2) { const ebitmap_node_t *n1, *n2; if (e1->highbit < e2->highbit) return 0; n1 = e1->node; n2 = e2->node; while (n1 && n2 && (n1->startbit <= n2->startbit)) { if (n1->startbit < n2->startbit) { n1 = n1->next; continue; } if ((n1->map & n2->map) != n2->map) return 0; n1 = n1->next; n2 = n2->next; } if (n2) return 0; return 1; } int ebitmap_match_any(const ebitmap_t *e1, const ebitmap_t *e2) { const ebitmap_node_t *n1 = e1->node; const ebitmap_node_t *n2 = e2->node; while (n1 && n2) { if (n1->startbit < n2->startbit) { n1 = n1->next; } else if (n2->startbit < n1->startbit) { n2 = n2->next; } else { if (n1->map & n2->map) { return 1; } n1 = n1->next; n2 = n2->next; } } return 0; } int ebitmap_get_bit(const ebitmap_t * e, unsigned int bit) { const ebitmap_node_t *n; if (e->highbit < bit) return 0; n = e->node; while (n && (n->startbit <= bit)) { if ((n->startbit + MAPSIZE) > bit) { if (n->map & (MAPBIT << (bit - n->startbit))) return 1; else return 0; } n = n->next; } return 0; } int ebitmap_set_bit(ebitmap_t * e, unsigned int bit, int value) { ebitmap_node_t *n, *prev, *new; uint32_t startbit = bit & ~(MAPSIZE - 1); uint32_t highbit = startbit + MAPSIZE; if (highbit == 0) { ERR(NULL, "bitmap overflow, bit 0x%x", bit); return -EINVAL; } prev = 0; n = e->node; while (n && n->startbit <= bit) { if ((n->startbit + MAPSIZE) > bit) { if (value) { n->map |= (MAPBIT << (bit - n->startbit)); } else { n->map &= ~(MAPBIT << (bit - n->startbit)); if (!n->map) { /* drop this node from the bitmap */ if (!n->next) { /* * this was the highest map * within the bitmap */ if (prev) e->highbit = prev->startbit + MAPSIZE; else e->highbit = 0; } if (prev) prev->next = n->next; else e->node = n->next; free(n); } } return 0; } prev = n; n = n->next; } if (!value) return 0; new = (ebitmap_node_t *) malloc(sizeof(ebitmap_node_t)); if (!new) return -ENOMEM; new->startbit = startbit; new->map = (MAPBIT << (bit - new->startbit)); if (!n) { /* this node will be the highest map within the bitmap */ e->highbit = highbit; } if (prev) { new->next = prev->next; prev->next = new; } else { new->next = e->node; e->node = new; } return 0; } int ebitmap_init_range(ebitmap_t * e, unsigned int minbit, unsigned int maxbit) { ebitmap_node_t *new = NULL, **prev; uint32_t minstartbit = minbit & ~(MAPSIZE - 1); uint32_t maxstartbit = maxbit & ~(MAPSIZE - 1); uint32_t minhighbit = minstartbit + MAPSIZE; uint32_t maxhighbit = maxstartbit + MAPSIZE; uint32_t startbit; MAPTYPE mask; ebitmap_init(e); if (minbit > maxbit) return -EINVAL; if (minhighbit == 0 || maxhighbit == 0) return -EOVERFLOW; prev = &e->node; for (startbit = minstartbit; startbit <= maxstartbit; startbit += MAPSIZE) { new = malloc(sizeof(ebitmap_node_t)); if (!new) return -ENOMEM; new->next = NULL; new->startbit = startbit; if (startbit != minstartbit && startbit != maxstartbit) { new->map = ~((MAPTYPE)0); } else if (startbit != maxstartbit) { new->map = ~((MAPTYPE)0) << (minbit - startbit); } else if (startbit != minstartbit) { new->map = ~((MAPTYPE)0) >> (MAPSIZE - (maxbit - startbit + 1)); } else { mask = ~((MAPTYPE)0) >> (MAPSIZE - (maxbit - minbit + 1)); new->map = (mask << (minbit - startbit)); } *prev = new; prev = &new->next; } e->highbit = maxhighbit; return 0; } unsigned int ebitmap_highest_set_bit(const ebitmap_t * e) { const ebitmap_node_t *n; MAPTYPE map; unsigned int pos = 0; n = e->node; if (!n) return 0; while (n->next) n = n->next; map = n->map; while (map >>= 1) pos++; return n->startbit + pos; } void ebitmap_destroy(ebitmap_t * e) { ebitmap_node_t *n, *temp; if (!e) return; n = e->node; while (n) { temp = n; n = n->next; free(temp); } e->highbit = 0; e->node = 0; return; } int ebitmap_read(ebitmap_t * e, void *fp) { int rc; ebitmap_node_t *n, *l; uint32_t buf[3], mapsize, count, i; uint64_t map; ebitmap_init(e); rc = next_entry(buf, fp, sizeof(uint32_t) * 3); if (rc < 0) goto bad; mapsize = le32_to_cpu(buf[0]); e->highbit = le32_to_cpu(buf[1]); count = le32_to_cpu(buf[2]); if (mapsize != MAPSIZE) { ERR(NULL, "security: ebitmap: map size %d does not match my size %zu (high bit was %d)", mapsize, MAPSIZE, e->highbit); goto bad; } if (!e->highbit) { e->node = NULL; goto ok; } if (e->highbit & (MAPSIZE - 1)) { ERR(NULL, "security: ebitmap: high bit (%d) is not a multiple of the map size (%zu)", e->highbit, MAPSIZE); goto bad; } if (e->highbit && !count) goto bad; l = NULL; for (i = 0; i < count; i++) { rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) { ERR(NULL, "security: ebitmap: truncated map"); goto bad; } n = (ebitmap_node_t *) malloc(sizeof(ebitmap_node_t)); if (!n) { ERR(NULL, "security: ebitmap: out of memory"); rc = -ENOMEM; goto bad; } memset(n, 0, sizeof(ebitmap_node_t)); n->startbit = le32_to_cpu(buf[0]); if (n->startbit & (MAPSIZE - 1)) { ERR(NULL, "security: ebitmap start bit (%d) is not a multiple of the map size (%zu)", n->startbit, MAPSIZE); goto bad_free; } if (n->startbit > (e->highbit - MAPSIZE)) { ERR(NULL, "security: ebitmap start bit (%d) is beyond the end of the bitmap (%zu)", n->startbit, (e->highbit - MAPSIZE)); goto bad_free; } rc = next_entry(&map, fp, sizeof(uint64_t)); if (rc < 0) { ERR(NULL, "security: ebitmap: truncated map"); goto bad_free; } n->map = le64_to_cpu(map); if (!n->map) { ERR(NULL, "security: ebitmap: null map in ebitmap (startbit %d)", n->startbit); goto bad_free; } if (l) { if (n->startbit <= l->startbit) { ERR(NULL, "security: ebitmap: start bit %d comes after start bit %d", n->startbit, l->startbit); goto bad_free; } l->next = n; } else e->node = n; l = n; } if (count && l->startbit + MAPSIZE != e->highbit) { ERR(NULL, "security: ebitmap: high bit %u has not the expected value %zu", e->highbit, l->startbit + MAPSIZE); goto bad; } ok: rc = 0; out: return rc; bad_free: free(n); bad: if (!rc) rc = -EINVAL; ebitmap_destroy(e); goto out; } /* FLASK */ libsepol-3.8.1/src/expand.c000066400000000000000000002550431476211737200155710ustar00rootroot00000000000000/* Authors: Karl MacMillan * Jason Tang * Joshua Brindle * * Copyright (C) 2004-2005 Tresys Technology, LLC * Copyright (C) 2007 Red Hat, Inc. * Copyright (C) 2017 Mellanox Technologies, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "context.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "debug.h" #include "private.h" typedef struct expand_state { int verbose; uint32_t *typemap; uint32_t *boolmap; uint32_t *rolemap; uint32_t *usermap; policydb_t *base; policydb_t *out; sepol_handle_t *handle; int expand_neverallow; } expand_state_t; static void expand_state_init(expand_state_t * state) { memset(state, 0, sizeof(expand_state_t)); } static int map_ebitmap(ebitmap_t * src, ebitmap_t * dst, uint32_t * map) { unsigned int i; ebitmap_node_t *tnode; ebitmap_init(dst); ebitmap_for_each_positive_bit(src, tnode, i) { if (!map[i]) continue; if (ebitmap_set_bit(dst, map[i] - 1, 1)) return -1; } return 0; } static int ebitmap_expand_roles(policydb_t *p, ebitmap_t *roles) { ebitmap_node_t *node; unsigned int bit; role_datum_t *role; ebitmap_t tmp; ebitmap_init(&tmp); ebitmap_for_each_positive_bit(roles, node, bit) { role = p->role_val_to_struct[bit]; assert(role); if (role->flavor != ROLE_ATTRIB) { if (ebitmap_set_bit(&tmp, bit, 1)) { ebitmap_destroy(&tmp); return -1; } } else { if (ebitmap_union(&tmp, &role->roles)) { ebitmap_destroy(&tmp); return -1; } } } ebitmap_destroy(roles); if (ebitmap_cpy(roles, &tmp)) { ebitmap_destroy(&tmp); return -1; } ebitmap_destroy(&tmp); return 0; } static int type_copy_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) { int ret; char *id, *new_id; type_datum_t *type, *new_type; expand_state_t *state; id = (char *)key; type = (type_datum_t *) datum; state = (expand_state_t *) data; if ((type->flavor == TYPE_TYPE && !type->primary) || type->flavor == TYPE_ALIAS) { /* aliases are handled later */ return 0; } if (!is_id_enabled(id, state->base, SYM_TYPES)) { /* identifier's scope is not enabled */ return 0; } if (state->verbose) INFO(state->handle, "copying type or attribute %s", id); new_id = strdup(id); if (new_id == NULL) { ERR(state->handle, "Out of memory!"); return -1; } new_type = (type_datum_t *) malloc(sizeof(type_datum_t)); if (!new_type) { ERR(state->handle, "Out of memory!"); free(new_id); return SEPOL_ENOMEM; } memset(new_type, 0, sizeof(type_datum_t)); new_type->flavor = type->flavor; new_type->flags = type->flags; new_type->s.value = ++state->out->p_types.nprim; if (new_type->s.value > UINT16_MAX) { free(new_id); free(new_type); ERR(state->handle, "type space overflow"); return -1; } new_type->primary = 1; state->typemap[type->s.value - 1] = new_type->s.value; ret = hashtab_insert(state->out->p_types.table, (hashtab_key_t) new_id, (hashtab_datum_t) new_type); if (ret) { free(new_id); free(new_type); ERR(state->handle, "hashtab overflow"); return -1; } if (new_type->flags & TYPE_FLAGS_PERMISSIVE) if (ebitmap_set_bit(&state->out->permissive_map, new_type->s.value, 1)) { ERR(state->handle, "Out of memory!"); return -1; } return 0; } static int attr_convert_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) { char *id; type_datum_t *type, *new_type; expand_state_t *state; ebitmap_t tmp_union; id = (char *)key; type = (type_datum_t *) datum; state = (expand_state_t *) data; if (type->flavor != TYPE_ATTRIB) return 0; if (!is_id_enabled(id, state->base, SYM_TYPES)) { /* identifier's scope is not enabled */ return 0; } if (state->verbose) INFO(state->handle, "converting attribute %s", id); new_type = hashtab_search(state->out->p_types.table, id); if (!new_type) { ERR(state->handle, "attribute %s vanished!", id); return -1; } if (map_ebitmap(&type->types, &tmp_union, state->typemap)) { ERR(state->handle, "out of memory"); return -1; } /* then union tmp_union onto &new_type->types */ if (ebitmap_union(&new_type->types, &tmp_union)) { ERR(state->handle, "Out of memory!"); return -1; } ebitmap_destroy(&tmp_union); return 0; } static int perm_copy_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) { int ret; char *id, *new_id; symtab_t *s; perm_datum_t *perm, *new_perm; id = key; perm = (perm_datum_t *) datum; s = (symtab_t *) data; new_perm = (perm_datum_t *) malloc(sizeof(perm_datum_t)); if (!new_perm) { return -1; } memset(new_perm, 0, sizeof(perm_datum_t)); new_id = strdup(id); if (!new_id) { free(new_perm); return -1; } new_perm->s.value = perm->s.value; s->nprim++; ret = hashtab_insert(s->table, new_id, (hashtab_datum_t) new_perm); if (ret) { free(new_id); free(new_perm); return -1; } return 0; } static int common_copy_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) { int ret; char *id, *new_id; common_datum_t *common, *new_common; expand_state_t *state; id = (char *)key; common = (common_datum_t *) datum; state = (expand_state_t *) data; if (state->verbose) INFO(state->handle, "copying common %s", id); new_common = (common_datum_t *) malloc(sizeof(common_datum_t)); if (!new_common) { ERR(state->handle, "Out of memory!"); return -1; } memset(new_common, 0, sizeof(common_datum_t)); if (symtab_init(&new_common->permissions, PERM_SYMTAB_SIZE)) { ERR(state->handle, "Out of memory!"); free(new_common); return -1; } new_id = strdup(id); if (!new_id) { ERR(state->handle, "Out of memory!"); /* free memory created by symtab_init first, then free new_common */ symtab_destroy(&new_common->permissions); free(new_common); return -1; } new_common->s.value = common->s.value; state->out->p_commons.nprim++; ret = hashtab_insert(state->out->p_commons.table, new_id, (hashtab_datum_t) new_common); if (ret) { ERR(state->handle, "hashtab overflow"); free(new_common); free(new_id); return -1; } if (hashtab_map (common->permissions.table, perm_copy_callback, &new_common->permissions)) { ERR(state->handle, "Out of memory!"); return -1; } return 0; } static int constraint_node_clone(constraint_node_t ** dst, constraint_node_t * src, expand_state_t * state) { constraint_node_t *new_con = NULL, *last_new_con = NULL; constraint_expr_t *new_expr = NULL; *dst = NULL; while (src != NULL) { constraint_expr_t *expr, *expr_l = NULL; new_con = (constraint_node_t *) malloc(sizeof(constraint_node_t)); if (!new_con) { goto out_of_mem; } memset(new_con, 0, sizeof(constraint_node_t)); new_con->permissions = src->permissions; for (expr = src->expr; expr; expr = expr->next) { if ((new_expr = calloc(1, sizeof(*new_expr))) == NULL) { goto out_of_mem; } if (constraint_expr_init(new_expr) == -1) { goto out_of_mem; } new_expr->expr_type = expr->expr_type; new_expr->attr = expr->attr; new_expr->op = expr->op; if (new_expr->expr_type == CEXPR_NAMES) { if (new_expr->attr & CEXPR_TYPE) { /* * Copy over constraint policy source types and/or * attributes for sepol_compute_av_reason_buffer(3) * so that utilities can analyse constraint errors. */ if (map_ebitmap(&expr->type_names->types, &new_expr->type_names->types, state->typemap)) { ERR(NULL, "Failed to map type_names->types"); goto out_of_mem; } /* Type sets require expansion and conversion. */ if (expand_convert_type_set(state->out, state-> typemap, expr-> type_names, &new_expr-> names, 1)) { goto out_of_mem; } } else if (new_expr->attr & CEXPR_ROLE) { if (map_ebitmap(&expr->names, &new_expr->names, state->rolemap)) { goto out_of_mem; } if (ebitmap_expand_roles(state->out, &new_expr->names)) { goto out_of_mem; } } else if (new_expr->attr & CEXPR_USER) { if (map_ebitmap(&expr->names, &new_expr->names, state->usermap)) { goto out_of_mem; } } else { /* Other kinds of sets do not. */ if (ebitmap_cpy(&new_expr->names, &expr->names)) { goto out_of_mem; } } } if (expr_l) { expr_l->next = new_expr; } else { new_con->expr = new_expr; } expr_l = new_expr; new_expr = NULL; } if (last_new_con == NULL) { *dst = new_con; } else { last_new_con->next = new_con; } last_new_con = new_con; src = src->next; } return 0; out_of_mem: ERR(state->handle, "Out of memory!"); if (new_con) free(new_con); constraint_expr_destroy(new_expr); return -1; } static int class_copy_default_new_object(expand_state_t *state, class_datum_t *olddatum, class_datum_t *newdatum) { if (olddatum->default_user) { if (newdatum->default_user && olddatum->default_user != newdatum->default_user) { ERR(state->handle, "Found conflicting default user definitions"); return SEPOL_ENOTSUP; } newdatum->default_user = olddatum->default_user; } if (olddatum->default_role) { if (newdatum->default_role && olddatum->default_role != newdatum->default_role) { ERR(state->handle, "Found conflicting default role definitions"); return SEPOL_ENOTSUP; } newdatum->default_role = olddatum->default_role; } if (olddatum->default_type) { if (newdatum->default_type && olddatum->default_type != newdatum->default_type) { ERR(state->handle, "Found conflicting default type definitions"); return SEPOL_ENOTSUP; } newdatum->default_type = olddatum->default_type; } if (olddatum->default_range) { if (newdatum->default_range && olddatum->default_range != newdatum->default_range) { ERR(state->handle, "Found conflicting default range definitions"); return SEPOL_ENOTSUP; } newdatum->default_range = olddatum->default_range; } return 0; } static int class_copy_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) { int ret; char *id, *new_id; class_datum_t *class, *new_class; expand_state_t *state; id = (char *)key; class = (class_datum_t *) datum; state = (expand_state_t *) data; if (!is_id_enabled(id, state->base, SYM_CLASSES)) { /* identifier's scope is not enabled */ return 0; } if (state->verbose) INFO(state->handle, "copying class %s", id); new_class = (class_datum_t *) malloc(sizeof(class_datum_t)); if (!new_class) { ERR(state->handle, "Out of memory!"); return -1; } memset(new_class, 0, sizeof(class_datum_t)); if (symtab_init(&new_class->permissions, PERM_SYMTAB_SIZE)) { ERR(state->handle, "Out of memory!"); free(new_class); return -1; } new_class->s.value = class->s.value; state->out->p_classes.nprim++; ret = class_copy_default_new_object(state, class, new_class); if (ret) { free(new_class); return ret; } new_id = strdup(id); if (!new_id) { ERR(state->handle, "Out of memory!"); free(new_class); return -1; } ret = hashtab_insert(state->out->p_classes.table, new_id, (hashtab_datum_t) new_class); if (ret) { ERR(state->handle, "hashtab overflow"); free(new_class); free(new_id); return -1; } if (hashtab_map (class->permissions.table, perm_copy_callback, &new_class->permissions)) { ERR(state->handle, "hashtab overflow"); return -1; } if (class->comkey) { new_class->comkey = strdup(class->comkey); if (!new_class->comkey) { ERR(state->handle, "Out of memory!"); return -1; } new_class->comdatum = hashtab_search(state->out->p_commons.table, new_class->comkey); if (!new_class->comdatum) { ERR(state->handle, "could not find common datum %s", new_class->comkey); return -1; } new_class->permissions.nprim += new_class->comdatum->permissions.nprim; } return 0; } static int constraint_copy_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) { char *id; class_datum_t *class, *new_class; expand_state_t *state; id = (char *)key; class = (class_datum_t *) datum; state = (expand_state_t *) data; new_class = hashtab_search(state->out->p_classes.table, id); if (!new_class) { ERR(state->handle, "class %s vanished", id); return -1; } /* constraints */ if (constraint_node_clone (&new_class->constraints, class->constraints, state) == -1 || constraint_node_clone(&new_class->validatetrans, class->validatetrans, state) == -1) { return -1; } return 0; } /* * The boundaries have to be copied after the types/roles/users are copied, * because it refers hashtab to lookup destinated objects. */ static int type_bounds_copy_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) { expand_state_t *state = (expand_state_t *) data; type_datum_t *type = (type_datum_t *) datum; type_datum_t *dest; uint32_t bounds_val; if (!type->bounds) return 0; if (!is_id_enabled((char *)key, state->base, SYM_TYPES)) return 0; bounds_val = state->typemap[type->bounds - 1]; dest = hashtab_search(state->out->p_types.table, (char *)key); if (!dest) { ERR(state->handle, "Type lookup failed for %s", (char *)key); return -1; } if (dest->bounds != 0 && dest->bounds != bounds_val) { ERR(state->handle, "Inconsistent boundary for %s", (char *)key); return -1; } dest->bounds = bounds_val; return 0; } static int role_bounds_copy_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) { expand_state_t *state = (expand_state_t *) data; role_datum_t *role = (role_datum_t *) datum; role_datum_t *dest; uint32_t bounds_val; if (!role->bounds) return 0; if (!is_id_enabled((char *)key, state->base, SYM_ROLES)) return 0; bounds_val = state->rolemap[role->bounds - 1]; dest = hashtab_search(state->out->p_roles.table, (char *)key); if (!dest) { ERR(state->handle, "Role lookup failed for %s", (char *)key); return -1; } if (dest->bounds != 0 && dest->bounds != bounds_val) { ERR(state->handle, "Inconsistent boundary for %s", (char *)key); return -1; } dest->bounds = bounds_val; return 0; } static int user_bounds_copy_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) { expand_state_t *state = (expand_state_t *) data; user_datum_t *user = (user_datum_t *) datum; user_datum_t *dest; uint32_t bounds_val; if (!user->bounds) return 0; if (!is_id_enabled((char *)key, state->base, SYM_USERS)) return 0; bounds_val = state->usermap[user->bounds - 1]; dest = hashtab_search(state->out->p_users.table, (char *)key); if (!dest) { ERR(state->handle, "User lookup failed for %s", (char *)key); return -1; } if (dest->bounds != 0 && dest->bounds != bounds_val) { ERR(state->handle, "Inconsistent boundary for %s", (char *)key); return -1; } dest->bounds = bounds_val; return 0; } /* The aliases have to be copied after the types and attributes to be certain that * the out symbol table will have the type that the alias refers. Otherwise, we * won't be able to find the type value for the alias. We can't depend on the * declaration ordering because of the hash table. */ static int alias_copy_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) { int ret; char *id, *new_id; type_datum_t *alias, *new_alias; expand_state_t *state; uint32_t prival; id = (char *)key; alias = (type_datum_t *) datum; state = (expand_state_t *) data; /* ignore regular types */ if (alias->flavor == TYPE_TYPE && alias->primary) return 0; /* ignore attributes */ if (alias->flavor == TYPE_ATTRIB) return 0; if (alias->flavor == TYPE_ALIAS) prival = alias->primary; else prival = alias->s.value; if (!is_id_enabled(state->base->p_type_val_to_name[prival - 1], state->base, SYM_TYPES)) { /* The primary type for this alias is not enabled, the alias * shouldn't be either */ return 0; } if (state->verbose) INFO(state->handle, "copying alias %s", id); new_id = strdup(id); if (!new_id) { ERR(state->handle, "Out of memory!"); return -1; } new_alias = (type_datum_t *) malloc(sizeof(type_datum_t)); if (!new_alias) { ERR(state->handle, "Out of memory!"); free(new_id); return SEPOL_ENOMEM; } memset(new_alias, 0, sizeof(type_datum_t)); if (alias->flavor == TYPE_TYPE) new_alias->s.value = state->typemap[alias->s.value - 1]; else if (alias->flavor == TYPE_ALIAS) new_alias->s.value = state->typemap[alias->primary - 1]; else assert(0); /* unreachable */ new_alias->flags = alias->flags; ret = hashtab_insert(state->out->p_types.table, (hashtab_key_t) new_id, (hashtab_datum_t) new_alias); if (ret) { ERR(state->handle, "hashtab overflow"); free(new_alias); free(new_id); return -1; } state->typemap[alias->s.value - 1] = new_alias->s.value; if (new_alias->flags & TYPE_FLAGS_PERMISSIVE) if (ebitmap_set_bit(&state->out->permissive_map, new_alias->s.value, 1)) { ERR(state->handle, "Out of memory!"); return -1; } return 0; } static int role_remap_dominates(hashtab_key_t key __attribute__ ((unused)), hashtab_datum_t datum, void *data) { ebitmap_t mapped_roles; role_datum_t *role = (role_datum_t *) datum; expand_state_t *state = (expand_state_t *) data; if (map_ebitmap(&role->dominates, &mapped_roles, state->rolemap)) return -1; ebitmap_destroy(&role->dominates); if (ebitmap_cpy(&role->dominates, &mapped_roles)) return -1; ebitmap_destroy(&mapped_roles); return 0; } /* For the role attribute in the base module, escalate its counterpart's * types.types ebitmap in the out module to the counterparts of all the * regular role that belongs to the current role attribute. Note, must be * invoked after role_copy_callback so that state->rolemap is available. */ static int role_fix_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) { char *id, *base_reg_role_id; role_datum_t *role, *new_role, *regular_role; expand_state_t *state; ebitmap_node_t *rnode; unsigned int i; ebitmap_t mapped_roles; id = key; role = (role_datum_t *)datum; state = (expand_state_t *)data; if (strcmp(id, OBJECT_R) == 0) { /* object_r is never a role attribute by far */ return 0; } if (!is_id_enabled(id, state->base, SYM_ROLES)) { /* identifier's scope is not enabled */ return 0; } if (role->flavor != ROLE_ATTRIB) return 0; if (state->verbose) INFO(state->handle, "fixing role attribute %s", id); new_role = (role_datum_t *)hashtab_search(state->out->p_roles.table, id); assert(new_role != NULL && new_role->flavor == ROLE_ATTRIB); ebitmap_init(&mapped_roles); if (map_ebitmap(&role->roles, &mapped_roles, state->rolemap)) return -1; if (ebitmap_union(&new_role->roles, &mapped_roles)) { ERR(state->handle, "Out of memory!"); ebitmap_destroy(&mapped_roles); return -1; } ebitmap_destroy(&mapped_roles); ebitmap_for_each_positive_bit(&role->roles, rnode, i) { /* take advantage of sym_val_to_name[] * of the base module */ base_reg_role_id = state->base->p_role_val_to_name[i]; regular_role = (role_datum_t *)hashtab_search( state->out->p_roles.table, base_reg_role_id); assert(regular_role != NULL && regular_role->flavor == ROLE_ROLE); if (ebitmap_union(®ular_role->types.types, &new_role->types.types)) { ERR(state->handle, "Out of memory!"); return -1; } } return 0; } static int role_copy_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) { int ret; char *id, *new_id; role_datum_t *role; role_datum_t *new_role; expand_state_t *state; ebitmap_t tmp_union_types; id = key; role = (role_datum_t *) datum; state = (expand_state_t *) data; if (strcmp(id, OBJECT_R) == 0) { /* object_r is always value 1 */ state->rolemap[role->s.value - 1] = 1; return 0; } if (!is_id_enabled(id, state->base, SYM_ROLES)) { /* identifier's scope is not enabled */ return 0; } if (state->verbose) INFO(state->handle, "copying role %s", id); new_role = (role_datum_t *) hashtab_search(state->out->p_roles.table, id); if (!new_role) { new_role = (role_datum_t *) malloc(sizeof(role_datum_t)); if (!new_role) { ERR(state->handle, "Out of memory!"); return -1; } memset(new_role, 0, sizeof(role_datum_t)); new_id = strdup(id); if (!new_id) { ERR(state->handle, "Out of memory!"); free(new_role); return -1; } state->out->p_roles.nprim++; new_role->flavor = role->flavor; new_role->s.value = state->out->p_roles.nprim; state->rolemap[role->s.value - 1] = new_role->s.value; ret = hashtab_insert(state->out->p_roles.table, (hashtab_key_t) new_id, (hashtab_datum_t) new_role); if (ret) { ERR(state->handle, "hashtab overflow"); free(new_role); free(new_id); return -1; } } /* The dominates bitmap is going to be wrong for the moment, * we'll come back later and remap them, after we are sure all * the roles have been added */ if (ebitmap_union(&new_role->dominates, &role->dominates)) { ERR(state->handle, "Out of memory!"); return -1; } ebitmap_init(&tmp_union_types); /* convert types in the role datum in the global symtab */ if (expand_convert_type_set (state->out, state->typemap, &role->types, &tmp_union_types, 1)) { ebitmap_destroy(&tmp_union_types); ERR(state->handle, "Out of memory!"); return -1; } if (ebitmap_union(&new_role->types.types, &tmp_union_types)) { ERR(state->handle, "Out of memory!"); ebitmap_destroy(&tmp_union_types); return -1; } ebitmap_destroy(&tmp_union_types); return 0; } int mls_semantic_level_expand(mls_semantic_level_t * sl, mls_level_t * l, policydb_t * p, sepol_handle_t * h) { mls_semantic_cat_t *cat; level_datum_t *levdatum; unsigned int i; mls_level_init(l); if (!p->mls) return 0; /* Required not declared. */ if (!sl->sens) return 0; /* Invalid sensitivity */ if (sl->sens > p->p_levels.nprim || !p->p_sens_val_to_name[sl->sens - 1]) return -1; l->sens = sl->sens; levdatum = (level_datum_t *) hashtab_search(p->p_levels.table, p->p_sens_val_to_name[l->sens - 1]); if (!levdatum) { ERR(h, "%s: Impossible situation found, nothing in p_levels.table.", __func__); errno = ENOENT; return -1; } for (cat = sl->cat; cat; cat = cat->next) { if (!cat->low || cat->low > cat->high) { ERR(h, "Category range is not valid %s.%s", cat->low > 0 ? p->p_cat_val_to_name[cat->low - 1] : "Invalid", cat->high > 0 ? p->p_cat_val_to_name[cat->high - 1] : "Invalid"); return -1; } for (i = cat->low - 1; i < cat->high; i++) { if (!ebitmap_get_bit(&levdatum->level->cat, i)) { ERR(h, "Category %s can not be associated with " "level %s", p->p_cat_val_to_name[i], p->p_sens_val_to_name[l->sens - 1]); return -1; } if (ebitmap_set_bit(&l->cat, i, 1)) { ERR(h, "Out of memory!"); return -1; } } } return 0; } int mls_semantic_range_expand(mls_semantic_range_t * sr, mls_range_t * r, policydb_t * p, sepol_handle_t * h) { if (mls_semantic_level_expand(&sr->level[0], &r->level[0], p, h) < 0) return -1; if (mls_semantic_level_expand(&sr->level[1], &r->level[1], p, h) < 0) { mls_level_destroy(&r->level[0]); return -1; } if (!mls_level_dom(&r->level[1], &r->level[0])) { mls_range_destroy(r); ERR(h, "MLS range high level does not dominate low level"); return -1; } return 0; } static int user_copy_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) { int ret; expand_state_t *state; user_datum_t *user; user_datum_t *new_user; char *id, *new_id; ebitmap_t tmp_union; id = key; user = (user_datum_t *) datum; state = (expand_state_t *) data; if (!is_id_enabled(id, state->base, SYM_USERS)) { /* identifier's scope is not enabled */ return 0; } if (state->verbose) INFO(state->handle, "copying user %s", id); new_user = (user_datum_t *) hashtab_search(state->out->p_users.table, id); if (!new_user) { new_user = (user_datum_t *) malloc(sizeof(user_datum_t)); if (!new_user) { ERR(state->handle, "Out of memory!"); return -1; } memset(new_user, 0, sizeof(user_datum_t)); state->out->p_users.nprim++; new_user->s.value = state->out->p_users.nprim; state->usermap[user->s.value - 1] = new_user->s.value; new_id = strdup(id); if (!new_id) { ERR(state->handle, "Out of memory!"); free(new_user); return -1; } ret = hashtab_insert(state->out->p_users.table, (hashtab_key_t) new_id, (hashtab_datum_t) new_user); if (ret) { ERR(state->handle, "hashtab overflow"); user_datum_destroy(new_user); free(new_user); free(new_id); return -1; } /* expand the semantic MLS info */ if (mls_semantic_range_expand(&user->range, &new_user->exp_range, state->out, state->handle)) { return -1; } if (mls_semantic_level_expand(&user->dfltlevel, &new_user->exp_dfltlevel, state->out, state->handle)) { return -1; } if (!mls_level_between(&new_user->exp_dfltlevel, &new_user->exp_range.level[0], &new_user->exp_range.level[1])) { ERR(state->handle, "default level not within user " "range"); return -1; } } else { /* require that the MLS info match */ mls_range_t tmp_range; mls_level_t tmp_level; if (mls_semantic_range_expand(&user->range, &tmp_range, state->out, state->handle)) { return -1; } if (mls_semantic_level_expand(&user->dfltlevel, &tmp_level, state->out, state->handle)) { mls_range_destroy(&tmp_range); return -1; } if (!mls_range_eq(&new_user->exp_range, &tmp_range) || !mls_level_eq(&new_user->exp_dfltlevel, &tmp_level)) { mls_range_destroy(&tmp_range); mls_level_destroy(&tmp_level); return -1; } mls_range_destroy(&tmp_range); mls_level_destroy(&tmp_level); } ebitmap_init(&tmp_union); /* get global roles for this user */ if (role_set_expand(&user->roles, &tmp_union, state->out, state->base, state->rolemap)) { ERR(state->handle, "Out of memory!"); ebitmap_destroy(&tmp_union); return -1; } if (ebitmap_union(&new_user->roles.roles, &tmp_union)) { ERR(state->handle, "Out of memory!"); ebitmap_destroy(&tmp_union); return -1; } ebitmap_destroy(&tmp_union); return 0; } static int bool_copy_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) { int ret; expand_state_t *state; cond_bool_datum_t *boolean, *new_bool; char *id, *new_id; id = key; boolean = (cond_bool_datum_t *) datum; state = (expand_state_t *) data; if (!is_id_enabled(id, state->base, SYM_BOOLS)) { /* identifier's scope is not enabled */ return 0; } if (boolean->flags & COND_BOOL_FLAGS_TUNABLE) { /* Skip tunables */ return 0; } if (state->verbose) INFO(state->handle, "copying boolean %s", id); new_bool = (cond_bool_datum_t *) malloc(sizeof(cond_bool_datum_t)); if (!new_bool) { ERR(state->handle, "Out of memory!"); return -1; } new_id = strdup(id); if (!new_id) { ERR(state->handle, "Out of memory!"); free(new_bool); return -1; } state->out->p_bools.nprim++; new_bool->s.value = state->out->p_bools.nprim; ret = hashtab_insert(state->out->p_bools.table, (hashtab_key_t) new_id, (hashtab_datum_t) new_bool); if (ret) { ERR(state->handle, "hashtab overflow"); free(new_bool); free(new_id); return -1; } state->boolmap[boolean->s.value - 1] = new_bool->s.value; new_bool->state = boolean->state; new_bool->flags = boolean->flags; return 0; } static int sens_copy_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) { expand_state_t *state = (expand_state_t *) data; level_datum_t *level = (level_datum_t *) datum, *new_level = NULL; char *id = (char *)key, *new_id = NULL; if (!is_id_enabled(id, state->base, SYM_LEVELS)) { /* identifier's scope is not enabled */ return 0; } if (state->verbose) INFO(state->handle, "copying sensitivity level %s", id); new_level = (level_datum_t *) malloc(sizeof(level_datum_t)); if (!new_level) goto out_of_mem; level_datum_init(new_level); new_level->level = (mls_level_t *) malloc(sizeof(mls_level_t)); if (!new_level->level) goto out_of_mem; mls_level_init(new_level->level); new_id = strdup(id); if (!new_id) goto out_of_mem; if (mls_level_cpy(new_level->level, level->level)) { goto out_of_mem; } new_level->isalias = level->isalias; state->out->p_levels.nprim++; if (hashtab_insert(state->out->p_levels.table, (hashtab_key_t) new_id, (hashtab_datum_t) new_level)) { goto out_of_mem; } return 0; out_of_mem: ERR(state->handle, "Out of memory!"); if (new_level != NULL && new_level->level != NULL) { mls_level_destroy(new_level->level); free(new_level->level); } level_datum_destroy(new_level); free(new_level); free(new_id); return -1; } static int cats_copy_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) { expand_state_t *state = (expand_state_t *) data; cat_datum_t *cat = (cat_datum_t *) datum, *new_cat = NULL; char *id = (char *)key, *new_id = NULL; if (!is_id_enabled(id, state->base, SYM_CATS)) { /* identifier's scope is not enabled */ return 0; } if (state->verbose) INFO(state->handle, "copying category attribute %s", id); new_cat = (cat_datum_t *) malloc(sizeof(cat_datum_t)); if (!new_cat) goto out_of_mem; cat_datum_init(new_cat); new_id = strdup(id); if (!new_id) goto out_of_mem; new_cat->s.value = cat->s.value; new_cat->isalias = cat->isalias; state->out->p_cats.nprim++; if (hashtab_insert(state->out->p_cats.table, (hashtab_key_t) new_id, (hashtab_datum_t) new_cat)) { goto out_of_mem; } return 0; out_of_mem: ERR(state->handle, "Out of memory!"); cat_datum_destroy(new_cat); free(new_cat); free(new_id); return -1; } static int copy_role_allows(expand_state_t * state, role_allow_rule_t * rules) { unsigned int i, j; role_allow_t *cur_allow, *n, *l; role_allow_rule_t *cur; ebitmap_t roles, new_roles; ebitmap_node_t *snode, *tnode; /* start at the end of the list */ for (l = state->out->role_allow; l && l->next; l = l->next) ; cur = rules; while (cur) { ebitmap_init(&roles); ebitmap_init(&new_roles); if (role_set_expand(&cur->roles, &roles, state->out, state->base, state->rolemap)) { ERR(state->handle, "Out of memory!"); return -1; } if (role_set_expand(&cur->new_roles, &new_roles, state->out, state->base, state->rolemap)) { ERR(state->handle, "Out of memory!"); return -1; } ebitmap_for_each_positive_bit(&roles, snode, i) { ebitmap_for_each_positive_bit(&new_roles, tnode, j) { /* check for duplicates */ cur_allow = state->out->role_allow; while (cur_allow) { if ((cur_allow->role == i + 1) && (cur_allow->new_role == j + 1)) break; cur_allow = cur_allow->next; } if (cur_allow) continue; n = (role_allow_t *) malloc(sizeof(role_allow_t)); if (!n) { ERR(state->handle, "Out of memory!"); return -1; } memset(n, 0, sizeof(role_allow_t)); n->role = i + 1; n->new_role = j + 1; if (l) { l->next = n; } else { state->out->role_allow = n; } l = n; } } ebitmap_destroy(&roles); ebitmap_destroy(&new_roles); cur = cur->next; } return 0; } static int copy_role_trans(expand_state_t * state, role_trans_rule_t * rules) { unsigned int i, j, k; role_trans_t *n, *l, *cur_trans; role_trans_rule_t *cur; ebitmap_t roles, types; ebitmap_node_t *rnode, *tnode, *cnode; /* start at the end of the list */ for (l = state->out->role_tr; l && l->next; l = l->next) ; cur = rules; while (cur) { ebitmap_init(&roles); ebitmap_init(&types); if (role_set_expand(&cur->roles, &roles, state->out, state->base, state->rolemap)) { ERR(state->handle, "Out of memory!"); return -1; } if (expand_convert_type_set (state->out, state->typemap, &cur->types, &types, 1)) { ERR(state->handle, "Out of memory!"); return -1; } ebitmap_for_each_positive_bit(&roles, rnode, i) { ebitmap_for_each_positive_bit(&types, tnode, j) { ebitmap_for_each_positive_bit(&cur->classes, cnode, k) { cur_trans = state->out->role_tr; while (cur_trans) { unsigned int mapped_role; mapped_role = state->rolemap[cur->new_role - 1]; if ((cur_trans->role == i + 1) && (cur_trans->type == j + 1) && (cur_trans->tclass == k + 1)) { if (cur_trans->new_role == mapped_role) { break; } else { ERR(state->handle, "Conflicting role trans rule %s %s : %s { %s vs %s }", state->out->p_role_val_to_name[i], state->out->p_type_val_to_name[j], state->out->p_class_val_to_name[k], state->out->p_role_val_to_name[mapped_role - 1], state->out->p_role_val_to_name[cur_trans->new_role - 1]); return -1; } } cur_trans = cur_trans->next; } if (cur_trans) continue; n = (role_trans_t *) malloc(sizeof(role_trans_t)); if (!n) { ERR(state->handle, "Out of memory!"); return -1; } memset(n, 0, sizeof(role_trans_t)); n->role = i + 1; n->type = j + 1; n->tclass = k + 1; n->new_role = state->rolemap [cur->new_role - 1]; if (l) l->next = n; else state->out->role_tr = n; l = n; } } } ebitmap_destroy(&roles); ebitmap_destroy(&types); cur = cur->next; } return 0; } static int expand_filename_trans_helper(expand_state_t *state, filename_trans_rule_t *rule, unsigned int s, unsigned int t) { uint32_t mapped_otype, present_otype; int rc; mapped_otype = state->typemap[rule->otype - 1]; rc = policydb_filetrans_insert( state->out, s + 1, t + 1, rule->tclass, rule->name, NULL, mapped_otype, &present_otype ); if (rc == SEPOL_EEXIST) { /* duplicate rule, ignore */ if (present_otype == mapped_otype) return 0; ERR(state->handle, "Conflicting name-based type_transition %s %s:%s \"%s\": %s vs %s", state->out->p_type_val_to_name[s], state->out->p_type_val_to_name[t], state->out->p_class_val_to_name[rule->tclass - 1], rule->name, state->out->p_type_val_to_name[present_otype - 1], state->out->p_type_val_to_name[mapped_otype - 1]); return -1; } else if (rc < 0) { ERR(state->handle, "Out of memory!"); return -1; } return 0; } static int expand_filename_trans(expand_state_t *state, filename_trans_rule_t *rules) { unsigned int i, j; filename_trans_rule_t *cur_rule; ebitmap_t stypes, ttypes; ebitmap_node_t *snode, *tnode; int rc; cur_rule = rules; while (cur_rule) { ebitmap_init(&stypes); ebitmap_init(&ttypes); if (expand_convert_type_set(state->out, state->typemap, &cur_rule->stypes, &stypes, 1)) { ERR(state->handle, "Out of memory!"); return -1; } if (expand_convert_type_set(state->out, state->typemap, &cur_rule->ttypes, &ttypes, 1)) { ERR(state->handle, "Out of memory!"); return -1; } ebitmap_for_each_positive_bit(&stypes, snode, i) { ebitmap_for_each_positive_bit(&ttypes, tnode, j) { rc = expand_filename_trans_helper( state, cur_rule, i, j ); if (rc) return rc; } if (cur_rule->flags & RULE_SELF) { rc = expand_filename_trans_helper( state, cur_rule, i, i ); if (rc) return rc; } } ebitmap_destroy(&stypes); ebitmap_destroy(&ttypes); cur_rule = cur_rule->next; } return 0; } static int exp_rangetr_helper(uint32_t stype, uint32_t ttype, uint32_t tclass, mls_semantic_range_t * trange, expand_state_t * state) { range_trans_t *rt = NULL, key; mls_range_t *r, *exp_range = NULL; int rc = -1; exp_range = calloc(1, sizeof(*exp_range)); if (!exp_range) { ERR(state->handle, "Out of memory!"); return -1; } if (mls_semantic_range_expand(trange, exp_range, state->out, state->handle)) goto err; /* check for duplicates/conflicts */ key.source_type = stype; key.target_type = ttype; key.target_class = tclass; r = hashtab_search(state->out->range_tr, (hashtab_key_t) &key); if (r) { if (mls_range_eq(r, exp_range)) { /* duplicate, ignore */ mls_range_destroy(exp_range); free(exp_range); return 0; } /* conflict */ ERR(state->handle, "Conflicting range trans rule %s %s : %s", state->out->p_type_val_to_name[stype - 1], state->out->p_type_val_to_name[ttype - 1], state->out->p_class_val_to_name[tclass - 1]); goto err; } rt = calloc(1, sizeof(*rt)); if (!rt) { ERR(state->handle, "Out of memory!"); goto err; } rt->source_type = stype; rt->target_type = ttype; rt->target_class = tclass; rc = hashtab_insert(state->out->range_tr, (hashtab_key_t) rt, exp_range); if (rc) { ERR(state->handle, "Out of memory!"); goto err; } return 0; err: free(rt); if (exp_range) { mls_range_destroy(exp_range); free(exp_range); } return -1; } static int expand_range_trans(expand_state_t * state, range_trans_rule_t * rules) { unsigned int i, j, k; range_trans_rule_t *rule; ebitmap_t stypes, ttypes; ebitmap_node_t *snode, *tnode, *cnode; if (state->verbose) INFO(state->handle, "expanding range transitions"); for (rule = rules; rule; rule = rule->next) { ebitmap_init(&stypes); ebitmap_init(&ttypes); /* expand the type sets */ if (expand_convert_type_set(state->out, state->typemap, &rule->stypes, &stypes, 1)) { ERR(state->handle, "Out of memory!"); return -1; } if (expand_convert_type_set(state->out, state->typemap, &rule->ttypes, &ttypes, 1)) { ebitmap_destroy(&stypes); ERR(state->handle, "Out of memory!"); return -1; } /* loop on source type */ ebitmap_for_each_positive_bit(&stypes, snode, i) { /* loop on target type */ ebitmap_for_each_positive_bit(&ttypes, tnode, j) { /* loop on target class */ ebitmap_for_each_positive_bit(&rule->tclasses, cnode, k) { if (exp_rangetr_helper(i + 1, j + 1, k + 1, &rule->trange, state)) { ebitmap_destroy(&stypes); ebitmap_destroy(&ttypes); return -1; } } } } ebitmap_destroy(&stypes); ebitmap_destroy(&ttypes); } return 0; } /* Search for an AV tab node within a hash table with the given key. * If the node does not exist, create it and return it; otherwise * return the pre-existing one. */ static avtab_ptr_t find_avtab_node(sepol_handle_t * handle, avtab_t * avtab, avtab_key_t * key, cond_av_list_t ** cond, av_extended_perms_t *xperms) { avtab_ptr_t node; avtab_datum_t avdatum; cond_av_list_t *nl; int match = 0; /* AVTAB_XPERMS entries are not necessarily unique */ if (key->specified & AVTAB_XPERMS) { if (xperms == NULL) { ERR(handle, "searching xperms NULL"); node = NULL; } else { node = avtab_search_node(avtab, key); while (node) { if ((node->datum.xperms->specified == xperms->specified) && (node->datum.xperms->driver == xperms->driver)) { match = 1; break; } node = avtab_search_node_next(node, key->specified); } if (!match) node = NULL; } } else { node = avtab_search_node(avtab, key); } /* If this is for conditional policies, keep searching in case the node is part of my conditional avtab. */ if (cond) { while (node) { if (node->parse_context == cond) break; node = avtab_search_node_next(node, key->specified); } } if (!node) { memset(&avdatum, 0, sizeof avdatum); /* * AUDITDENY, aka DONTAUDIT, are &= assigned, versus |= for * others. Initialize the data accordingly. */ avdatum.data = key->specified == AVTAB_AUDITDENY ? ~UINT32_C(0) : UINT32_C(0); /* this is used to get the node - insertion is actually unique */ node = avtab_insert_nonunique(avtab, key, &avdatum); if (!node) { ERR(handle, "hash table overflow"); return NULL; } if (cond) { node->parse_context = cond; nl = (cond_av_list_t *) malloc(sizeof(cond_av_list_t)); if (!nl) { ERR(handle, "Memory error"); return NULL; } memset(nl, 0, sizeof(cond_av_list_t)); nl->node = node; nl->next = *cond; *cond = nl; } } return node; } static uint32_t avrule_to_avtab_spec(uint32_t specification) { return (specification == AVRULE_DONTAUDIT) ? AVTAB_AUDITDENY : specification; } #define EXPAND_RULE_SUCCESS 1 #define EXPAND_RULE_CONFLICT 0 #define EXPAND_RULE_ERROR -1 static int expand_terule_helper(sepol_handle_t * handle, policydb_t * p, uint32_t * typemap, uint32_t specified, cond_av_list_t ** cond, cond_av_list_t ** other, uint32_t stype, uint32_t ttype, class_perm_node_t * perms, avtab_t * avtab, int enabled) { avtab_key_t avkey; avtab_datum_t *avdatump; avtab_ptr_t node; class_perm_node_t *cur; int conflict; uint32_t oldtype = 0; if (!(specified & (AVRULE_TRANSITION|AVRULE_MEMBER|AVRULE_CHANGE))) { ERR(handle, "Invalid specification: %"PRIu32, specified); return EXPAND_RULE_ERROR; } avkey.specified = avrule_to_avtab_spec(specified); avkey.source_type = stype + 1; avkey.target_type = ttype + 1; cur = perms; while (cur) { uint32_t remapped_data = typemap ? typemap[cur->data - 1] : cur->data; avkey.target_class = cur->tclass; conflict = 0; /* check to see if the expanded TE already exists -- * either in the global scope or in another * conditional AV tab */ node = avtab_search_node(&p->te_avtab, &avkey); if (node) { conflict = 1; } else { node = avtab_search_node(&p->te_cond_avtab, &avkey); if (node && node->parse_context != other) { conflict = 2; } } if (conflict) { avdatump = &node->datum; if (specified & AVRULE_TRANSITION) { oldtype = avdatump->data; } else if (specified & AVRULE_MEMBER) { oldtype = avdatump->data; } else if (specified & AVRULE_CHANGE) { oldtype = avdatump->data; } if (oldtype == remapped_data) { /* if the duplicate is inside the same scope (eg., unconditional * or in same conditional then ignore it */ if ((conflict == 1 && cond == NULL) || node->parse_context == cond) return EXPAND_RULE_SUCCESS; ERR(handle, "duplicate TE rule for %s %s:%s %s", p->p_type_val_to_name[avkey.source_type - 1], p->p_type_val_to_name[avkey.target_type - 1], p->p_class_val_to_name[avkey.target_class - 1], p->p_type_val_to_name[oldtype - 1]); return EXPAND_RULE_CONFLICT; } ERR(handle, "conflicting TE rule for (%s, %s:%s): old was %s, new is %s", p->p_type_val_to_name[avkey.source_type - 1], p->p_type_val_to_name[avkey.target_type - 1], p->p_class_val_to_name[avkey.target_class - 1], p->p_type_val_to_name[oldtype - 1], p->p_type_val_to_name[remapped_data - 1]); return EXPAND_RULE_CONFLICT; } node = find_avtab_node(handle, avtab, &avkey, cond, NULL); if (!node) return -1; if (enabled) { node->key.specified |= AVTAB_ENABLED; } else { node->key.specified &= ~AVTAB_ENABLED; } avdatump = &node->datum; avdatump->data = remapped_data; cur = cur->next; } return EXPAND_RULE_SUCCESS; } /* 0 for success -1 indicates failure */ static int allocate_xperms(sepol_handle_t * handle, avtab_datum_t * avdatump, av_extended_perms_t * extended_perms) { unsigned int i; avtab_extended_perms_t *xperms = avdatump->xperms; if (!xperms) { xperms = (avtab_extended_perms_t *) calloc(1, sizeof(avtab_extended_perms_t)); if (!xperms) { ERR(handle, "Out of memory!"); return -1; } avdatump->xperms = xperms; } switch (extended_perms->specified) { case AVRULE_XPERMS_IOCTLFUNCTION: xperms->specified = AVTAB_XPERMS_IOCTLFUNCTION; break; case AVRULE_XPERMS_IOCTLDRIVER: xperms->specified = AVTAB_XPERMS_IOCTLDRIVER; break; case AVRULE_XPERMS_NLMSG: xperms->specified = AVTAB_XPERMS_NLMSG; break; default: return -1; } xperms->driver = extended_perms->driver; for (i = 0; i < ARRAY_SIZE(xperms->perms); i++) xperms->perms[i] |= extended_perms->perms[i]; return 0; } static int expand_avrule_helper(sepol_handle_t * handle, uint32_t specified, cond_av_list_t ** cond, uint32_t stype, uint32_t ttype, class_perm_node_t * perms, avtab_t * avtab, int enabled, av_extended_perms_t *extended_perms) { avtab_key_t avkey; avtab_datum_t *avdatump; avtab_ptr_t node; class_perm_node_t *cur; /* bail early if dontaudit's are disabled and it's a dontaudit rule */ if ((specified & (AVRULE_DONTAUDIT|AVRULE_XPERMS_DONTAUDIT)) && handle && handle->disable_dontaudit) return EXPAND_RULE_SUCCESS; avkey.source_type = stype + 1; avkey.target_type = ttype + 1; avkey.specified = avrule_to_avtab_spec(specified); cur = perms; while (cur) { avkey.target_class = cur->tclass; node = find_avtab_node(handle, avtab, &avkey, cond, extended_perms); if (!node) return EXPAND_RULE_ERROR; if (enabled) { node->key.specified |= AVTAB_ENABLED; } else { node->key.specified &= ~AVTAB_ENABLED; } avdatump = &node->datum; switch (specified) { case AVRULE_ALLOWED: case AVRULE_AUDITALLOW: case AVRULE_NEVERALLOW: avdatump->data |= cur->data; break; case AVRULE_DONTAUDIT: avdatump->data &= ~cur->data; break; case AVRULE_AUDITDENY: /* Since a '0' in an auditdeny mask represents * a permission we do NOT want to audit * (dontaudit), we use the '&' operand to * ensure that all '0's in the mask are * retained (much unlike the allow and * auditallow cases). */ avdatump->data &= cur->data; break; case AVRULE_XPERMS_ALLOWED: case AVRULE_XPERMS_AUDITALLOW: case AVRULE_XPERMS_DONTAUDIT: case AVRULE_XPERMS_NEVERALLOW: if (allocate_xperms(handle, avdatump, extended_perms)) return EXPAND_RULE_ERROR; break; default: ERR(handle, "Unknown specification: %"PRIu32, specified); return EXPAND_RULE_ERROR; } cur = cur->next; } return EXPAND_RULE_SUCCESS; } static int expand_rule_helper(sepol_handle_t * handle, policydb_t * p, uint32_t * typemap, avrule_t * source_rule, avtab_t * dest_avtab, cond_av_list_t ** cond, cond_av_list_t ** other, int enabled, ebitmap_t * stypes, ebitmap_t * ttypes) { unsigned int i, j; int retval; ebitmap_node_t *snode, *tnode; ebitmap_for_each_positive_bit(stypes, snode, i) { if (source_rule->flags & RULE_SELF) { if (source_rule->specified & (AVRULE_AV | AVRULE_XPERMS)) { retval = expand_avrule_helper(handle, source_rule->specified, cond, i, i, source_rule->perms, dest_avtab, enabled, source_rule->xperms); if (retval != EXPAND_RULE_SUCCESS) return retval; } else { retval = expand_terule_helper(handle, p, typemap, source_rule->specified, cond, other, i, i, source_rule->perms, dest_avtab, enabled); if (retval != EXPAND_RULE_SUCCESS) return retval; } } ebitmap_for_each_positive_bit(ttypes, tnode, j) { if (source_rule->specified & (AVRULE_AV | AVRULE_XPERMS)) { retval = expand_avrule_helper(handle, source_rule->specified, cond, i, j, source_rule->perms, dest_avtab, enabled, source_rule->xperms); if (retval != EXPAND_RULE_SUCCESS) return retval; } else { retval = expand_terule_helper(handle, p, typemap, source_rule->specified, cond, other, i, j, source_rule->perms, dest_avtab, enabled); if (retval != EXPAND_RULE_SUCCESS) return retval; } } } return EXPAND_RULE_SUCCESS; } /* * Expand a rule into a given avtab - checking for conflicting type * rules in the destination policy. Return EXPAND_RULE_SUCCESS on * success, EXPAND_RULE_CONFLICT if the rule conflicts with something * (and hence was not added), or EXPAND_RULE_ERROR on error. */ static int convert_and_expand_rule(sepol_handle_t * handle, policydb_t * dest_pol, uint32_t * typemap, avrule_t * source_rule, avtab_t * dest_avtab, cond_av_list_t ** cond, cond_av_list_t ** other, int enabled, int do_neverallow) { int retval; ebitmap_t stypes, ttypes; unsigned char alwaysexpand; if (!do_neverallow && source_rule->specified & AVRULE_NEVERALLOW) return EXPAND_RULE_SUCCESS; if (!do_neverallow && source_rule->specified & AVRULE_XPERMS_NEVERALLOW) return EXPAND_RULE_SUCCESS; ebitmap_init(&stypes); ebitmap_init(&ttypes); /* Force expansion for type rules and for self rules. */ alwaysexpand = ((source_rule->specified & AVRULE_TYPE) || (source_rule->flags & RULE_SELF)); if (expand_convert_type_set (dest_pol, typemap, &source_rule->stypes, &stypes, alwaysexpand)) return EXPAND_RULE_ERROR; if (expand_convert_type_set (dest_pol, typemap, &source_rule->ttypes, &ttypes, alwaysexpand)) return EXPAND_RULE_ERROR; retval = expand_rule_helper(handle, dest_pol, typemap, source_rule, dest_avtab, cond, other, enabled, &stypes, &ttypes); ebitmap_destroy(&stypes); ebitmap_destroy(&ttypes); return retval; } static int cond_avrule_list_copy(policydb_t * dest_pol, avrule_t * source_rules, avtab_t * dest_avtab, cond_av_list_t ** list, cond_av_list_t ** other, uint32_t * typemap, int enabled, expand_state_t * state) { avrule_t *cur; cur = source_rules; while (cur) { if (convert_and_expand_rule(state->handle, dest_pol, typemap, cur, dest_avtab, list, other, enabled, 0) != EXPAND_RULE_SUCCESS) { return -1; } cur = cur->next; } return 0; } static int cond_node_map_bools(expand_state_t * state, cond_node_t * cn) { cond_expr_t *cur; unsigned int i; cur = cn->expr; while (cur) { if (cur->boolean) cur->boolean = state->boolmap[cur->boolean - 1]; cur = cur->next; } for (i = 0; i < min(cn->nbools, COND_MAX_BOOLS); i++) cn->bool_ids[i] = state->boolmap[cn->bool_ids[i] - 1]; if (cond_normalize_expr(state->out, cn)) { ERR(state->handle, "Error while normalizing conditional"); return -1; } return 0; } /* copy the nodes in *reverse* order -- the result is that the last * given conditional appears first in the policy, so as to match the * behavior of the upstream compiler */ static int cond_node_copy(expand_state_t * state, cond_node_t * cn) { cond_node_t *new_cond, *tmp; if (cn == NULL) { return 0; } if (cond_node_copy(state, cn->next)) { return -1; } /* If current cond_node_t is of tunable, its effective branch * has been appended to its home decl->avrules list during link * and now we should just skip it. */ if (cn->flags & COND_NODE_FLAGS_TUNABLE) return 0; if (cond_normalize_expr(state->base, cn)) { ERR(state->handle, "Error while normalizing conditional"); return -1; } /* create a new temporary conditional node with the booleans * mapped */ tmp = cond_node_create(state->base, cn); if (!tmp) { ERR(state->handle, "Out of memory"); return -1; } if (cond_node_map_bools(state, tmp)) { cond_node_destroy(tmp); free(tmp); ERR(state->handle, "Error mapping booleans"); return -1; } new_cond = cond_node_search(state->out, state->out->cond_list, tmp); if (!new_cond) { cond_node_destroy(tmp); free(tmp); ERR(state->handle, "Out of memory!"); return -1; } cond_node_destroy(tmp); free(tmp); if (cond_avrule_list_copy (state->out, cn->avtrue_list, &state->out->te_cond_avtab, &new_cond->true_list, &new_cond->false_list, state->typemap, new_cond->cur_state, state)) return -1; if (cond_avrule_list_copy (state->out, cn->avfalse_list, &state->out->te_cond_avtab, &new_cond->false_list, &new_cond->true_list, state->typemap, !new_cond->cur_state, state)) return -1; return 0; } static int context_copy(context_struct_t * dst, context_struct_t * src, expand_state_t * state) { dst->user = state->usermap[src->user - 1]; dst->role = state->rolemap[src->role - 1]; dst->type = state->typemap[src->type - 1]; return mls_context_cpy(dst, src); } static int ocontext_copy_xen(expand_state_t *state) { unsigned int i; ocontext_t *c, *n, *l; for (i = 0; i < OCON_NUM; i++) { l = NULL; for (c = state->base->ocontexts[i]; c; c = c->next) { if (i == OCON_XEN_ISID && !c->context[0].user) { INFO(state->handle, "No context assigned to SID %s, omitting from policy", c->u.name); continue; } n = malloc(sizeof(ocontext_t)); if (!n) { ERR(state->handle, "Out of memory!"); return -1; } memset(n, 0, sizeof(ocontext_t)); if (l) l->next = n; else state->out->ocontexts[i] = n; l = n; switch (i) { case OCON_XEN_ISID: n->sid[0] = c->sid[0]; break; case OCON_XEN_PIRQ: n->u.pirq = c->u.pirq; break; case OCON_XEN_IOPORT: n->u.ioport.low_ioport = c->u.ioport.low_ioport; n->u.ioport.high_ioport = c->u.ioport.high_ioport; break; case OCON_XEN_IOMEM: n->u.iomem.low_iomem = c->u.iomem.low_iomem; n->u.iomem.high_iomem = c->u.iomem.high_iomem; break; case OCON_XEN_PCIDEVICE: n->u.device = c->u.device; break; case OCON_XEN_DEVICETREE: n->u.name = strdup(c->u.name); if (!n->u.name) { ERR(state->handle, "Out of memory!"); return -1; } break; default: /* shouldn't get here */ ERR(state->handle, "Unknown ocontext"); return -1; } if (context_copy(&n->context[0], &c->context[0], state)) { ERR(state->handle, "Out of memory!"); return -1; } } } return 0; } static int ocontext_copy_selinux(expand_state_t *state) { unsigned int i, j; ocontext_t *c, *n, *l; for (i = 0; i < OCON_NUM; i++) { l = NULL; for (c = state->base->ocontexts[i]; c; c = c->next) { if (i == OCON_ISID && !c->context[0].user) { INFO(state->handle, "No context assigned to SID %s, omitting from policy", c->u.name); continue; } n = malloc(sizeof(ocontext_t)); if (!n) { ERR(state->handle, "Out of memory!"); return -1; } memset(n, 0, sizeof(ocontext_t)); if (l) l->next = n; else state->out->ocontexts[i] = n; l = n; switch (i) { case OCON_ISID: n->sid[0] = c->sid[0]; break; case OCON_FS: /* FALLTHROUGH */ case OCON_NETIF: n->u.name = strdup(c->u.name); if (!n->u.name) { ERR(state->handle, "Out of memory!"); return -1; } if (context_copy (&n->context[1], &c->context[1], state)) { ERR(state->handle, "Out of memory!"); return -1; } break; case OCON_IBPKEY: n->u.ibpkey.subnet_prefix = c->u.ibpkey.subnet_prefix; n->u.ibpkey.low_pkey = c->u.ibpkey.low_pkey; n->u.ibpkey.high_pkey = c->u.ibpkey.high_pkey; break; case OCON_IBENDPORT: n->u.ibendport.dev_name = strdup(c->u.ibendport.dev_name); if (!n->u.ibendport.dev_name) { ERR(state->handle, "Out of memory!"); return -1; } n->u.ibendport.port = c->u.ibendport.port; break; case OCON_PORT: n->u.port.protocol = c->u.port.protocol; n->u.port.low_port = c->u.port.low_port; n->u.port.high_port = c->u.port.high_port; break; case OCON_NODE: n->u.node.addr = c->u.node.addr; n->u.node.mask = c->u.node.mask; break; case OCON_FSUSE: n->v.behavior = c->v.behavior; n->u.name = strdup(c->u.name); if (!n->u.name) { ERR(state->handle, "Out of memory!"); return -1; } break; case OCON_NODE6: for (j = 0; j < 4; j++) n->u.node6.addr[j] = c->u.node6.addr[j]; for (j = 0; j < 4; j++) n->u.node6.mask[j] = c->u.node6.mask[j]; break; default: /* shouldn't get here */ ERR(state->handle, "Unknown ocontext"); return -1; } if (context_copy(&n->context[0], &c->context[0], state)) { ERR(state->handle, "Out of memory!"); return -1; } } } return 0; } static int ocontext_copy(expand_state_t *state, uint32_t target) { int rc = -1; switch (target) { case SEPOL_TARGET_SELINUX: rc = ocontext_copy_selinux(state); break; case SEPOL_TARGET_XEN: rc = ocontext_copy_xen(state); break; default: ERR(state->handle, "Unknown target"); return -1; } return rc; } static int genfs_copy(expand_state_t * state) { ocontext_t *c, *newc, *l; genfs_t *genfs, *newgenfs, *end; end = NULL; for (genfs = state->base->genfs; genfs; genfs = genfs->next) { newgenfs = malloc(sizeof(genfs_t)); if (!newgenfs) { ERR(state->handle, "Out of memory!"); return -1; } memset(newgenfs, 0, sizeof(genfs_t)); newgenfs->fstype = strdup(genfs->fstype); if (!newgenfs->fstype) { free(newgenfs); ERR(state->handle, "Out of memory!"); return -1; } if (!end) state->out->genfs = newgenfs; else end->next = newgenfs; end = newgenfs; l = NULL; for (c = genfs->head; c; c = c->next) { newc = malloc(sizeof(ocontext_t)); if (!newc) { ERR(state->handle, "Out of memory!"); return -1; } memset(newc, 0, sizeof(ocontext_t)); newc->u.name = strdup(c->u.name); if (!newc->u.name) { ERR(state->handle, "Out of memory!"); free(newc); return -1; } newc->v.sclass = c->v.sclass; context_copy(&newc->context[0], &c->context[0], state); if (l) l->next = newc; else newgenfs->head = newc; l = newc; } } return 0; } static int type_attr_map(hashtab_key_t key __attribute__ ((unused)), hashtab_datum_t datum, void *ptr) { type_datum_t *type; expand_state_t *state = ptr; policydb_t *p = state->out; unsigned int i; ebitmap_node_t *tnode; uint32_t value; type = (type_datum_t *) datum; value = type->s.value; if (type->flavor == TYPE_ATTRIB) { if (!(type->flags & TYPE_FLAGS_EXPAND_ATTR_TRUE)) { if (ebitmap_cpy(&p->attr_type_map[value - 1], &type->types)) { goto oom; } ebitmap_for_each_positive_bit(&type->types, tnode, i) { if (ebitmap_set_bit(&p->type_attr_map[i], value - 1, 1)) { goto oom; } } } else { /* Attribute is being expanded, so remove */ if (ebitmap_set_bit(&p->type_attr_map[value - 1], value - 1, 0)) { goto oom; } } } else { if (ebitmap_set_bit(&p->attr_type_map[value - 1], value - 1, 1)) { goto oom; } } return 0; oom: ERR(state->handle, "Out of memory!"); return -1; } /* converts typeset using typemap and expands into ebitmap_t types using the attributes in the passed in policy. * this should not be called until after all the blocks have been processed and the attributes in target policy * are complete. */ int expand_convert_type_set(policydb_t * p, uint32_t * typemap, type_set_t * set, ebitmap_t * types, unsigned char alwaysexpand) { type_set_t tmpset; type_set_init(&tmpset); if (map_ebitmap(&set->types, &tmpset.types, typemap)) return -1; if (map_ebitmap(&set->negset, &tmpset.negset, typemap)) return -1; tmpset.flags = set->flags; if (type_set_expand(&tmpset, types, p, alwaysexpand)) return -1; type_set_destroy(&tmpset); return 0; } /* Expand a rule into a given avtab - checking for conflicting type * rules. Return 1 on success, 0 if the rule conflicts with something * (and hence was not added), or -1 on error. */ int expand_rule(sepol_handle_t * handle, policydb_t * source_pol, avrule_t * source_rule, avtab_t * dest_avtab, cond_av_list_t ** cond, cond_av_list_t ** other, int enabled) { int retval; ebitmap_t stypes, ttypes; if ((source_rule->specified & AVRULE_NEVERALLOW) || (source_rule->specified & AVRULE_XPERMS_NEVERALLOW)) return 1; ebitmap_init(&stypes); ebitmap_init(&ttypes); if (type_set_expand(&source_rule->stypes, &stypes, source_pol, 1)) return -1; if (type_set_expand(&source_rule->ttypes, &ttypes, source_pol, 1)) return -1; retval = expand_rule_helper(handle, source_pol, NULL, source_rule, dest_avtab, cond, other, enabled, &stypes, &ttypes); ebitmap_destroy(&stypes); ebitmap_destroy(&ttypes); return retval; } /* Expand a role set into an ebitmap containing the roles. * This handles the attribute and flags. * Attribute expansion depends on if the rolemap is available. * During module compile the rolemap is not available, the * possible duplicates of a regular role and the role attribute * the regular role belongs to could be properly handled by * copy_role_trans and copy_role_allow. */ int role_set_expand(role_set_t * x, ebitmap_t * r, policydb_t * out, policydb_t * base, uint32_t * rolemap) { unsigned int i; ebitmap_node_t *rnode; ebitmap_t mapped_roles, roles; policydb_t *p = out; role_datum_t *role; ebitmap_init(r); if (x->flags & ROLE_STAR) { for (i = 0; i < p->p_roles.nprim; i++) if (ebitmap_set_bit(r, i, 1)) return -1; return 0; } ebitmap_init(&mapped_roles); ebitmap_init(&roles); if (rolemap) { assert(base != NULL); ebitmap_for_each_positive_bit(&x->roles, rnode, i) { /* take advantage of p_role_val_to_struct[] * of the base module */ role = base->role_val_to_struct[i]; assert(role != NULL); if (role->flavor == ROLE_ATTRIB) { if (ebitmap_union(&roles, &role->roles)) goto bad; } else { if (ebitmap_set_bit(&roles, i, 1)) goto bad; } } if (map_ebitmap(&roles, &mapped_roles, rolemap)) goto bad; } else { if (ebitmap_cpy(&mapped_roles, &x->roles)) goto bad; } ebitmap_for_each_positive_bit(&mapped_roles, rnode, i) { if (ebitmap_set_bit(r, i, 1)) goto bad; } ebitmap_destroy(&mapped_roles); ebitmap_destroy(&roles); /* if role is to be complimented, invert the entire bitmap here */ if (x->flags & ROLE_COMP) { for (i = 0; i < p->p_roles.nprim; i++) { if (ebitmap_get_bit(r, i)) { if (ebitmap_set_bit(r, i, 0)) return -1; } else { if (ebitmap_set_bit(r, i, 1)) return -1; } } } return 0; bad: ebitmap_destroy(&mapped_roles); ebitmap_destroy(&roles); return -1; } /* Expand a type set into an ebitmap containing the types. This * handles the negset, attributes, and flags. * Attribute expansion depends on several factors: * - if alwaysexpand is 1, then they will be expanded, * - if the type set has a negset or flags, then they will be expanded, * - otherwise, they will not be expanded. */ int type_set_expand(type_set_t * set, ebitmap_t * t, policydb_t * p, unsigned char alwaysexpand) { unsigned int i; ebitmap_t types, neg_types; ebitmap_node_t *tnode; unsigned char expand = alwaysexpand || !ebitmap_is_empty(&set->negset) || set->flags; type_datum_t *type; int rc =-1; ebitmap_init(&types); ebitmap_init(t); /* First go through the types and OR all the attributes to types */ ebitmap_for_each_positive_bit(&set->types, tnode, i) { /* * invalid policies might have more types set in the ebitmap than * what's available in the type_val_to_struct mapping */ if (i >= p->p_types.nprim) goto err_types; type = p->type_val_to_struct[i]; if (!type) { goto err_types; } if (type->flavor == TYPE_ATTRIB && (expand || (type->flags & TYPE_FLAGS_EXPAND_ATTR_TRUE))) { if (ebitmap_union(&types, &type->types)) { goto err_types; } } else { if (ebitmap_set_bit(&types, i, 1)) { goto err_types; } } } /* Now do the same thing for negset */ ebitmap_init(&neg_types); ebitmap_for_each_positive_bit(&set->negset, tnode, i) { if (p->type_val_to_struct[i] && p->type_val_to_struct[i]->flavor == TYPE_ATTRIB) { if (ebitmap_union (&neg_types, &p->type_val_to_struct[i]->types)) { goto err_neg; } } else { if (ebitmap_set_bit(&neg_types, i, 1)) { goto err_neg; } } } if (set->flags & TYPE_STAR) { /* set all types not in neg_types */ for (i = 0; i < p->p_types.nprim; i++) { if (ebitmap_get_bit(&neg_types, i)) continue; if (p->type_val_to_struct[i] && p->type_val_to_struct[i]->flavor == TYPE_ATTRIB) continue; if (ebitmap_set_bit(t, i, 1)) goto err_neg; } goto out; } ebitmap_for_each_positive_bit(&types, tnode, i) { if (!ebitmap_get_bit(&neg_types, i)) if (ebitmap_set_bit(t, i, 1)) goto err_neg; } if (set->flags & TYPE_COMP) { for (i = 0; i < p->p_types.nprim; i++) { if (p->type_val_to_struct[i] && p->type_val_to_struct[i]->flavor == TYPE_ATTRIB) { assert(!ebitmap_get_bit(t, i)); continue; } if (ebitmap_get_bit(t, i)) { if (ebitmap_set_bit(t, i, 0)) goto err_neg; } else { if (ebitmap_set_bit(t, i, 1)) goto err_neg; } } } out: rc = 0; err_neg: ebitmap_destroy(&neg_types); err_types: ebitmap_destroy(&types); return rc; } static int copy_neverallow(policydb_t * dest_pol, uint32_t * typemap, avrule_t * source_rule) { ebitmap_t stypes, ttypes; avrule_t *avrule; class_perm_node_t *cur_perm, *new_perm, *tail_perm; av_extended_perms_t *xperms = NULL; ebitmap_init(&stypes); ebitmap_init(&ttypes); if (expand_convert_type_set (dest_pol, typemap, &source_rule->stypes, &stypes, 1)) return -1; if (expand_convert_type_set (dest_pol, typemap, &source_rule->ttypes, &ttypes, 1)) return -1; avrule = (avrule_t *) malloc(sizeof(avrule_t)); if (!avrule) return -1; avrule_init(avrule); avrule->specified = source_rule->specified; avrule->line = source_rule->line; avrule->flags = source_rule->flags; avrule->source_line = source_rule->source_line; if (source_rule->source_filename) { avrule->source_filename = strdup(source_rule->source_filename); if (!avrule->source_filename) goto err; } if (ebitmap_cpy(&avrule->stypes.types, &stypes)) goto err; if (ebitmap_cpy(&avrule->ttypes.types, &ttypes)) goto err; cur_perm = source_rule->perms; tail_perm = NULL; while (cur_perm) { new_perm = (class_perm_node_t *) malloc(sizeof(class_perm_node_t)); if (!new_perm) goto err; class_perm_node_init(new_perm); new_perm->tclass = cur_perm->tclass; assert(new_perm->tclass); /* once we have modules with permissions we'll need to map the permissions (and classes) */ new_perm->data = cur_perm->data; if (!avrule->perms) avrule->perms = new_perm; if (tail_perm) tail_perm->next = new_perm; tail_perm = new_perm; cur_perm = cur_perm->next; } /* copy over extended permissions */ if (source_rule->xperms) { xperms = calloc(1, sizeof(av_extended_perms_t)); if (!xperms) goto err; memcpy(xperms, source_rule->xperms, sizeof(av_extended_perms_t)); avrule->xperms = xperms; } /* just prepend the avrule to the first branch; it'll never be written to disk */ if (!dest_pol->global->branch_list->avrules) dest_pol->global->branch_list->avrules = avrule; else { avrule->next = dest_pol->global->branch_list->avrules; dest_pol->global->branch_list->avrules = avrule; } ebitmap_destroy(&stypes); ebitmap_destroy(&ttypes); return 0; err: ebitmap_destroy(&stypes); ebitmap_destroy(&ttypes); ebitmap_destroy(&avrule->stypes.types); ebitmap_destroy(&avrule->ttypes.types); cur_perm = avrule->perms; while (cur_perm) { tail_perm = cur_perm->next; free(cur_perm); cur_perm = tail_perm; } free(xperms); free(avrule); return -1; } /* * Expands the avrule blocks for a policy. RBAC rules are copied. Neverallow * rules are copied or expanded as per the settings in the state object; all * other AV rules are expanded. If neverallow rules are expanded, they are not * copied, otherwise they are copied for later use by the assertion checker. */ static int copy_and_expand_avrule_block(expand_state_t * state) { avrule_block_t *curblock = state->base->global; avrule_block_t *prevblock; int retval = -1; if (avtab_alloc(&state->out->te_avtab, MAX_AVTAB_SIZE)) { ERR(state->handle, "Out of Memory!"); return -1; } if (avtab_alloc(&state->out->te_cond_avtab, MAX_AVTAB_SIZE)) { ERR(state->handle, "Out of Memory!"); return -1; } while (curblock) { avrule_decl_t *decl = curblock->enabled; avrule_t *cur_avrule; if (decl == NULL) { /* nothing was enabled within this block */ goto cont; } /* copy role allows and role trans */ if (copy_role_allows(state, decl->role_allow_rules) != 0 || copy_role_trans(state, decl->role_tr_rules) != 0) { goto cleanup; } if (expand_filename_trans(state, decl->filename_trans_rules)) goto cleanup; /* expand the range transition rules */ if (expand_range_trans(state, decl->range_tr_rules)) goto cleanup; /* copy rules */ cur_avrule = decl->avrules; while (cur_avrule != NULL) { if (!(state->expand_neverallow) && cur_avrule->specified & (AVRULE_NEVERALLOW | AVRULE_XPERMS_NEVERALLOW)) { /* copy this over directly so that assertions are checked later */ if (copy_neverallow (state->out, state->typemap, cur_avrule)) ERR(state->handle, "Error while copying neverallow."); } else { if (cur_avrule->specified & (AVRULE_NEVERALLOW | AVRULE_XPERMS_NEVERALLOW)) state->out->unsupported_format = 1; if (convert_and_expand_rule (state->handle, state->out, state->typemap, cur_avrule, &state->out->te_avtab, NULL, NULL, 0, state->expand_neverallow) != EXPAND_RULE_SUCCESS) { goto cleanup; } } cur_avrule = cur_avrule->next; } /* copy conditional rules */ if (cond_node_copy(state, decl->cond_list)) goto cleanup; cont: prevblock = curblock; curblock = curblock->next; if (state->handle && state->handle->expand_consume_base) { /* set base top avrule block in case there * is an error condition and the policy needs * to be destroyed */ state->base->global = curblock; avrule_block_destroy(prevblock); } } retval = 0; cleanup: return retval; } /* * This function allows external users of the library (such as setools) to * expand only the avrules and optionally perform expansion of neverallow rules * or expand into the same policy for analysis purposes. */ int expand_module_avrules(sepol_handle_t * handle, policydb_t * base, policydb_t * out, uint32_t * typemap, uint32_t * boolmap, uint32_t * rolemap, uint32_t * usermap, int verbose, int expand_neverallow) { expand_state_t state; expand_state_init(&state); state.base = base; state.out = out; state.typemap = typemap; state.boolmap = boolmap; state.rolemap = rolemap; state.usermap = usermap; state.handle = handle; state.verbose = verbose; state.expand_neverallow = expand_neverallow; return copy_and_expand_avrule_block(&state); } static void discard_tunables(sepol_handle_t *sh, policydb_t *pol) { avrule_block_t *block; avrule_decl_t *decl; cond_node_t *cur_node; cond_expr_t *cur_expr; int cur_state, preserve_tunables = 0; avrule_t *tail, *to_be_appended; if (sh && sh->preserve_tunables) preserve_tunables = 1; /* Iterate through all cond_node of all enabled decls, if a cond_node * is about tunable, calculate its state value and concatenate one of * its avrule list to the current decl->avrules list. On the other * hand, the disabled unused branch of a tunable would be discarded. * * Note, such tunable cond_node would be skipped over in expansion, * so we won't have to worry about removing it from decl->cond_list * here :-) * * If tunables are requested to be preserved then they would be * "transformed" as booleans by having their TUNABLE flag cleared. */ for (block = pol->global; block != NULL; block = block->next) { decl = block->enabled; if (decl == NULL || decl->enabled == 0) continue; tail = decl->avrules; while (tail && tail->next) tail = tail->next; for (cur_node = decl->cond_list; cur_node != NULL; cur_node = cur_node->next) { int booleans, tunables, i; cond_bool_datum_t *booldatum; cond_bool_datum_t *tmp[COND_EXPR_MAXDEPTH]; booleans = tunables = 0; memset(tmp, 0, sizeof(cond_bool_datum_t *) * COND_EXPR_MAXDEPTH); for (cur_expr = cur_node->expr; cur_expr != NULL; cur_expr = cur_expr->next) { if (cur_expr->expr_type != COND_BOOL) continue; booldatum = pol->bool_val_to_struct[cur_expr->boolean - 1]; if (booldatum->flags & COND_BOOL_FLAGS_TUNABLE) tmp[tunables++] = booldatum; else booleans++; } /* bool_copy_callback() at link phase has ensured * that no mixture of tunables and booleans in one * expression. However, this would be broken by the * request to preserve tunables */ if (!preserve_tunables) assert(!(booleans && tunables)); if (booleans || preserve_tunables) { cur_node->flags &= ~COND_NODE_FLAGS_TUNABLE; if (tunables) { for (i = 0; i < tunables; i++) tmp[i]->flags &= ~COND_BOOL_FLAGS_TUNABLE; } } else { cur_node->flags |= COND_NODE_FLAGS_TUNABLE; cur_state = cond_evaluate_expr(pol, cur_node->expr); if (cur_state == -1) { printf("Expression result was " "undefined, skipping all" "rules\n"); continue; } to_be_appended = (cur_state == 1) ? cur_node->avtrue_list : cur_node->avfalse_list; if (tail) tail->next = to_be_appended; else tail = decl->avrules = to_be_appended; /* Now that the effective branch has been * appended, neutralize its original pointer */ if (cur_state == 1) cur_node->avtrue_list = NULL; else cur_node->avfalse_list = NULL; /* Update the tail of decl->avrules for * further concatenation */ while (tail && tail->next) tail = tail->next; } } } } /* Linking should always be done before calling expand, even if * there is only a base since all optionals are dealt with at link time * the base passed in should be indexed and avrule blocks should be * enabled. */ int expand_module(sepol_handle_t * handle, policydb_t * base, policydb_t * out, int verbose, int check) { int retval = -1; unsigned int i; expand_state_t state; avrule_block_t *curblock; /* Append tunable's avtrue_list or avfalse_list to the avrules list * of its home decl depending on its state value, so that the effect * rules of a tunable would be added to te_avtab permanently. Whereas * the disabled unused branch would be discarded. * * Originally this function is called at the very end of link phase, * however, we need to keep the linked policy intact for analysis * purpose. */ discard_tunables(handle, base); expand_state_init(&state); state.verbose = verbose; state.typemap = NULL; state.base = base; state.out = out; state.handle = handle; if (base->policy_type != POLICY_BASE) { ERR(handle, "Target of expand was not a base policy."); return -1; } state.out->policy_type = POLICY_KERN; state.out->policyvers = POLICYDB_VERSION_MAX; if (state.base->name) { state.out->name = strdup(state.base->name); if (!state.out->name) { ERR(handle, "Out of memory!"); goto cleanup; } } /* Copy mls state from base to out */ out->mls = base->mls; out->handle_unknown = base->handle_unknown; /* Copy target from base to out */ out->target_platform = base->target_platform; /* Copy policy capabilities */ if (ebitmap_cpy(&out->policycaps, &base->policycaps)) { ERR(handle, "Out of memory!"); goto cleanup; } if ((state.typemap = (uint32_t *) calloc(state.base->p_types.nprim, sizeof(uint32_t))) == NULL) { ERR(handle, "Out of memory!"); goto cleanup; } state.boolmap = (uint32_t *)calloc(state.base->p_bools.nprim, sizeof(uint32_t)); if (!state.boolmap) { ERR(handle, "Out of memory!"); goto cleanup; } state.rolemap = (uint32_t *)calloc(state.base->p_roles.nprim, sizeof(uint32_t)); if (!state.rolemap) { ERR(handle, "Out of memory!"); goto cleanup; } state.usermap = (uint32_t *)calloc(state.base->p_users.nprim, sizeof(uint32_t)); if (!state.usermap) { ERR(handle, "Out of memory!"); goto cleanup; } /* order is important - types must be first */ /* copy types */ if (hashtab_map(state.base->p_types.table, type_copy_callback, &state)) { goto cleanup; } /* convert attribute type sets */ if (hashtab_map (state.base->p_types.table, attr_convert_callback, &state)) { goto cleanup; } /* copy commons */ if (hashtab_map (state.base->p_commons.table, common_copy_callback, &state)) { goto cleanup; } /* copy classes, note, this does not copy constraints, constraints can't be * copied until after all the blocks have been processed and attributes are complete */ if (hashtab_map (state.base->p_classes.table, class_copy_callback, &state)) { goto cleanup; } /* copy type bounds */ if (hashtab_map(state.base->p_types.table, type_bounds_copy_callback, &state)) goto cleanup; /* copy aliases */ if (hashtab_map(state.base->p_types.table, alias_copy_callback, &state)) goto cleanup; /* index here so that type indexes are available for role_copy_callback */ if (policydb_index_others(handle, out, verbose)) { ERR(handle, "Error while indexing out symbols"); goto cleanup; } /* copy roles */ if (hashtab_map(state.base->p_roles.table, role_copy_callback, &state)) goto cleanup; if (hashtab_map(state.base->p_roles.table, role_bounds_copy_callback, &state)) goto cleanup; /* copy MLS's sensitivity level and categories - this needs to be done * before expanding users (they need to be indexed too) */ if (hashtab_map(state.base->p_levels.table, sens_copy_callback, &state)) goto cleanup; if (hashtab_map(state.base->p_cats.table, cats_copy_callback, &state)) goto cleanup; if (policydb_index_others(handle, out, verbose)) { ERR(handle, "Error while indexing out symbols"); goto cleanup; } /* copy users */ if (hashtab_map(state.base->p_users.table, user_copy_callback, &state)) goto cleanup; if (hashtab_map(state.base->p_users.table, user_bounds_copy_callback, &state)) goto cleanup; /* copy bools */ if (hashtab_map(state.base->p_bools.table, bool_copy_callback, &state)) goto cleanup; if (policydb_index_classes(out)) { ERR(handle, "Error while indexing out classes"); goto cleanup; } if (policydb_index_others(handle, out, verbose)) { ERR(handle, "Error while indexing out symbols"); goto cleanup; } /* loop through all decls and union attributes, roles, users */ for (curblock = state.base->global; curblock != NULL; curblock = curblock->next) { avrule_decl_t *decl = curblock->enabled; if (decl == NULL) { /* nothing was enabled within this block */ continue; } /* convert attribute type sets */ if (hashtab_map (decl->p_types.table, attr_convert_callback, &state)) { goto cleanup; } /* copy roles */ if (hashtab_map (decl->p_roles.table, role_copy_callback, &state)) goto cleanup; /* copy users */ if (hashtab_map (decl->p_users.table, user_copy_callback, &state)) goto cleanup; } /* remap role dominates bitmaps */ if (hashtab_map(state.out->p_roles.table, role_remap_dominates, &state)) { goto cleanup; } /* escalate the type_set_t in a role attribute to all regular roles * that belongs to it. */ if (hashtab_map(state.base->p_roles.table, role_fix_callback, &state)) goto cleanup; if (copy_and_expand_avrule_block(&state) < 0) { ERR(handle, "Error during expand"); goto cleanup; } /* copy constraints */ if (hashtab_map (state.base->p_classes.table, constraint_copy_callback, &state)) { goto cleanup; } cond_optimize_lists(state.out->cond_list); if (evaluate_conds(state.out)) goto cleanup; /* copy ocontexts */ if (ocontext_copy(&state, out->target_platform)) goto cleanup; /* copy genfs */ if (genfs_copy(&state)) goto cleanup; /* Build the type<->attribute maps and remove attributes. */ state.out->attr_type_map = calloc(state.out->p_types.nprim, sizeof(ebitmap_t)); state.out->type_attr_map = calloc(state.out->p_types.nprim, sizeof(ebitmap_t)); if (!state.out->attr_type_map || !state.out->type_attr_map) { ERR(handle, "Out of memory!"); goto cleanup; } for (i = 0; i < state.out->p_types.nprim; i++) { /* add the type itself as the degenerate case */ if (ebitmap_set_bit(&state.out->type_attr_map[i], i, 1)) { ERR(handle, "Out of memory!"); goto cleanup; } } if (hashtab_map(state.out->p_types.table, type_attr_map, &state)) goto cleanup; if (check) { if (hierarchy_check_constraints(handle, state.out)) goto cleanup; if (check_assertions (handle, state.out, state.out->global->branch_list->avrules)) goto cleanup; } retval = 0; cleanup: free(state.typemap); free(state.boolmap); free(state.rolemap); free(state.usermap); return retval; } static int expand_avtab_insert(avtab_t * a, avtab_key_t * k, avtab_datum_t * d) { avtab_ptr_t node; avtab_datum_t *avd; avtab_extended_perms_t *xperms; unsigned int i; unsigned int match = 0; if (k->specified & AVTAB_XPERMS) { /* * AVTAB_XPERMS entries are not necessarily unique. * find node with matching xperms */ node = avtab_search_node(a, k); while (node) { if ((node->datum.xperms->specified == d->xperms->specified) && (node->datum.xperms->driver == d->xperms->driver)) { match = 1; break; } node = avtab_search_node_next(node, k->specified); } if (!match) node = NULL; } else { node = avtab_search_node(a, k); } if (!node || ((k->specified & AVTAB_ENABLED) != (node->key.specified & AVTAB_ENABLED))) { node = avtab_insert_nonunique(a, k, d); if (!node) { ERR(NULL, "Out of memory!"); return -1; } return 0; } avd = &node->datum; xperms = node->datum.xperms; switch (k->specified & ~AVTAB_ENABLED) { case AVTAB_ALLOWED: case AVTAB_AUDITALLOW: avd->data |= d->data; break; case AVTAB_AUDITDENY: avd->data &= d->data; break; case AVTAB_XPERMS_ALLOWED: case AVTAB_XPERMS_AUDITALLOW: case AVTAB_XPERMS_DONTAUDIT: for (i = 0; i < ARRAY_SIZE(xperms->perms); i++) xperms->perms[i] |= d->xperms->perms[i]; break; default: ERR(NULL, "Type conflict!"); return -1; } return 0; } struct expand_avtab_data { avtab_t *expa; policydb_t *p; }; static int expand_avtab_node(avtab_key_t * k, avtab_datum_t * d, void *args) { struct expand_avtab_data *ptr = args; avtab_t *expa = ptr->expa; policydb_t *p = ptr->p; type_datum_t *stype = p->type_val_to_struct[k->source_type - 1]; type_datum_t *ttype = p->type_val_to_struct[k->target_type - 1]; ebitmap_t *sattr = &p->attr_type_map[k->source_type - 1]; ebitmap_t *tattr = &p->attr_type_map[k->target_type - 1]; ebitmap_node_t *snode, *tnode; unsigned int i, j; avtab_key_t newkey; int rc; newkey.target_class = k->target_class; newkey.specified = k->specified; if (stype && ttype && stype->flavor != TYPE_ATTRIB && ttype->flavor != TYPE_ATTRIB) { /* Both are individual types, no expansion required. */ return expand_avtab_insert(expa, k, d); } if (stype && stype->flavor != TYPE_ATTRIB) { /* Source is an individual type, target is an attribute. */ newkey.source_type = k->source_type; ebitmap_for_each_positive_bit(tattr, tnode, j) { newkey.target_type = j + 1; rc = expand_avtab_insert(expa, &newkey, d); if (rc) return -1; } return 0; } if (ttype && ttype->flavor != TYPE_ATTRIB) { /* Target is an individual type, source is an attribute. */ newkey.target_type = k->target_type; ebitmap_for_each_positive_bit(sattr, snode, i) { newkey.source_type = i + 1; rc = expand_avtab_insert(expa, &newkey, d); if (rc) return -1; } return 0; } /* Both source and target type are attributes. */ ebitmap_for_each_positive_bit(sattr, snode, i) { ebitmap_for_each_positive_bit(tattr, tnode, j) { newkey.source_type = i + 1; newkey.target_type = j + 1; rc = expand_avtab_insert(expa, &newkey, d); if (rc) return -1; } } return 0; } int expand_avtab(policydb_t * p, avtab_t * a, avtab_t * expa) { struct expand_avtab_data data; if (avtab_alloc(expa, MAX_AVTAB_SIZE)) { ERR(NULL, "Out of memory!"); return -1; } data.expa = expa; data.p = p; return avtab_map(a, expand_avtab_node, &data); } static int expand_cond_insert(cond_av_list_t ** l, avtab_t * expa, avtab_key_t * k, avtab_datum_t * d) { avtab_ptr_t node; avtab_datum_t *avd; cond_av_list_t *nl; node = avtab_search_node(expa, k); if (!node || (k->specified & AVTAB_ENABLED) != (node->key.specified & AVTAB_ENABLED)) { node = avtab_insert_nonunique(expa, k, d); if (!node) { ERR(NULL, "Out of memory!"); return -1; } node->parse_context = (void *)1; nl = (cond_av_list_t *) malloc(sizeof(*nl)); if (!nl) { ERR(NULL, "Out of memory!"); return -1; } memset(nl, 0, sizeof(*nl)); nl->node = node; nl->next = *l; *l = nl; return 0; } avd = &node->datum; switch (k->specified & ~AVTAB_ENABLED) { case AVTAB_ALLOWED: case AVTAB_AUDITALLOW: avd->data |= d->data; break; case AVTAB_AUDITDENY: avd->data &= d->data; break; default: ERR(NULL, "Type conflict!"); return -1; } return 0; } static int expand_cond_av_node(policydb_t * p, avtab_ptr_t node, cond_av_list_t ** newl, avtab_t * expa) { avtab_key_t *k = &node->key; avtab_datum_t *d = &node->datum; type_datum_t *stype = p->type_val_to_struct[k->source_type - 1]; type_datum_t *ttype = p->type_val_to_struct[k->target_type - 1]; ebitmap_t *sattr = &p->attr_type_map[k->source_type - 1]; ebitmap_t *tattr = &p->attr_type_map[k->target_type - 1]; ebitmap_node_t *snode, *tnode; unsigned int i, j; avtab_key_t newkey; int rc; newkey.target_class = k->target_class; newkey.specified = k->specified; if (stype && ttype && stype->flavor != TYPE_ATTRIB && ttype->flavor != TYPE_ATTRIB) { /* Both are individual types, no expansion required. */ return expand_cond_insert(newl, expa, k, d); } if (stype && stype->flavor != TYPE_ATTRIB) { /* Source is an individual type, target is an attribute. */ newkey.source_type = k->source_type; ebitmap_for_each_positive_bit(tattr, tnode, j) { newkey.target_type = j + 1; rc = expand_cond_insert(newl, expa, &newkey, d); if (rc) return -1; } return 0; } if (ttype && ttype->flavor != TYPE_ATTRIB) { /* Target is an individual type, source is an attribute. */ newkey.target_type = k->target_type; ebitmap_for_each_positive_bit(sattr, snode, i) { newkey.source_type = i + 1; rc = expand_cond_insert(newl, expa, &newkey, d); if (rc) return -1; } return 0; } /* Both source and target type are attributes. */ ebitmap_for_each_positive_bit(sattr, snode, i) { ebitmap_for_each_positive_bit(tattr, tnode, j) { newkey.source_type = i + 1; newkey.target_type = j + 1; rc = expand_cond_insert(newl, expa, &newkey, d); if (rc) return -1; } } return 0; } int expand_cond_av_list(policydb_t * p, cond_av_list_t * l, cond_av_list_t ** newl, avtab_t * expa) { cond_av_list_t *cur; avtab_ptr_t node; int rc; if (avtab_alloc(expa, MAX_AVTAB_SIZE)) { ERR(NULL, "Out of memory!"); return -1; } *newl = NULL; for (cur = l; cur; cur = cur->next) { node = cur->node; rc = expand_cond_av_node(p, node, newl, expa); if (rc) return rc; } return 0; } libsepol-3.8.1/src/flask.h000066400000000000000000000034541476211737200154140ustar00rootroot00000000000000/* This file is automatically generated. Do not edit. */ #ifndef _SEPOL_POLICYDB_FLASK_H_ #define _SEPOL_POLICYDB_FLASK_H_ /* * Security identifier indices for initial entities */ #define SECINITSID_KERNEL 1 #define SECINITSID_SECURITY 2 #define SECINITSID_UNLABELED 3 #define SECINITSID_FS 4 #define SECINITSID_FILE 5 #define SECINITSID_FILE_LABELS 6 #define SECINITSID_INIT 7 #define SECINITSID_ANY_SOCKET 8 #define SECINITSID_PORT 9 #define SECINITSID_NETIF 10 #define SECINITSID_NETMSG 11 #define SECINITSID_NODE 12 #define SECINITSID_IGMP_PACKET 13 #define SECINITSID_ICMP_SOCKET 14 #define SECINITSID_TCP_SOCKET 15 #define SECINITSID_SYSCTL_MODPROBE 16 #define SECINITSID_SYSCTL 17 #define SECINITSID_SYSCTL_FS 18 #define SECINITSID_SYSCTL_KERNEL 19 #define SECINITSID_SYSCTL_NET 20 #define SECINITSID_SYSCTL_NET_UNIX 21 #define SECINITSID_SYSCTL_VM 22 #define SECINITSID_SYSCTL_DEV 23 #define SECINITSID_KMOD 24 #define SECINITSID_POLICY 25 #define SECINITSID_SCMP_PACKET 26 #define SECINITSID_DEVNULL 27 #define SECINITSID_NUM 27 #endif libsepol-3.8.1/src/handle.c000066400000000000000000000023311476211737200155330ustar00rootroot00000000000000#include #include #include "handle.h" #include "debug.h" sepol_handle_t *sepol_handle_create(void) { sepol_handle_t *sh = malloc(sizeof(sepol_handle_t)); if (sh == NULL) return NULL; /* Set callback */ sh->msg_callback = sepol_msg_default_handler; sh->msg_callback_arg = NULL; /* by default do not disable dontaudits */ sh->disable_dontaudit = 0; sh->expand_consume_base = 0; /* by default needless unused branch of tunables would be discarded */ sh->preserve_tunables = 0; return sh; } int sepol_get_preserve_tunables(sepol_handle_t *sh) { assert(sh != NULL); return sh->preserve_tunables; } void sepol_set_preserve_tunables(sepol_handle_t * sh, int preserve_tunables) { assert(sh !=NULL); sh->preserve_tunables = preserve_tunables; } int sepol_get_disable_dontaudit(sepol_handle_t *sh) { assert(sh !=NULL); return sh->disable_dontaudit; } void sepol_set_disable_dontaudit(sepol_handle_t * sh, int disable_dontaudit) { assert(sh !=NULL); sh->disable_dontaudit = disable_dontaudit; } void sepol_set_expand_consume_base(sepol_handle_t *sh, int consume_base) { assert(sh != NULL); sh->expand_consume_base = consume_base; } void sepol_handle_destroy(sepol_handle_t * sh) { free(sh); } libsepol-3.8.1/src/handle.h000066400000000000000000000007301476211737200155410ustar00rootroot00000000000000#ifndef _SEPOL_INTERNAL_HANDLE_H_ #define _SEPOL_INTERNAL_HANDLE_H_ #include struct sepol_handle { /* Error handling */ int msg_level; const char *msg_channel; const char *msg_fname; #ifdef __GNUC__ __attribute__ ((format(printf, 3, 4))) #endif void (*msg_callback) (void *varg, sepol_handle_t * handle, const char *fmt, ...); void *msg_callback_arg; int disable_dontaudit; int expand_consume_base; int preserve_tunables; }; #endif libsepol-3.8.1/src/hashtab.c000066400000000000000000000131661476211737200157220ustar00rootroot00000000000000 /* Author : Stephen Smalley, */ /* * Updated : Karl MacMillan * * Copyright (C) 2007 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* FLASK */ /* * Implementation of the hash table type. */ #include #include #include #include "private.h" hashtab_t hashtab_create(unsigned int (*hash_value) (hashtab_t h, const_hashtab_key_t key), int (*keycmp) (hashtab_t h, const_hashtab_key_t key1, const_hashtab_key_t key2), unsigned int size) { hashtab_t p; p = (hashtab_t) malloc(sizeof(hashtab_val_t)); if (p == NULL) return p; *p = (hashtab_val_t) { .size = size, .nel = 0, .hash_value = hash_value, .keycmp = keycmp, .htable = (hashtab_ptr_t *) calloc(size, sizeof(hashtab_ptr_t)), }; if (p->htable == NULL) { free(p); return NULL; } return p; } static void hashtab_check_resize(hashtab_t h) { unsigned int hvalue, i, old_size, new_size = h->size; hashtab_ptr_t *new_htable, *dst, cur, next; while (new_size <= h->nel && new_size * 2 != 0) new_size *= 2; if (h->size == new_size) return; new_htable = calloc(new_size, sizeof(*new_htable)); if (!new_htable) return; old_size = h->size; h->size = new_size; /* Move all elements to the new htable */ for (i = 0; i < old_size; i++) { cur = h->htable[i]; while (cur != NULL) { hvalue = h->hash_value(h, cur->key); dst = &new_htable[hvalue]; while (*dst && h->keycmp(h, cur->key, (*dst)->key) > 0) dst = &(*dst)->next; next = cur->next; cur->next = *dst; *dst = cur; cur = next; } } free(h->htable); h->htable = new_htable; } int hashtab_insert(hashtab_t h, hashtab_key_t key, hashtab_datum_t datum) { unsigned int hvalue; hashtab_ptr_t prev, cur, newnode; if (!h || h->nel == UINT32_MAX) return SEPOL_ENOMEM; hashtab_check_resize(h); hvalue = h->hash_value(h, key); for (prev = NULL, cur = h->htable[hvalue]; cur; prev = cur, cur = cur->next) { int cmp; cmp = h->keycmp(h, key, cur->key); if (cmp > 0) continue; if (cmp == 0) return SEPOL_EEXIST; break; } newnode = (hashtab_ptr_t) malloc(sizeof(hashtab_node_t)); if (newnode == NULL) return SEPOL_ENOMEM; *newnode = (hashtab_node_t) { .key = key, .datum = datum, }; if (prev) { newnode->next = prev->next; prev->next = newnode; } else { newnode->next = h->htable[hvalue]; h->htable[hvalue] = newnode; } h->nel++; return SEPOL_OK; } int hashtab_remove(hashtab_t h, hashtab_key_t key, void (*destroy) (hashtab_key_t k, hashtab_datum_t d, void *args), void *args) { unsigned int hvalue; hashtab_ptr_t cur, last; if (!h) return SEPOL_ENOENT; hvalue = h->hash_value(h, key); for (last = NULL, cur = h->htable[hvalue]; cur; last = cur, cur = cur->next) { int cmp; cmp = h->keycmp(h, key, cur->key); if (cmp > 0) continue; if (cmp == 0) break; return SEPOL_ENOENT; } if (cur == NULL) return SEPOL_ENOENT; if (last == NULL) h->htable[hvalue] = cur->next; else last->next = cur->next; if (destroy) destroy(cur->key, cur->datum, args); free(cur); h->nel--; return SEPOL_OK; } hashtab_datum_t hashtab_search(hashtab_t h, const_hashtab_key_t key) { unsigned int hvalue; hashtab_ptr_t cur; if (!h) return NULL; hvalue = h->hash_value(h, key); for (cur = h->htable[hvalue]; cur; cur = cur->next) { int cmp; cmp = h->keycmp(h, key, cur->key); if (cmp > 0) continue; if (cmp == 0) return cur->datum; break; } return NULL; } void hashtab_destroy(hashtab_t h) { unsigned int i; hashtab_ptr_t cur, temp; if (!h) return; for (i = 0; i < h->size; i++) { cur = h->htable[i]; while (cur != NULL) { temp = cur; cur = cur->next; free(temp); } h->htable[i] = NULL; } free(h->htable); free(h); } int hashtab_map(hashtab_t h, int (*apply) (hashtab_key_t k, hashtab_datum_t d, void *args), void *args) { unsigned int i; hashtab_ptr_t cur; int ret; if (!h) return SEPOL_OK; for (i = 0; i < h->size; i++) { cur = h->htable[i]; while (cur != NULL) { ret = apply(cur->key, cur->datum, args); if (ret) return ret; cur = cur->next; } } return SEPOL_OK; } void hashtab_hash_eval(hashtab_t h, const char *tag) { unsigned int i; size_t chain_len, slots_used, max_chain_len, chain2_len_sum; hashtab_ptr_t cur; slots_used = 0; max_chain_len = 0; chain2_len_sum = 0; for (i = 0; i < h->size; i++) { cur = h->htable[i]; if (cur) { slots_used++; chain_len = 0; while (cur) { chain_len++; cur = cur->next; } if (chain_len > max_chain_len) max_chain_len = chain_len; chain2_len_sum += chain_len * chain_len; } } printf ("%s: %d entries and %zu/%d buckets used, longest chain length %zu, chain length^2 %zu, normalized chain length^2 %.2f\n", tag, h->nel, slots_used, h->size, max_chain_len, chain2_len_sum, chain2_len_sum ? (float)chain2_len_sum / slots_used : 0); } libsepol-3.8.1/src/hierarchy.c000066400000000000000000000417121476211737200162640ustar00rootroot00000000000000/* Authors: Joshua Brindle * Jason Tang * * Updates: KaiGai Kohei * adds checks based on newer boundary facility. * * A set of utility functions that aid policy decision when dealing * with hierarchal namespaces. * * Copyright (C) 2005 Tresys Technology, LLC * * Copyright (c) 2008 NEC Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include "debug.h" #define BOUNDS_AVTAB_SIZE 1024 static int bounds_insert_helper(sepol_handle_t *handle, avtab_t *avtab, avtab_key_t *avtab_key, avtab_datum_t *datum) { int rc = avtab_insert(avtab, avtab_key, datum); if (rc) { if (rc == SEPOL_ENOMEM) ERR(handle, "Insufficient memory"); else ERR(handle, "Unexpected error (%d)", rc); } return rc; } static int bounds_insert_rule(sepol_handle_t *handle, avtab_t *avtab, avtab_t *global, avtab_t *other, avtab_key_t *avtab_key, avtab_datum_t *datum) { int rc = 0; avtab_datum_t *dup = avtab_search(avtab, avtab_key); if (!dup) { rc = bounds_insert_helper(handle, avtab, avtab_key, datum); if (rc) goto exit; } else { dup->data |= datum->data; } if (other) { /* Search the other conditional avtab for the key and * add any common permissions to the global avtab */ uint32_t data = 0; dup = avtab_search(other, avtab_key); if (dup) { data = dup->data & datum->data; if (data) { dup = avtab_search(global, avtab_key); if (!dup) { avtab_datum_t d; d.data = data; rc = bounds_insert_helper(handle, global, avtab_key, &d); if (rc) goto exit; } else { dup->data |= data; } } } } exit: return rc; } static int bounds_expand_rule(sepol_handle_t *handle, policydb_t *p, avtab_t *avtab, avtab_t *global, avtab_t *other, uint32_t parent, uint32_t src, uint32_t tgt, uint32_t class, uint32_t data) { int rc = 0; avtab_key_t avtab_key; avtab_datum_t datum; ebitmap_node_t *tnode; unsigned int i; avtab_key.specified = AVTAB_ALLOWED; avtab_key.target_class = class; datum.data = data; if (ebitmap_get_bit(&p->attr_type_map[src - 1], parent - 1)) { avtab_key.source_type = parent; ebitmap_for_each_positive_bit(&p->attr_type_map[tgt - 1], tnode, i) { avtab_key.target_type = i + 1; rc = bounds_insert_rule(handle, avtab, global, other, &avtab_key, &datum); if (rc) goto exit; } } exit: return rc; } static int bounds_expand_cond_rules(sepol_handle_t *handle, policydb_t *p, cond_av_list_t *cur, avtab_t *avtab, avtab_t *global, avtab_t *other, uint32_t parent) { int rc = 0; for (; cur; cur = cur->next) { avtab_ptr_t n = cur->node; rc = bounds_expand_rule(handle, p, avtab, global, other, parent, n->key.source_type, n->key.target_type, n->key.target_class, n->datum.data); if (rc) goto exit; } exit: return rc; } struct bounds_expand_args { sepol_handle_t *handle; policydb_t *p; avtab_t *avtab; uint32_t parent; }; static int bounds_expand_rule_callback(avtab_key_t *k, avtab_datum_t *d, void *args) { struct bounds_expand_args *a = (struct bounds_expand_args *)args; if (!(k->specified & AVTAB_ALLOWED)) return 0; return bounds_expand_rule(a->handle, a->p, a->avtab, NULL, NULL, a->parent, k->source_type, k->target_type, k->target_class, d->data); } struct bounds_cond_info { avtab_t true_avtab; avtab_t false_avtab; cond_list_t *cond_list; struct bounds_cond_info *next; }; static void bounds_destroy_cond_info(struct bounds_cond_info *cur) { struct bounds_cond_info *next; for (; cur; cur = next) { next = cur->next; avtab_destroy(&cur->true_avtab); avtab_destroy(&cur->false_avtab); cur->next = NULL; free(cur); } } static int bounds_expand_parent_rules(sepol_handle_t *handle, policydb_t *p, avtab_t *global_avtab, struct bounds_cond_info **cond_info, uint32_t parent) { int rc = 0; struct bounds_expand_args args; cond_list_t *cur; avtab_init(global_avtab); rc = avtab_alloc(global_avtab, BOUNDS_AVTAB_SIZE); if (rc) goto oom; args.handle = handle; args.p = p; args.avtab = global_avtab; args.parent = parent; rc = avtab_map(&p->te_avtab, bounds_expand_rule_callback, &args); if (rc) goto exit; *cond_info = NULL; for (cur = p->cond_list; cur; cur = cur->next) { struct bounds_cond_info *ci; ci = malloc(sizeof(struct bounds_cond_info)); if (!ci) goto oom; avtab_init(&ci->true_avtab); avtab_init(&ci->false_avtab); ci->cond_list = cur; ci->next = *cond_info; *cond_info = ci; if (cur->true_list) { rc = avtab_alloc(&ci->true_avtab, BOUNDS_AVTAB_SIZE); if (rc) goto oom; rc = bounds_expand_cond_rules(handle, p, cur->true_list, &ci->true_avtab, NULL, NULL, parent); if (rc) goto exit; } if (cur->false_list) { rc = avtab_alloc(&ci->false_avtab, BOUNDS_AVTAB_SIZE); if (rc) goto oom; rc = bounds_expand_cond_rules(handle, p, cur->false_list, &ci->false_avtab, global_avtab, &ci->true_avtab, parent); if (rc) goto exit; } } return 0; oom: ERR(handle, "Insufficient memory"); exit: ERR(handle,"Failed to expand parent rules"); avtab_destroy(global_avtab); bounds_destroy_cond_info(*cond_info); *cond_info = NULL; return rc; } static int bounds_not_covered(avtab_t *global_avtab, avtab_t *cur_avtab, avtab_key_t *avtab_key, uint32_t data) { avtab_datum_t *datum = avtab_search(cur_avtab, avtab_key); if (datum) data &= ~datum->data; if (global_avtab && data) { datum = avtab_search(global_avtab, avtab_key); if (datum) data &= ~datum->data; } return data; } static int bounds_add_bad(sepol_handle_t *handle, uint32_t src, uint32_t tgt, uint32_t class, uint32_t data, avtab_ptr_t *bad) { struct avtab_node *new = malloc(sizeof(struct avtab_node)); if (new == NULL) { ERR(handle, "Insufficient memory"); return SEPOL_ENOMEM; } memset(new, 0, sizeof(struct avtab_node)); new->key.source_type = src; new->key.target_type = tgt; new->key.target_class = class; new->datum.data = data; new->next = *bad; *bad = new; return 0; } static int bounds_check_rule(sepol_handle_t *handle, policydb_t *p, avtab_t *global_avtab, avtab_t *cur_avtab, uint32_t child, uint32_t parent, uint32_t src, uint32_t tgt, uint32_t class, uint32_t data, avtab_ptr_t *bad, int *numbad) { int rc = 0; avtab_key_t avtab_key; type_datum_t *td; ebitmap_node_t *tnode; unsigned int i; uint32_t d; avtab_key.specified = AVTAB_ALLOWED; avtab_key.target_class = class; if (ebitmap_get_bit(&p->attr_type_map[src - 1], child - 1)) { avtab_key.source_type = parent; ebitmap_for_each_positive_bit(&p->attr_type_map[tgt - 1], tnode, i) { td = p->type_val_to_struct[i]; if (td && td->bounds) { avtab_key.target_type = td->bounds; d = bounds_not_covered(global_avtab, cur_avtab, &avtab_key, data); } else { avtab_key.target_type = i + 1; d = bounds_not_covered(global_avtab, cur_avtab, &avtab_key, data); } if (d) { (*numbad)++; rc = bounds_add_bad(handle, child, i+1, class, d, bad); if (rc) goto exit; } } } exit: return rc; } static int bounds_check_cond_rules(sepol_handle_t *handle, policydb_t *p, avtab_t *global_avtab, avtab_t *cond_avtab, cond_av_list_t *rules, uint32_t child, uint32_t parent, avtab_ptr_t *bad, int *numbad) { int rc = 0; cond_av_list_t *cur; for (cur = rules; cur; cur = cur->next) { avtab_ptr_t ap = cur->node; avtab_key_t *key = &ap->key; avtab_datum_t *datum = &ap->datum; if (!(key->specified & AVTAB_ALLOWED)) continue; rc = bounds_check_rule(handle, p, global_avtab, cond_avtab, child, parent, key->source_type, key->target_type, key->target_class, datum->data, bad, numbad); if (rc) goto exit; } exit: return rc; } struct bounds_check_args { sepol_handle_t *handle; policydb_t *p; avtab_t *cur_avtab; uint32_t child; uint32_t parent; avtab_ptr_t bad; int numbad; }; static int bounds_check_rule_callback(avtab_key_t *k, avtab_datum_t *d, void *args) { struct bounds_check_args *a = (struct bounds_check_args *)args; if (!(k->specified & AVTAB_ALLOWED)) return 0; return bounds_check_rule(a->handle, a->p, NULL, a->cur_avtab, a->child, a->parent, k->source_type, k->target_type, k->target_class, d->data, &a->bad, &a->numbad); } static int bounds_check_child_rules(sepol_handle_t *handle, policydb_t *p, avtab_t *global_avtab, struct bounds_cond_info *cond_info, uint32_t child, uint32_t parent, avtab_ptr_t *bad, int *numbad) { int rc; struct bounds_check_args args; struct bounds_cond_info *cur; args.handle = handle; args.p = p; args.cur_avtab = global_avtab; args.child = child; args.parent = parent; args.bad = NULL; args.numbad = 0; rc = avtab_map(&p->te_avtab, bounds_check_rule_callback, &args); if (rc) goto exit; for (cur = cond_info; cur; cur = cur->next) { cond_list_t *node = cur->cond_list; rc = bounds_check_cond_rules(handle, p, global_avtab, &cur->true_avtab, node->true_list, child, parent, &args.bad, &args.numbad); if (rc) goto exit; rc = bounds_check_cond_rules(handle, p, global_avtab, &cur->false_avtab, node->false_list, child, parent, &args.bad, &args.numbad); if (rc) goto exit; } *numbad += args.numbad; *bad = args.bad; exit: return rc; } int bounds_check_type(sepol_handle_t *handle, policydb_t *p, uint32_t child, uint32_t parent, avtab_ptr_t *bad, int *numbad) { int rc = 0; avtab_t global_avtab; struct bounds_cond_info *cond_info = NULL; rc = bounds_expand_parent_rules(handle, p, &global_avtab, &cond_info, parent); if (rc) goto exit; rc = bounds_check_child_rules(handle, p, &global_avtab, cond_info, child, parent, bad, numbad); bounds_destroy_cond_info(cond_info); avtab_destroy(&global_avtab); exit: return rc; } struct bounds_args { sepol_handle_t *handle; policydb_t *p; int numbad; }; static void bounds_report(sepol_handle_t *handle, policydb_t *p, uint32_t child, uint32_t parent, avtab_ptr_t cur) { ERR(handle, "Child type %s exceeds bounds of parent %s in the following rules:", p->p_type_val_to_name[child - 1], p->p_type_val_to_name[parent - 1]); for (; cur; cur = cur->next) { char *permstr = sepol_av_to_string(p, cur->key.target_class, cur->datum.data); ERR(handle, " %s %s : %s { %s }", p->p_type_val_to_name[cur->key.source_type - 1], p->p_type_val_to_name[cur->key.target_type - 1], p->p_class_val_to_name[cur->key.target_class - 1], permstr ?: ""); free(permstr); } } void bounds_destroy_bad(avtab_ptr_t cur) { avtab_ptr_t next; for (; cur; cur = next) { next = cur->next; cur->next = NULL; free(cur); } } static int bounds_check_type_callback(hashtab_key_t k __attribute__ ((unused)), hashtab_datum_t d, void *args) { int rc = 0; struct bounds_args *a = (struct bounds_args *)args; type_datum_t *t = (type_datum_t *)d; avtab_ptr_t bad = NULL; if (t->bounds) { rc = bounds_check_type(a->handle, a->p, t->s.value, t->bounds, &bad, &a->numbad); if (bad) { bounds_report(a->handle, a->p, t->s.value, t->bounds, bad); bounds_destroy_bad(bad); } } return rc; } int bounds_check_types(sepol_handle_t *handle, policydb_t *p) { int rc; struct bounds_args args; args.handle = handle; args.p = p; args.numbad = 0; rc = hashtab_map(p->p_types.table, bounds_check_type_callback, &args); if (rc) goto exit; if (args.numbad > 0) { ERR(handle, "%d errors found during type bounds check", args.numbad); rc = SEPOL_ERR; } exit: return rc; } /* The role bounds is defined as: a child role cannot have a type that * its parent doesn't have. */ static int bounds_check_role_callback(hashtab_key_t k, hashtab_datum_t d, void *args) { struct bounds_args *a = (struct bounds_args *)args; role_datum_t *r = (role_datum_t *) d; role_datum_t *rp = NULL; if (!r->bounds) return 0; rp = a->p->role_val_to_struct[r->bounds - 1]; if (rp && !ebitmap_contains(&rp->types.types, &r->types.types)) { ERR(a->handle, "Role bounds violation, %s exceeds %s", (char *)k, a->p->p_role_val_to_name[rp->s.value - 1]); a->numbad++; } return 0; } int bounds_check_roles(sepol_handle_t *handle, policydb_t *p) { struct bounds_args args; args.handle = handle; args.p = p; args.numbad = 0; hashtab_map(p->p_roles.table, bounds_check_role_callback, &args); if (args.numbad > 0) { ERR(handle, "%d errors found during role bounds check", args.numbad); return SEPOL_ERR; } return 0; } /* The user bounds is defined as: a child user cannot have a role that * its parent doesn't have. */ static int bounds_check_user_callback(hashtab_key_t k, hashtab_datum_t d, void *args) { struct bounds_args *a = (struct bounds_args *)args; user_datum_t *u = (user_datum_t *) d; user_datum_t *up = NULL; if (!u->bounds) return 0; up = a->p->user_val_to_struct[u->bounds - 1]; if (up && !ebitmap_contains(&up->roles.roles, &u->roles.roles)) { ERR(a->handle, "User bounds violation, %s exceeds %s", (char *) k, a->p->p_user_val_to_name[up->s.value - 1]); a->numbad++; } return 0; } int bounds_check_users(sepol_handle_t *handle, policydb_t *p) { struct bounds_args args; args.handle = handle; args.p = p; args.numbad = 0; hashtab_map(p->p_users.table, bounds_check_user_callback, &args); if (args.numbad > 0) { ERR(handle, "%d errors found during user bounds check", args.numbad); return SEPOL_ERR; } return 0; } #define add_hierarchy_callback_template(prefix) \ int hierarchy_add_##prefix##_callback(hashtab_key_t k __attribute__ ((unused)), \ hashtab_datum_t d, void *args) \ { \ struct bounds_args *a = (struct bounds_args *)args; \ sepol_handle_t *handle = a->handle; \ policydb_t *p = a->p; \ prefix##_datum_t *datum = (prefix##_datum_t *)d; \ prefix##_datum_t *parent; \ char *parent_name, *datum_name, *tmp; \ \ if (!datum->bounds) { \ datum_name = p->p_##prefix##_val_to_name[datum->s.value - 1]; \ \ tmp = strrchr(datum_name, '.'); \ /* no '.' means it has no parent */ \ if (!tmp) return 0; \ \ parent_name = strdup(datum_name); \ if (!parent_name) { \ ERR(handle, "Insufficient memory"); \ return SEPOL_ENOMEM; \ } \ parent_name[tmp - datum_name] = '\0'; \ \ parent = hashtab_search(p->p_##prefix##s.table, parent_name); \ if (!parent) { \ /* Orphan type/role/user */ \ ERR(handle, "%s doesn't exist, %s is an orphan",\ parent_name, \ p->p_##prefix##_val_to_name[datum->s.value - 1]); \ free(parent_name); \ a->numbad++; \ return 0; \ } \ datum->bounds = parent->s.value; \ free(parent_name); \ } \ \ return 0; \ } \ static add_hierarchy_callback_template(type) static add_hierarchy_callback_template(role) static add_hierarchy_callback_template(user) int hierarchy_add_bounds(sepol_handle_t *handle, policydb_t *p) { int rc = 0; struct bounds_args args; args.handle = handle; args.p = p; args.numbad = 0; rc = hashtab_map(p->p_users.table, hierarchy_add_user_callback, &args); if (rc) goto exit; rc = hashtab_map(p->p_roles.table, hierarchy_add_role_callback, &args); if (rc) goto exit; rc = hashtab_map(p->p_types.table, hierarchy_add_type_callback, &args); if (rc) goto exit; if (args.numbad > 0) { ERR(handle, "%d errors found while adding hierarchies", args.numbad); rc = SEPOL_ERR; } exit: return rc; } int hierarchy_check_constraints(sepol_handle_t * handle, policydb_t * p) { int rc = 0; int violation = 0; rc = hierarchy_add_bounds(handle, p); if (rc) goto exit; rc = bounds_check_users(handle, p); if (rc) violation = 1; rc = bounds_check_roles(handle, p); if (rc) violation = 1; rc = bounds_check_types(handle, p); if (rc) { if (rc == SEPOL_ERR) violation = 1; else goto exit; } if (violation) rc = SEPOL_ERR; exit: return rc; } libsepol-3.8.1/src/ibendport_internal.h000066400000000000000000000002251476211737200201670ustar00rootroot00000000000000#ifndef _SEPOL_IBENDPORT_INTERNAL_H_ #define _SEPOL_IBENDPORT_INTERNAL_H_ #include #include #endif libsepol-3.8.1/src/ibendport_record.c000066400000000000000000000137671476211737200176430ustar00rootroot00000000000000#include #include #include #include #include #include "sepol/policydb/policydb.h" #include "ibendport_internal.h" #include "context_internal.h" #include "debug.h" struct sepol_ibendport { /* Device Name */ char *ibdev_name; /* Port number */ int port; /* Context */ sepol_context_t *con; }; struct sepol_ibendport_key { /* Device Name */ char *ibdev_name; /* Port number */ int port; }; /* Allocates a sufficiently large string (ibdev_name) */ int sepol_ibendport_alloc_ibdev_name(sepol_handle_t *handle, char **ibdev_name) { *ibdev_name = calloc(1, IB_DEVICE_NAME_MAX); if (!*ibdev_name) goto omem; return STATUS_SUCCESS; omem: ERR(handle, "out of memory"); ERR(handle, "could not allocate string buffer for ibdev_name"); return STATUS_ERR; } /* Key */ int sepol_ibendport_key_create(sepol_handle_t *handle, const char *ibdev_name, int port, sepol_ibendport_key_t **key_ptr) { sepol_ibendport_key_t *tmp_key = (sepol_ibendport_key_t *)malloc(sizeof(sepol_ibendport_key_t)); if (!tmp_key) { ERR(handle, "out of memory, could not create ibendport key"); goto omem; } if (sepol_ibendport_alloc_ibdev_name(handle, &tmp_key->ibdev_name) < 0) goto err; strncpy(tmp_key->ibdev_name, ibdev_name, IB_DEVICE_NAME_MAX - 1); tmp_key->port = port; *key_ptr = tmp_key; return STATUS_SUCCESS; omem: ERR(handle, "out of memory"); err: sepol_ibendport_key_free(tmp_key); ERR(handle, "could not create ibendport key for IB device %s, port %u", ibdev_name, port); return STATUS_ERR; } void sepol_ibendport_key_unpack(const sepol_ibendport_key_t *key, const char **ibdev_name, int *port) { *ibdev_name = key->ibdev_name; *port = key->port; } int sepol_ibendport_key_extract(sepol_handle_t *handle, const sepol_ibendport_t *ibendport, sepol_ibendport_key_t **key_ptr) { if (sepol_ibendport_key_create (handle, ibendport->ibdev_name, ibendport->port, key_ptr) < 0) { ERR(handle, "could not extract key from ibendport device %s port %d", ibendport->ibdev_name, ibendport->port); return STATUS_ERR; } return STATUS_SUCCESS; } void sepol_ibendport_key_free(sepol_ibendport_key_t *key) { if (!key) return; free(key->ibdev_name); free(key); } int sepol_ibendport_compare(const sepol_ibendport_t *ibendport, const sepol_ibendport_key_t *key) { int rc; rc = strcmp(ibendport->ibdev_name, key->ibdev_name); if ((ibendport->port == key->port) && !rc) return 0; if (ibendport->port < key->port) return -1; else if (key->port < ibendport->port) return 1; else return rc; } int sepol_ibendport_compare2(const sepol_ibendport_t *ibendport, const sepol_ibendport_t *ibendport2) { int rc; rc = strcmp(ibendport->ibdev_name, ibendport2->ibdev_name); if ((ibendport->port == ibendport2->port) && !rc) return 0; if (ibendport->port < ibendport2->port) return -1; else if (ibendport2->port < ibendport->port) return 1; else return rc; } int sepol_ibendport_get_port(const sepol_ibendport_t *ibendport) { return ibendport->port; } void sepol_ibendport_set_port(sepol_ibendport_t *ibendport, int port) { ibendport->port = port; } int sepol_ibendport_get_ibdev_name(sepol_handle_t *handle, const sepol_ibendport_t *ibendport, char **ibdev_name) { char *tmp_ibdev_name = NULL; if (sepol_ibendport_alloc_ibdev_name(handle, &tmp_ibdev_name) < 0) goto err; strncpy(tmp_ibdev_name, ibendport->ibdev_name, IB_DEVICE_NAME_MAX - 1); *ibdev_name = tmp_ibdev_name; return STATUS_SUCCESS; err: free(tmp_ibdev_name); ERR(handle, "could not get ibendport ibdev_name"); return STATUS_ERR; } int sepol_ibendport_set_ibdev_name(sepol_handle_t *handle, sepol_ibendport_t *ibendport, const char *ibdev_name) { char *tmp = NULL; if (sepol_ibendport_alloc_ibdev_name(handle, &tmp) < 0) goto err; strncpy(tmp, ibdev_name, IB_DEVICE_NAME_MAX - 1); free(ibendport->ibdev_name); ibendport->ibdev_name = tmp; return STATUS_SUCCESS; err: free(tmp); ERR(handle, "could not set ibendport subnet prefix to %s", ibdev_name); return STATUS_ERR; } /* Create */ int sepol_ibendport_create(sepol_handle_t *handle, sepol_ibendport_t **ibendport) { sepol_ibendport_t *tmp_ibendport = (sepol_ibendport_t *)malloc(sizeof(sepol_ibendport_t)); if (!tmp_ibendport) { ERR(handle, "out of memory, could not create ibendport record"); return STATUS_ERR; } tmp_ibendport->ibdev_name = NULL; tmp_ibendport->port = 0; tmp_ibendport->con = NULL; *ibendport = tmp_ibendport; return STATUS_SUCCESS; } /* Deep copy clone */ int sepol_ibendport_clone(sepol_handle_t *handle, const sepol_ibendport_t *ibendport, sepol_ibendport_t **ibendport_ptr) { sepol_ibendport_t *new_ibendport = NULL; if (sepol_ibendport_create(handle, &new_ibendport) < 0) goto err; if (sepol_ibendport_alloc_ibdev_name(handle, &new_ibendport->ibdev_name) < 0) goto omem; strncpy(new_ibendport->ibdev_name, ibendport->ibdev_name, IB_DEVICE_NAME_MAX - 1); new_ibendport->port = ibendport->port; if (ibendport->con && (sepol_context_clone(handle, ibendport->con, &new_ibendport->con) < 0)) goto err; *ibendport_ptr = new_ibendport; return STATUS_SUCCESS; omem: ERR(handle, "out of memory"); err: ERR(handle, "could not clone ibendport record"); sepol_ibendport_free(new_ibendport); return STATUS_ERR; } /* Destroy */ void sepol_ibendport_free(sepol_ibendport_t *ibendport) { if (!ibendport) return; free(ibendport->ibdev_name); sepol_context_free(ibendport->con); free(ibendport); } /* Context */ sepol_context_t *sepol_ibendport_get_con(const sepol_ibendport_t *ibendport) { return ibendport->con; } int sepol_ibendport_set_con(sepol_handle_t *handle, sepol_ibendport_t *ibendport, sepol_context_t *con) { sepol_context_t *newcon; if (sepol_context_clone(handle, con, &newcon) < 0) { ERR(handle, "out of memory, could not set ibendport context"); return STATUS_ERR; } sepol_context_free(ibendport->con); ibendport->con = newcon; return STATUS_SUCCESS; } libsepol-3.8.1/src/ibendports.c000066400000000000000000000135441476211737200164610ustar00rootroot00000000000000#include #include #include "debug.h" #include "context.h" #include "handle.h" #include #include "ibendport_internal.h" /* Create a low level ibendport structure from * a high level representation */ static int ibendport_from_record(sepol_handle_t *handle, const policydb_t *policydb, ocontext_t **ibendport, const sepol_ibendport_t *data) { ocontext_t *tmp_ibendport = NULL; context_struct_t *tmp_con = NULL; char *ibdev_name = NULL; int port = sepol_ibendport_get_port(data); tmp_ibendport = (ocontext_t *)calloc(1, sizeof(ocontext_t)); if (!tmp_ibendport) goto omem; if (sepol_ibendport_alloc_ibdev_name(handle, &tmp_ibendport->u.ibendport.dev_name) < 0) goto omem; if (sepol_ibendport_get_ibdev_name(handle, data, &ibdev_name) < 0) goto err; strncpy(tmp_ibendport->u.ibendport.dev_name, ibdev_name, IB_DEVICE_NAME_MAX - 1); free(ibdev_name); ibdev_name = NULL; tmp_ibendport->u.ibendport.port = port; /* Context */ if (context_from_record(handle, policydb, &tmp_con, sepol_ibendport_get_con(data)) < 0) goto err; context_cpy(&tmp_ibendport->context[0], tmp_con); context_destroy(tmp_con); free(tmp_con); tmp_con = NULL; *ibendport = tmp_ibendport; return STATUS_SUCCESS; omem: ERR(handle, "out of memory"); err: if (tmp_ibendport) { context_destroy(&tmp_ibendport->context[0]); free(tmp_ibendport); } context_destroy(tmp_con); free(tmp_con); free(ibdev_name); ERR(handle, "could not create ibendport structure"); return STATUS_ERR; } static int ibendport_to_record(sepol_handle_t *handle, const policydb_t *policydb, ocontext_t *ibendport, sepol_ibendport_t **record) { int port = ibendport->u.ibendport.port; context_struct_t *con = &ibendport->context[0]; sepol_context_t *tmp_con = NULL; sepol_ibendport_t *tmp_record = NULL; if (sepol_ibendport_create(handle, &tmp_record) < 0) goto err; if (sepol_ibendport_set_ibdev_name(handle, tmp_record, ibendport->u.ibendport.dev_name) < 0) goto err; sepol_ibendport_set_port(tmp_record, port); if (context_to_record(handle, policydb, con, &tmp_con) < 0) goto err; if (sepol_ibendport_set_con(handle, tmp_record, tmp_con) < 0) goto err; sepol_context_free(tmp_con); *record = tmp_record; return STATUS_SUCCESS; err: ERR(handle, "could not convert ibendport to record"); sepol_context_free(tmp_con); sepol_ibendport_free(tmp_record); return STATUS_ERR; } /* Return the number of ibendports */ extern int sepol_ibendport_count(sepol_handle_t *handle __attribute__ ((unused)), const sepol_policydb_t *p, unsigned int *response) { unsigned int count = 0; ocontext_t *c, *head; const policydb_t *policydb = &p->p; head = policydb->ocontexts[OCON_IBENDPORT]; for (c = head; c; c = c->next) count++; *response = count; return STATUS_SUCCESS; } /* Check if a ibendport exists */ int sepol_ibendport_exists(sepol_handle_t *handle __attribute__ ((unused)), const sepol_policydb_t *p, const sepol_ibendport_key_t *key, int *response) { const policydb_t *policydb = &p->p; ocontext_t *c, *head; int port; const char *ibdev_name; sepol_ibendport_key_unpack(key, &ibdev_name, &port); head = policydb->ocontexts[OCON_IBENDPORT]; for (c = head; c; c = c->next) { const char *ibdev_name2 = c->u.ibendport.dev_name; int port2 = c->u.ibendport.port; if (port2 == port && (!strcmp(ibdev_name, ibdev_name2))) { *response = 1; return STATUS_SUCCESS; } } *response = 0; return STATUS_SUCCESS; } int sepol_ibendport_query(sepol_handle_t *handle, const sepol_policydb_t *p, const sepol_ibendport_key_t *key, sepol_ibendport_t **response) { const policydb_t *policydb = &p->p; ocontext_t *c, *head; int port; const char *ibdev_name; sepol_ibendport_key_unpack(key, &ibdev_name, &port); head = policydb->ocontexts[OCON_IBENDPORT]; for (c = head; c; c = c->next) { const char *ibdev_name2 = c->u.ibendport.dev_name; int port2 = c->u.ibendport.port; if (port2 == port && (!strcmp(ibdev_name, ibdev_name2))) { if (ibendport_to_record(handle, policydb, c, response) < 0) goto err; return STATUS_SUCCESS; } } *response = NULL; return STATUS_SUCCESS; err: ERR(handle, "could not query ibendport, IB device: %s port %u", ibdev_name, port); return STATUS_ERR; } /* Load a ibendport into policy */ int sepol_ibendport_modify(sepol_handle_t *handle, sepol_policydb_t *p, const sepol_ibendport_key_t *key, const sepol_ibendport_t *data) { policydb_t *policydb = &p->p; ocontext_t *ibendport = NULL; int port; const char *ibdev_name; sepol_ibendport_key_unpack(key, &ibdev_name, &port); if (ibendport_from_record(handle, policydb, &ibendport, data) < 0) goto err; /* Attach to context list */ ibendport->next = policydb->ocontexts[OCON_IBENDPORT]; policydb->ocontexts[OCON_IBENDPORT] = ibendport; return STATUS_SUCCESS; err: ERR(handle, "could not load ibendport %s/%d", ibdev_name, port); if (ibendport) { context_destroy(&ibendport->context[0]); free(ibendport); } return STATUS_ERR; } int sepol_ibendport_iterate(sepol_handle_t *handle, const sepol_policydb_t *p, int (*fn)(const sepol_ibendport_t *ibendport, void *fn_arg), void *arg) { const policydb_t *policydb = &p->p; ocontext_t *c, *head; sepol_ibendport_t *ibendport = NULL; head = policydb->ocontexts[OCON_IBENDPORT]; for (c = head; c; c = c->next) { int status; if (ibendport_to_record(handle, policydb, c, &ibendport) < 0) goto err; /* Invoke handler */ status = fn(ibendport, arg); if (status < 0) goto err; sepol_ibendport_free(ibendport); ibendport = NULL; /* Handler requested exit */ if (status > 0) break; } return STATUS_SUCCESS; err: ERR(handle, "could not iterate over ibendports"); sepol_ibendport_free(ibendport); return STATUS_ERR; } libsepol-3.8.1/src/ibpkey_internal.h000066400000000000000000000002111476211737200174570ustar00rootroot00000000000000#ifndef _SEPOL_IBPKEY_INTERNAL_H_ #define _SEPOL_IBPKEY_INTERNAL_H_ #include #include #endif libsepol-3.8.1/src/ibpkey_record.c000066400000000000000000000172721476211737200171330ustar00rootroot00000000000000#include #include #include #include #include #include #include "ibpkey_internal.h" #include "context_internal.h" #include "debug.h" struct sepol_ibpkey { /* Subnet prefix */ uint64_t subnet_prefix; /* Low - High range. Same for single ibpkeys. */ int low, high; /* Context */ sepol_context_t *con; }; struct sepol_ibpkey_key { /* Subnet prefix */ uint64_t subnet_prefix; /* Low - High range. Same for single ibpkeys. */ int low, high; }; /* Converts a string represtation (subnet_prefix_str) * to a numeric representation (subnet_prefix_bytes) */ static int ibpkey_parse_subnet_prefix(sepol_handle_t *handle, const char *subnet_prefix_str, uint64_t *subnet_prefix) { struct in6_addr in_addr; if (inet_pton(AF_INET6, subnet_prefix_str, &in_addr) <= 0) { ERR(handle, "could not parse IPv6 address for ibpkey subnet prefix %s: %m", subnet_prefix_str); return STATUS_ERR; } memcpy(subnet_prefix, in_addr.s6_addr, sizeof(*subnet_prefix)); return STATUS_SUCCESS; } /* Converts a numeric representation (subnet_prefix_bytes) * to a string representation (subnet_prefix_str) */ static int ibpkey_expand_subnet_prefix(sepol_handle_t *handle, uint64_t subnet_prefix, char *subnet_prefix_str) { struct in6_addr addr; memset(&addr, 0, sizeof(struct in6_addr)); memcpy(&addr.s6_addr[0], &subnet_prefix, sizeof(subnet_prefix)); if (inet_ntop(AF_INET6, &addr, subnet_prefix_str, INET6_ADDRSTRLEN) == NULL) { ERR(handle, "could not expand IPv6 address to string: %m"); return STATUS_ERR; } return STATUS_SUCCESS; } /* Allocates a sufficiently large string (subnet_prefix) * for an IPV6 address for the subnet prefix */ static int ibpkey_alloc_subnet_prefix_string(sepol_handle_t *handle, char **subnet_prefix) { char *tmp_subnet_prefix = NULL; tmp_subnet_prefix = malloc(INET6_ADDRSTRLEN); if (!tmp_subnet_prefix) goto omem; *subnet_prefix = tmp_subnet_prefix; return STATUS_SUCCESS; omem: ERR(handle, "out of memory"); ERR(handle, "could not allocate string buffer for subnet_prefix"); return STATUS_ERR; } /* Key */ int sepol_ibpkey_key_create(sepol_handle_t *handle, const char *subnet_prefix, int low, int high, sepol_ibpkey_key_t **key_ptr) { sepol_ibpkey_key_t *tmp_key = (sepol_ibpkey_key_t *)malloc(sizeof(sepol_ibpkey_key_t)); if (!tmp_key) { ERR(handle, "out of memory, could not create ibpkey key"); goto omem; } if (ibpkey_parse_subnet_prefix(handle, subnet_prefix, &tmp_key->subnet_prefix) < 0) goto err; tmp_key->low = low; tmp_key->high = high; *key_ptr = tmp_key; return STATUS_SUCCESS; omem: ERR(handle, "out of memory"); err: sepol_ibpkey_key_free(tmp_key); ERR(handle, "could not create ibpkey key for subnet prefix%s, range %u, %u", subnet_prefix, low, high); return STATUS_ERR; } void sepol_ibpkey_key_unpack(const sepol_ibpkey_key_t *key, uint64_t *subnet_prefix, int *low, int *high) { *subnet_prefix = key->subnet_prefix; *low = key->low; *high = key->high; } int sepol_ibpkey_key_extract(sepol_handle_t *handle, const sepol_ibpkey_t *ibpkey, sepol_ibpkey_key_t **key_ptr) { char subnet_prefix_str[INET6_ADDRSTRLEN]; ibpkey_expand_subnet_prefix(handle, ibpkey->subnet_prefix, subnet_prefix_str); if (sepol_ibpkey_key_create (handle, subnet_prefix_str, ibpkey->low, ibpkey->high, key_ptr) < 0) { ERR(handle, "could not extract key from ibpkey %s %d:%d", subnet_prefix_str, ibpkey->low, ibpkey->high); return STATUS_ERR; } return STATUS_SUCCESS; } void sepol_ibpkey_key_free(sepol_ibpkey_key_t *key) { if (!key) return; free(key); } int sepol_ibpkey_compare(const sepol_ibpkey_t *ibpkey, const sepol_ibpkey_key_t *key) { if (ibpkey->subnet_prefix < key->subnet_prefix) return -1; if (key->subnet_prefix < ibpkey->subnet_prefix) return 1; if (ibpkey->low < key->low) return -1; if (key->low < ibpkey->low) return 1; if (ibpkey->high < key->high) return -1; if (key->high < ibpkey->high) return 1; return 0; } int sepol_ibpkey_compare2(const sepol_ibpkey_t *ibpkey, const sepol_ibpkey_t *ibpkey2) { if (ibpkey->subnet_prefix < ibpkey2->subnet_prefix) return -1; if (ibpkey2->subnet_prefix < ibpkey->subnet_prefix) return 1; if (ibpkey->low < ibpkey2->low) return -1; if (ibpkey2->low < ibpkey->low) return 1; if (ibpkey->high < ibpkey2->high) return -1; if (ibpkey2->high < ibpkey->high) return 1; return 0; } /* Pkey */ int sepol_ibpkey_get_low(const sepol_ibpkey_t *ibpkey) { return ibpkey->low; } int sepol_ibpkey_get_high(const sepol_ibpkey_t *ibpkey) { return ibpkey->high; } void sepol_ibpkey_set_pkey(sepol_ibpkey_t *ibpkey, int pkey_num) { ibpkey->low = pkey_num; ibpkey->high = pkey_num; } void sepol_ibpkey_set_range(sepol_ibpkey_t *ibpkey, int low, int high) { ibpkey->low = low; ibpkey->high = high; } int sepol_ibpkey_get_subnet_prefix(sepol_handle_t *handle, const sepol_ibpkey_t *ibpkey, char **subnet_prefix) { char *tmp_subnet_prefix = NULL; if (ibpkey_alloc_subnet_prefix_string(handle, &tmp_subnet_prefix) < 0) goto err; if (ibpkey_expand_subnet_prefix(handle, ibpkey->subnet_prefix, tmp_subnet_prefix) < 0) goto err; *subnet_prefix = tmp_subnet_prefix; return STATUS_SUCCESS; err: free(tmp_subnet_prefix); ERR(handle, "could not get ibpkey subnet_prefix"); return STATUS_ERR; } /* Subnet prefix */ uint64_t sepol_ibpkey_get_subnet_prefix_bytes(const sepol_ibpkey_t *ibpkey) { return ibpkey->subnet_prefix; } int sepol_ibpkey_set_subnet_prefix(sepol_handle_t *handle, sepol_ibpkey_t *ibpkey, const char *subnet_prefix_str) { uint64_t tmp = 0; if (ibpkey_parse_subnet_prefix(handle, subnet_prefix_str, &tmp) < 0) goto err; ibpkey->subnet_prefix = tmp; return STATUS_SUCCESS; err: ERR(handle, "could not set ibpkey subnet prefix to %s", subnet_prefix_str); return STATUS_ERR; } void sepol_ibpkey_set_subnet_prefix_bytes(sepol_ibpkey_t *ibpkey, uint64_t subnet_prefix) { ibpkey->subnet_prefix = subnet_prefix; } /* Create */ int sepol_ibpkey_create(sepol_handle_t *handle, sepol_ibpkey_t **ibpkey) { sepol_ibpkey_t *tmp_ibpkey = (sepol_ibpkey_t *)malloc(sizeof(sepol_ibpkey_t)); if (!tmp_ibpkey) { ERR(handle, "out of memory, could not create ibpkey record"); return STATUS_ERR; } tmp_ibpkey->subnet_prefix = 0; tmp_ibpkey->low = 0; tmp_ibpkey->high = 0; tmp_ibpkey->con = NULL; *ibpkey = tmp_ibpkey; return STATUS_SUCCESS; } /* Deep copy clone */ int sepol_ibpkey_clone(sepol_handle_t *handle, const sepol_ibpkey_t *ibpkey, sepol_ibpkey_t **ibpkey_ptr) { sepol_ibpkey_t *new_ibpkey = NULL; if (sepol_ibpkey_create(handle, &new_ibpkey) < 0) goto err; new_ibpkey->subnet_prefix = ibpkey->subnet_prefix; new_ibpkey->low = ibpkey->low; new_ibpkey->high = ibpkey->high; if (ibpkey->con && (sepol_context_clone(handle, ibpkey->con, &new_ibpkey->con) < 0)) goto err; *ibpkey_ptr = new_ibpkey; return STATUS_SUCCESS; err: ERR(handle, "could not clone ibpkey record"); sepol_ibpkey_free(new_ibpkey); return STATUS_ERR; } /* Destroy */ void sepol_ibpkey_free(sepol_ibpkey_t *ibpkey) { if (!ibpkey) return; sepol_context_free(ibpkey->con); free(ibpkey); } /* Context */ sepol_context_t *sepol_ibpkey_get_con(const sepol_ibpkey_t *ibpkey) { return ibpkey->con; } int sepol_ibpkey_set_con(sepol_handle_t *handle, sepol_ibpkey_t *ibpkey, sepol_context_t *con) { sepol_context_t *newcon; if (sepol_context_clone(handle, con, &newcon) < 0) { ERR(handle, "out of memory, could not set ibpkey context"); return STATUS_ERR; } sepol_context_free(ibpkey->con); ibpkey->con = newcon; return STATUS_SUCCESS; } libsepol-3.8.1/src/ibpkeys.c000066400000000000000000000137601476211737200157560ustar00rootroot00000000000000#include #include #include #include "debug.h" #include "context.h" #include "handle.h" #include #include #include "ibpkey_internal.h" /* Create a low level ibpkey structure from * a high level representation */ static int ibpkey_from_record(sepol_handle_t *handle, const policydb_t *policydb, ocontext_t **ibpkey, const sepol_ibpkey_t *data) { ocontext_t *tmp_ibpkey = NULL; context_struct_t *tmp_con = NULL; char *subnet_prefix_buf = NULL; int low = sepol_ibpkey_get_low(data); int high = sepol_ibpkey_get_high(data); tmp_ibpkey = (ocontext_t *)calloc(1, sizeof(*tmp_ibpkey)); if (!tmp_ibpkey) goto omem; tmp_ibpkey->u.ibpkey.subnet_prefix = sepol_ibpkey_get_subnet_prefix_bytes(data); /* Pkey range */ tmp_ibpkey->u.ibpkey.low_pkey = low; tmp_ibpkey->u.ibpkey.high_pkey = high; if (tmp_ibpkey->u.ibpkey.low_pkey > tmp_ibpkey->u.ibpkey.high_pkey) { ERR(handle, "low ibpkey %d exceeds high ibpkey %d", tmp_ibpkey->u.ibpkey.low_pkey, tmp_ibpkey->u.ibpkey.high_pkey); goto err; } /* Context */ if (context_from_record(handle, policydb, &tmp_con, sepol_ibpkey_get_con(data)) < 0) goto err; context_cpy(&tmp_ibpkey->context[0], tmp_con); context_destroy(tmp_con); free(tmp_con); tmp_con = NULL; *ibpkey = tmp_ibpkey; return STATUS_SUCCESS; omem: ERR(handle, "out of memory"); err: if (tmp_ibpkey) { context_destroy(&tmp_ibpkey->context[0]); free(tmp_ibpkey); } context_destroy(tmp_con); free(tmp_con); free(subnet_prefix_buf); ERR(handle, "could not create ibpkey structure"); return STATUS_ERR; } static int ibpkey_to_record(sepol_handle_t *handle, const policydb_t *policydb, ocontext_t *ibpkey, sepol_ibpkey_t **record) { context_struct_t *con = &ibpkey->context[0]; sepol_context_t *tmp_con = NULL; sepol_ibpkey_t *tmp_record = NULL; if (sepol_ibpkey_create(handle, &tmp_record) < 0) goto err; sepol_ibpkey_set_subnet_prefix_bytes(tmp_record, ibpkey->u.ibpkey.subnet_prefix); sepol_ibpkey_set_range(tmp_record, ibpkey->u.ibpkey.low_pkey, ibpkey->u.ibpkey.high_pkey); if (context_to_record(handle, policydb, con, &tmp_con) < 0) goto err; if (sepol_ibpkey_set_con(handle, tmp_record, tmp_con) < 0) goto err; sepol_context_free(tmp_con); *record = tmp_record; return STATUS_SUCCESS; err: ERR(handle, "could not convert ibpkey to record"); sepol_context_free(tmp_con); sepol_ibpkey_free(tmp_record); return STATUS_ERR; } /* Return the number of ibpkeys */ extern int sepol_ibpkey_count(sepol_handle_t *handle __attribute__ ((unused)), const sepol_policydb_t *p, unsigned int *response) { unsigned int count = 0; ocontext_t *c, *head; const policydb_t *policydb = &p->p; head = policydb->ocontexts[OCON_IBPKEY]; for (c = head; c; c = c->next) count++; *response = count; return STATUS_SUCCESS; } /* Check if a ibpkey exists */ int sepol_ibpkey_exists(sepol_handle_t *handle __attribute__ ((unused)), const sepol_policydb_t *p, const sepol_ibpkey_key_t *key, int *response) { const policydb_t *policydb = &p->p; ocontext_t *c, *head; int low, high; uint64_t subnet_prefix; sepol_ibpkey_key_unpack(key, &subnet_prefix, &low, &high); head = policydb->ocontexts[OCON_IBPKEY]; for (c = head; c; c = c->next) { uint64_t subnet_prefix2 = c->u.ibpkey.subnet_prefix; uint16_t low2 = c->u.ibpkey.low_pkey; uint16_t high2 = c->u.ibpkey.high_pkey; if (low2 == low && high2 == high && subnet_prefix == subnet_prefix2) { *response = 1; return STATUS_SUCCESS; } } *response = 0; return STATUS_SUCCESS; } /* Query a ibpkey */ int sepol_ibpkey_query(sepol_handle_t *handle, const sepol_policydb_t *p, const sepol_ibpkey_key_t *key, sepol_ibpkey_t **response) { const policydb_t *policydb = &p->p; ocontext_t *c, *head; int low, high; uint64_t subnet_prefix; sepol_ibpkey_key_unpack(key, &subnet_prefix, &low, &high); head = policydb->ocontexts[OCON_IBPKEY]; for (c = head; c; c = c->next) { uint64_t subnet_prefix2 = c->u.ibpkey.subnet_prefix; int low2 = c->u.ibpkey.low_pkey; int high2 = c->u.ibpkey.high_pkey; if (low2 == low && high2 == high && subnet_prefix == subnet_prefix2) { if (ibpkey_to_record(handle, policydb, c, response) < 0) goto err; return STATUS_SUCCESS; } } *response = NULL; return STATUS_SUCCESS; err: ERR(handle, "could not query ibpkey subnet prefix: %#" PRIx64 " range %u - %u exists", subnet_prefix, low, high); return STATUS_ERR; } /* Load a ibpkey into policy */ int sepol_ibpkey_modify(sepol_handle_t *handle, sepol_policydb_t *p, const sepol_ibpkey_key_t *key, const sepol_ibpkey_t *data) { policydb_t *policydb = &p->p; ocontext_t *ibpkey = NULL; int low, high; uint64_t subnet_prefix; sepol_ibpkey_key_unpack(key, &subnet_prefix, &low, &high); if (ibpkey_from_record(handle, policydb, &ibpkey, data) < 0) goto err; /* Attach to context list */ ibpkey->next = policydb->ocontexts[OCON_IBPKEY]; policydb->ocontexts[OCON_IBPKEY] = ibpkey; return STATUS_SUCCESS; err: ERR(handle, "could not load ibpkey subnet prefix: %#" PRIx64 " range %u - %u exists", subnet_prefix, low, high); if (ibpkey) { context_destroy(&ibpkey->context[0]); free(ibpkey); } return STATUS_ERR; } int sepol_ibpkey_iterate(sepol_handle_t *handle, const sepol_policydb_t *p, int (*fn)(const sepol_ibpkey_t *ibpkey, void *fn_arg), void *arg) { const policydb_t *policydb = &p->p; ocontext_t *c, *head; sepol_ibpkey_t *ibpkey = NULL; head = policydb->ocontexts[OCON_IBPKEY]; for (c = head; c; c = c->next) { int status; if (ibpkey_to_record(handle, policydb, c, &ibpkey) < 0) goto err; /* Invoke handler */ status = fn(ibpkey, arg); if (status < 0) goto err; sepol_ibpkey_free(ibpkey); ibpkey = NULL; /* Handler requested exit */ if (status > 0) break; } return STATUS_SUCCESS; err: ERR(handle, "could not iterate over ibpkeys"); sepol_ibpkey_free(ibpkey); return STATUS_ERR; } libsepol-3.8.1/src/iface_internal.h000066400000000000000000000002111476211737200172430ustar00rootroot00000000000000#ifndef _SEPOL_IFACE_INTERNAL_H_ #define _SEPOL_IFACE_INTERNAL_H_ #include #include #endif libsepol-3.8.1/src/iface_record.c000066400000000000000000000105421476211737200167100ustar00rootroot00000000000000#include #include #include "iface_internal.h" #include "context_internal.h" #include "debug.h" struct sepol_iface { /* Interface name */ char *name; /* Interface context */ sepol_context_t *netif_con; /* Message context */ sepol_context_t *netmsg_con; }; struct sepol_iface_key { /* Interface name */ char *name; }; /* Key */ int sepol_iface_key_create(sepol_handle_t * handle, const char *name, sepol_iface_key_t ** key_ptr) { sepol_iface_key_t *tmp_key = (sepol_iface_key_t *) malloc(sizeof(sepol_iface_key_t)); if (!tmp_key) { ERR(handle, "out of memory, could not create interface key"); return STATUS_ERR; } tmp_key->name = strdup(name); if (!tmp_key->name) { ERR(handle, "out of memory, could not create interface key"); free(tmp_key); return STATUS_ERR; } *key_ptr = tmp_key; return STATUS_SUCCESS; } void sepol_iface_key_unpack(const sepol_iface_key_t * key, const char **name) { *name = key->name; } int sepol_iface_key_extract(sepol_handle_t * handle, const sepol_iface_t * iface, sepol_iface_key_t ** key_ptr) { if (sepol_iface_key_create(handle, iface->name, key_ptr) < 0) { ERR(handle, "could not extract key from " "interface %s", iface->name); return STATUS_ERR; } return STATUS_SUCCESS; } void sepol_iface_key_free(sepol_iface_key_t * key) { if (!key) return; free(key->name); free(key); } int sepol_iface_compare(const sepol_iface_t * iface, const sepol_iface_key_t * key) { return strcmp(iface->name, key->name); } int sepol_iface_compare2(const sepol_iface_t * iface, const sepol_iface_t * iface2) { return strcmp(iface->name, iface2->name); } /* Create */ int sepol_iface_create(sepol_handle_t * handle, sepol_iface_t ** iface) { sepol_iface_t *tmp_iface = (sepol_iface_t *) malloc(sizeof(sepol_iface_t)); if (!tmp_iface) { ERR(handle, "out of memory, could not create " "interface record"); return STATUS_ERR; } tmp_iface->name = NULL; tmp_iface->netif_con = NULL; tmp_iface->netmsg_con = NULL; *iface = tmp_iface; return STATUS_SUCCESS; } /* Name */ const char *sepol_iface_get_name(const sepol_iface_t * iface) { return iface->name; } int sepol_iface_set_name(sepol_handle_t * handle, sepol_iface_t * iface, const char *name) { char *tmp_name = strdup(name); if (!tmp_name) { ERR(handle, "out of memory, " "could not set interface name"); return STATUS_ERR; } free(iface->name); iface->name = tmp_name; return STATUS_SUCCESS; } /* Interface Context */ sepol_context_t *sepol_iface_get_ifcon(const sepol_iface_t * iface) { return iface->netif_con; } int sepol_iface_set_ifcon(sepol_handle_t * handle, sepol_iface_t * iface, sepol_context_t * con) { sepol_context_t *newcon; if (sepol_context_clone(handle, con, &newcon) < 0) { ERR(handle, "out of memory, could not set interface context"); return STATUS_ERR; } sepol_context_free(iface->netif_con); iface->netif_con = newcon; return STATUS_SUCCESS; } /* Message Context */ sepol_context_t *sepol_iface_get_msgcon(const sepol_iface_t * iface) { return iface->netmsg_con; } int sepol_iface_set_msgcon(sepol_handle_t * handle, sepol_iface_t * iface, sepol_context_t * con) { sepol_context_t *newcon; if (sepol_context_clone(handle, con, &newcon) < 0) { ERR(handle, "out of memory, could not set message context"); return STATUS_ERR; } sepol_context_free(iface->netmsg_con); iface->netmsg_con = newcon; return STATUS_SUCCESS; } /* Deep copy clone */ int sepol_iface_clone(sepol_handle_t * handle, const sepol_iface_t * iface, sepol_iface_t ** iface_ptr) { sepol_iface_t *new_iface = NULL; if (sepol_iface_create(handle, &new_iface) < 0) goto err; if (sepol_iface_set_name(handle, new_iface, iface->name) < 0) goto err; if (iface->netif_con && (sepol_context_clone (handle, iface->netif_con, &new_iface->netif_con) < 0)) goto err; if (iface->netmsg_con && (sepol_context_clone (handle, iface->netmsg_con, &new_iface->netmsg_con) < 0)) goto err; *iface_ptr = new_iface; return STATUS_SUCCESS; err: ERR(handle, "could not clone interface record"); sepol_iface_free(new_iface); return STATUS_ERR; } /* Destroy */ void sepol_iface_free(sepol_iface_t * iface) { if (!iface) return; free(iface->name); sepol_context_free(iface->netif_con); sepol_context_free(iface->netmsg_con); free(iface); } libsepol-3.8.1/src/interfaces.c000066400000000000000000000136721476211737200164350ustar00rootroot00000000000000#include #include "debug.h" #include "context.h" #include "handle.h" #include #include #include "iface_internal.h" /* Create a low level structure from record */ static int iface_from_record(sepol_handle_t * handle, const policydb_t * policydb, ocontext_t ** iface, const sepol_iface_t * record) { ocontext_t *tmp_iface = NULL; context_struct_t *tmp_con = NULL; tmp_iface = (ocontext_t *) calloc(1, sizeof(ocontext_t)); if (!tmp_iface) goto omem; /* Name */ tmp_iface->u.name = strdup(sepol_iface_get_name(record)); if (!tmp_iface->u.name) goto omem; /* Interface Context */ if (context_from_record(handle, policydb, &tmp_con, sepol_iface_get_ifcon(record)) < 0) goto err; context_cpy(&tmp_iface->context[0], tmp_con); context_destroy(tmp_con); free(tmp_con); tmp_con = NULL; /* Message Context */ if (context_from_record(handle, policydb, &tmp_con, sepol_iface_get_msgcon(record)) < 0) goto err; context_cpy(&tmp_iface->context[1], tmp_con); context_destroy(tmp_con); free(tmp_con); tmp_con = NULL; *iface = tmp_iface; return STATUS_SUCCESS; omem: ERR(handle, "out of memory"); err: if (tmp_iface != NULL) { free(tmp_iface->u.name); context_destroy(&tmp_iface->context[0]); context_destroy(&tmp_iface->context[1]); free(tmp_iface); } context_destroy(tmp_con); free(tmp_con); ERR(handle, "error creating interface structure"); return STATUS_ERR; } static int iface_to_record(sepol_handle_t * handle, const policydb_t * policydb, ocontext_t * iface, sepol_iface_t ** record) { char *name = iface->u.name; context_struct_t *ifcon = &iface->context[0]; context_struct_t *msgcon = &iface->context[1]; sepol_context_t *tmp_con = NULL; sepol_iface_t *tmp_record = NULL; if (sepol_iface_create(handle, &tmp_record) < 0) goto err; if (sepol_iface_set_name(handle, tmp_record, name) < 0) goto err; if (context_to_record(handle, policydb, ifcon, &tmp_con) < 0) goto err; if (sepol_iface_set_ifcon(handle, tmp_record, tmp_con) < 0) goto err; sepol_context_free(tmp_con); tmp_con = NULL; if (context_to_record(handle, policydb, msgcon, &tmp_con) < 0) goto err; if (sepol_iface_set_msgcon(handle, tmp_record, tmp_con) < 0) goto err; sepol_context_free(tmp_con); tmp_con = NULL; *record = tmp_record; return STATUS_SUCCESS; err: ERR(handle, "could not convert interface %s to record", name); sepol_context_free(tmp_con); sepol_iface_free(tmp_record); return STATUS_ERR; } /* Check if an interface exists */ int sepol_iface_exists(sepol_handle_t * handle __attribute__ ((unused)), const sepol_policydb_t * p, const sepol_iface_key_t * key, int *response) { const policydb_t *policydb = &p->p; ocontext_t *c, *head; const char *name; sepol_iface_key_unpack(key, &name); head = policydb->ocontexts[OCON_NETIF]; for (c = head; c; c = c->next) { if (!strcmp(name, c->u.name)) { *response = 1; return STATUS_SUCCESS; } } *response = 0; return STATUS_SUCCESS; } /* Query an interface */ int sepol_iface_query(sepol_handle_t * handle, const sepol_policydb_t * p, const sepol_iface_key_t * key, sepol_iface_t ** response) { const policydb_t *policydb = &p->p; ocontext_t *c, *head; const char *name; sepol_iface_key_unpack(key, &name); head = policydb->ocontexts[OCON_NETIF]; for (c = head; c; c = c->next) { if (!strcmp(name, c->u.name)) { if (iface_to_record(handle, policydb, c, response) < 0) goto err; return STATUS_SUCCESS; } } *response = NULL; return STATUS_SUCCESS; err: ERR(handle, "could not query interface %s", name); return STATUS_ERR; } /* Load an interface into policy */ int sepol_iface_modify(sepol_handle_t * handle, sepol_policydb_t * p, const sepol_iface_key_t * key, const sepol_iface_t * data) { policydb_t *policydb = &p->p; ocontext_t *head, *prev, *c, *iface = NULL; const char *name; sepol_iface_key_unpack(key, &name); if (iface_from_record(handle, policydb, &iface, data) < 0) goto err; prev = NULL; head = policydb->ocontexts[OCON_NETIF]; for (c = head; c; c = c->next) { if (!strcmp(name, c->u.name)) { /* Replace */ iface->next = c->next; if (prev == NULL) policydb->ocontexts[OCON_NETIF] = iface; else prev->next = iface; free(c->u.name); context_destroy(&c->context[0]); context_destroy(&c->context[1]); free(c); return STATUS_SUCCESS; } prev = c; } /* Attach to context list */ iface->next = policydb->ocontexts[OCON_NETIF]; policydb->ocontexts[OCON_NETIF] = iface; return STATUS_SUCCESS; err: ERR(handle, "error while loading interface %s", name); if (iface != NULL) { free(iface->u.name); context_destroy(&iface->context[0]); context_destroy(&iface->context[1]); free(iface); } return STATUS_ERR; } /* Return the number of interfaces */ extern int sepol_iface_count(sepol_handle_t * handle __attribute__ ((unused)), const sepol_policydb_t * p, unsigned int *response) { unsigned int count = 0; ocontext_t *c, *head; const policydb_t *policydb = &p->p; head = policydb->ocontexts[OCON_NETIF]; for (c = head; c != NULL; c = c->next) count++; *response = count; return STATUS_SUCCESS; } int sepol_iface_iterate(sepol_handle_t * handle, const sepol_policydb_t * p, int (*fn) (const sepol_iface_t * iface, void *fn_arg), void *arg) { const policydb_t *policydb = &p->p; ocontext_t *c, *head; sepol_iface_t *iface = NULL; head = policydb->ocontexts[OCON_NETIF]; for (c = head; c; c = c->next) { int status; if (iface_to_record(handle, policydb, c, &iface) < 0) goto err; /* Invoke handler */ status = fn(iface, arg); if (status < 0) goto err; sepol_iface_free(iface); iface = NULL; /* Handler requested exit */ if (status > 0) break; } return STATUS_SUCCESS; err: ERR(handle, "could not iterate over interfaces"); sepol_iface_free(iface); return STATUS_ERR; } libsepol-3.8.1/src/kernel_to_cil.c000066400000000000000000002133211476211737200171140ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include #include #ifndef IPPROTO_DCCP #define IPPROTO_DCCP 33 #endif #ifndef IPPROTO_SCTP #define IPPROTO_SCTP 132 #endif #include #include #include #include #include #include #include #include #include "debug.h" #include "kernel_to_common.h" static char *cond_expr_to_str(struct policydb *pdb, struct cond_expr *expr) { struct cond_expr *curr; struct strs *stack; char *new_val; char *str = NULL; int rc; rc = strs_stack_init(&stack); if (rc != 0) { goto exit; } for (curr = expr; curr != NULL; curr = curr->next) { if (curr->expr_type == COND_BOOL) { char *val1 = pdb->p_bool_val_to_name[curr->boolean - 1]; new_val = create_str("%s", val1); } else { const char *op; uint32_t num_params; char *val1 = NULL; char *val2 = NULL; switch(curr->expr_type) { case COND_NOT: op = "not"; num_params = 1; break; case COND_OR: op = "or"; num_params = 2; break; case COND_AND: op = "and"; num_params = 2; break; case COND_XOR: op = "xor"; num_params = 2; break; case COND_EQ: op = "eq"; num_params = 2; break; case COND_NEQ: op = "neq"; num_params = 2; break; default: ERR(NULL, "Unknown conditional operator: %i", curr->expr_type); goto exit; } if (num_params == 2) { val2 = strs_stack_pop(stack); if (!val2) { ERR(NULL, "Invalid conditional expression"); goto exit; } } val1 = strs_stack_pop(stack); if (!val1) { ERR(NULL, "Invalid conditional expression"); free(val2); goto exit; } if (num_params == 2) { new_val = create_str("(%s %s %s)", op, val1, val2); free(val2); } else { new_val = create_str("(%s %s)", op, val1); } free(val1); } if (!new_val) { ERR(NULL, "Invalid conditional expression"); goto exit; } rc = strs_stack_push(stack, new_val); if (rc != 0) { ERR(NULL, "Out of memory"); goto exit; } } new_val = strs_stack_pop(stack); if (!new_val || !strs_stack_empty(stack)) { ERR(NULL, "Invalid conditional expression"); goto exit; } str = new_val; strs_stack_destroy(&stack); return str; exit: if (stack) { while ((new_val = strs_stack_pop(stack)) != NULL) { free(new_val); } strs_stack_destroy(&stack); } return NULL; } static char *constraint_expr_to_str(struct policydb *pdb, struct constraint_expr *expr, int *use_mls) { struct constraint_expr *curr; struct strs *stack = NULL; char *new_val = NULL; const char *op; char *str = NULL; int rc; *use_mls = 0; rc = strs_stack_init(&stack); if (rc != 0) { goto exit; } for (curr = expr; curr; curr = curr->next) { if (curr->expr_type == CEXPR_ATTR || curr->expr_type == CEXPR_NAMES) { const char *attr1 = NULL; const char *attr2 = NULL; switch (curr->op) { case CEXPR_EQ: op = "eq"; break; case CEXPR_NEQ: op = "neq"; break; case CEXPR_DOM: op = "dom"; break; case CEXPR_DOMBY: op = "domby"; break; case CEXPR_INCOMP: op = "incomp"; break; default: ERR(NULL, "Unknown constraint operator: %i", curr->op); goto exit; } switch (curr->attr) { case CEXPR_USER: attr1 ="u1"; attr2 ="u2"; break; case CEXPR_USER | CEXPR_TARGET: attr1 ="u2"; attr2 =""; break; case CEXPR_USER | CEXPR_XTARGET: attr1 ="u3"; attr2 =""; break; case CEXPR_ROLE: attr1 ="r1"; attr2 ="r2"; break; case CEXPR_ROLE | CEXPR_TARGET: attr1 ="r2"; attr2 =""; break; case CEXPR_ROLE | CEXPR_XTARGET: attr1 ="r3"; attr2 =""; break; case CEXPR_TYPE: attr1 ="t1"; attr2 ="t2"; break; case CEXPR_TYPE | CEXPR_TARGET: attr1 ="t2"; attr2 =""; break; case CEXPR_TYPE | CEXPR_XTARGET: attr1 ="t3"; attr2 =""; break; case CEXPR_L1L2: attr1 ="l1"; attr2 ="l2"; break; case CEXPR_L1H2: attr1 ="l1"; attr2 ="h2"; break; case CEXPR_H1L2: attr1 ="h1"; attr2 ="l2"; break; case CEXPR_H1H2: attr1 ="h1"; attr2 ="h2"; break; case CEXPR_L1H1: attr1 ="l1"; attr2 ="h1"; break; case CEXPR_L2H2: attr1 ="l2"; attr2 ="h2"; break; default: ERR(NULL, "Unknown constraint attribute: %i", curr->attr); goto exit; } if (curr->attr >= CEXPR_L1L2) { *use_mls = 1; } if (curr->expr_type == CEXPR_ATTR) { new_val = create_str("(%s %s %s)", op, attr1, attr2); } else { char *names = NULL; if (curr->attr & CEXPR_TYPE) { struct type_set *ts = curr->type_names; names = ebitmap_to_str(&ts->types, pdb->p_type_val_to_name, 1); } else if (curr->attr & CEXPR_USER) { names = ebitmap_to_str(&curr->names, pdb->p_user_val_to_name, 1); } else if (curr->attr & CEXPR_ROLE) { names = ebitmap_to_str(&curr->names, pdb->p_role_val_to_name, 1); } if (!names) { names = strdup("NO_IDENTIFIER"); if (!names) { ERR(NULL, "Out of memory"); goto exit; } } if (strchr(names, ' ')) { new_val = create_str("(%s %s (%s))", op, attr1, names); } else { new_val = create_str("(%s %s %s)", op, attr1, names); } free(names); } } else { uint32_t num_params; char *val1 = NULL; char *val2 = NULL; switch (curr->expr_type) { case CEXPR_NOT: op = "not"; num_params = 1; break; case CEXPR_AND: op = "and"; num_params = 2; break; case CEXPR_OR: op = "or"; num_params = 2; break; default: ERR(NULL, "Unknown constraint expression type: %i", curr->expr_type); goto exit; } if (num_params == 2) { val2 = strs_stack_pop(stack); if (!val2) { ERR(NULL, "Invalid constraint expression"); goto exit; } } val1 = strs_stack_pop(stack); if (!val1) { ERR(NULL, "Invalid constraint expression"); goto exit; } if (num_params == 2) { new_val = create_str("(%s %s %s)", op, val1, val2); free(val2); } else { new_val = create_str("(%s %s)", op, val1); } free(val1); } if (!new_val) { goto exit; } rc = strs_stack_push(stack, new_val); if (rc != 0) { ERR(NULL, "Out of memory"); goto exit; } } new_val = strs_stack_pop(stack); if (!new_val || !strs_stack_empty(stack)) { ERR(NULL, "Invalid constraint expression"); goto exit; } str = new_val; strs_stack_destroy(&stack); return str; exit: if (stack) { while ((new_val = strs_stack_pop(stack)) != NULL) { free(new_val); } strs_stack_destroy(&stack); } return NULL; } static int class_constraint_rules_to_strs(struct policydb *pdb, char *classkey, class_datum_t *class, struct constraint_node *constraint_rules, struct strs *mls_list, struct strs *non_mls_list) { int rc = 0; struct constraint_node *curr; char *expr = NULL; int is_mls; char *perms; const char *key_word; struct strs *strs; for (curr = constraint_rules; curr != NULL; curr = curr->next) { if (curr->permissions == 0) { continue; } expr = constraint_expr_to_str(pdb, curr->expr, &is_mls); if (!expr) { rc = -1; goto exit; } perms = sepol_av_to_string(pdb, class->s.value, curr->permissions); if (!perms) { ERR(NULL, "Failed to generate permission string"); rc = -1; goto exit; } if (*perms == '\0') { ERR(NULL, "No permissions in permission string"); free(perms); rc = -1; goto exit; } if (is_mls) { key_word = "mlsconstrain"; strs = mls_list; } else { key_word = "constrain"; strs = non_mls_list; } rc = strs_create_and_add(strs, "(%s (%s (%s)) %s)", key_word, classkey, perms+1, expr); free(perms); free(expr); if (rc != 0) { goto exit; } } return 0; exit: ERR(NULL, "Error gathering constraint rules"); return rc; } static int class_validatetrans_rules_to_strs(struct policydb *pdb, char *classkey, struct constraint_node *validatetrans_rules, struct strs *mls_list, struct strs *non_mls_list) { struct constraint_node *curr; char *expr = NULL; int is_mls; const char *key_word; struct strs *strs; int rc = 0; for (curr = validatetrans_rules; curr != NULL; curr = curr->next) { expr = constraint_expr_to_str(pdb, curr->expr, &is_mls); if (!expr) { rc = -1; goto exit; } if (is_mls) { key_word = "mlsvalidatetrans"; strs = mls_list; } else { key_word = "validatetrans"; strs = non_mls_list; } rc = strs_create_and_add(strs, "(%s %s %s)", key_word, classkey, expr); free(expr); if (rc != 0) { goto exit; } } exit: return rc; } static int constraint_rules_to_strs(struct policydb *pdb, struct strs *mls_strs, struct strs *non_mls_strs) { class_datum_t *class; char *name; unsigned i; int rc = 0; for (i=0; i < pdb->p_classes.nprim; i++) { class = pdb->class_val_to_struct[i]; if (!class) continue; if (class->constraints) { name = pdb->p_class_val_to_name[i]; rc = class_constraint_rules_to_strs(pdb, name, class, class->constraints, mls_strs, non_mls_strs); if (rc != 0) { goto exit; } } } strs_sort(mls_strs); strs_sort(non_mls_strs); exit: return rc; } static int validatetrans_rules_to_strs(struct policydb *pdb, struct strs *mls_strs, struct strs *non_mls_strs) { class_datum_t *class; char *name; unsigned i; int rc = 0; for (i=0; i < pdb->p_classes.nprim; i++) { class = pdb->class_val_to_struct[i]; if (!class) continue; if (class->validatetrans) { name = pdb->p_class_val_to_name[i]; rc = class_validatetrans_rules_to_strs(pdb, name, class->validatetrans, mls_strs, non_mls_strs); if (rc != 0) { goto exit; } } } strs_sort(mls_strs); strs_sort(non_mls_strs); exit: return rc; } static int write_handle_unknown_to_cil(FILE *out, struct policydb *pdb) { const char *action; switch (pdb->handle_unknown) { case SEPOL_DENY_UNKNOWN: action = "deny"; break; case SEPOL_REJECT_UNKNOWN: action = "reject"; break; case SEPOL_ALLOW_UNKNOWN: action = "allow"; break; default: ERR(NULL, "Unknown value for handle-unknown: %i", pdb->handle_unknown); return -1; } sepol_printf(out, "(handleunknown %s)\n", action); return 0; } static char *class_or_common_perms_to_str(symtab_t *permtab) { struct strs *strs; char *perms = NULL; int rc; rc = strs_init(&strs, permtab->nprim); if (rc != 0) { goto exit; } rc = hashtab_map(permtab->table, hashtab_ordered_to_strs, strs); if (rc != 0) { goto exit; } if (strs_num_items(strs) > 0) { perms = strs_to_str(strs); } exit: strs_destroy(&strs); return perms; } static int write_class_decl_rules_to_cil(FILE *out, struct policydb *pdb) { class_datum_t *class; common_datum_t *common; int *used; char *name, *perms; unsigned i; int rc = 0; /* class */ for (i=0; i < pdb->p_classes.nprim; i++) { class = pdb->class_val_to_struct[i]; if (!class) continue; name = pdb->p_class_val_to_name[i]; perms = class_or_common_perms_to_str(&class->permissions); if (perms) { sepol_printf(out, "(class %s (%s))\n", name, perms); free(perms); } else { sepol_printf(out, "(class %s ())\n", name); } } /* classorder */ sepol_printf(out, "(classorder ("); name = NULL; for (i=0; i < pdb->p_classes.nprim; i++) { if (name) { sepol_printf(out, "%s ", name); } name = pdb->p_class_val_to_name[i]; } if (name) { sepol_printf(out, "%s", name); } sepol_printf(out, "))\n"); /* classcommon */ for (i=0; i < pdb->p_classes.nprim; i++) { class = pdb->class_val_to_struct[i]; if (!class) continue; name = pdb->p_class_val_to_name[i]; if (class->comkey != NULL) { sepol_printf(out, "(classcommon %s %s)\n", name, class->comkey); } } /* common */ used = calloc(pdb->p_commons.nprim, sizeof(*used)); if (!used) { ERR(NULL, "Out of memory"); rc = -1; goto exit; } for (i=0; i < pdb->p_classes.nprim; i++) { class = pdb->class_val_to_struct[i]; if (!class) continue; name = class->comkey; if (name != NULL) { common = hashtab_search(pdb->p_commons.table, name); if (!common) { rc = -1; free(used); goto exit; } /* Only write common rule once */ if (!used[common->s.value-1]) { perms = class_or_common_perms_to_str(&common->permissions); if (!perms) { rc = -1; free(perms); free(used); goto exit; } sepol_printf(out, "(common %s (%s))\n", name, perms); free(perms); used[common->s.value-1] = 1; } } } free(used); exit: if (rc != 0) { ERR(NULL, "Error writing class rules to CIL"); } return rc; } static int write_sids_to_cil(FILE *out, const char *const *sid_to_str, unsigned num_sids, struct ocontext *isids) { struct ocontext *isid; struct strs *strs; char *sid; char *prev; char unknown[18]; unsigned i; int rc; rc = strs_init(&strs, num_sids+1); if (rc != 0) { goto exit; } for (isid = isids; isid != NULL; isid = isid->next) { i = isid->sid[0]; if (i < num_sids && sid_to_str[i]) { sid = strdup(sid_to_str[i]); } else { snprintf(unknown, 18, "%s%u", "UNKNOWN", i); sid = strdup(unknown); } if (!sid) { ERR(NULL, "Out of memory"); rc = -1; goto exit; } rc = strs_add_at_index(strs, sid, i); if (rc != 0) { free(sid); goto exit; } } for (i=0; itarget_platform == SEPOL_TARGET_SELINUX) { rc = write_sids_to_cil(out, selinux_sid_to_str, SELINUX_SID_SZ, pdb->ocontexts[0]); } else if (pdb->target_platform == SEPOL_TARGET_XEN) { rc = write_sids_to_cil(out, xen_sid_to_str, XEN_SID_SZ, pdb->ocontexts[0]); } else { ERR(NULL, "Unknown target platform: %i", pdb->target_platform); rc = -1; } return rc; } static int write_default_user_to_cil(FILE *out, char *class_name, class_datum_t *class) { const char *dft; switch (class->default_user) { case DEFAULT_SOURCE: dft = "source"; break; case DEFAULT_TARGET: dft = "target"; break; default: ERR(NULL, "Unknown default role value: %i", class->default_user); return -1; } sepol_printf(out, "(defaultuser %s %s)\n", class_name, dft); return 0; } static int write_default_role_to_cil(FILE *out, char *class_name, class_datum_t *class) { const char *dft; switch (class->default_role) { case DEFAULT_SOURCE: dft = "source"; break; case DEFAULT_TARGET: dft = "target"; break; default: ERR(NULL, "Unknown default role value: %i", class->default_role); return -1; } sepol_printf(out, "(defaultrole %s %s)\n", class_name, dft); return 0; } static int write_default_type_to_cil(FILE *out, char *class_name, class_datum_t *class) { const char *dft; switch (class->default_type) { case DEFAULT_SOURCE: dft = "source"; break; case DEFAULT_TARGET: dft = "target"; break; default: ERR(NULL, "Unknown default type value: %i", class->default_type); return -1; } sepol_printf(out, "(defaulttype %s %s)\n", class_name, dft); return 0; } static int write_default_range_to_cil(FILE *out, char *class_name, class_datum_t *class) { const char *dft; switch (class->default_range) { case DEFAULT_SOURCE_LOW: dft = "source low"; break; case DEFAULT_SOURCE_HIGH: dft = "source high"; break; case DEFAULT_SOURCE_LOW_HIGH: dft = "source low-high"; break; case DEFAULT_TARGET_LOW: dft = "target low"; break; case DEFAULT_TARGET_HIGH: dft = "target high"; break; case DEFAULT_TARGET_LOW_HIGH: dft = "target low-high"; break; case DEFAULT_GLBLUB: dft = "glblub"; break; default: ERR(NULL, "Unknown default type value: %i", class->default_range); return -1; } sepol_printf(out, "(defaultrange %s %s)\n", class_name, dft); return 0; } static int write_default_rules_to_cil(FILE *out, struct policydb *pdb) { class_datum_t *class; unsigned i; int rc = 0; /* default_user */ for (i=0; i < pdb->p_classes.nprim; i++) { class = pdb->class_val_to_struct[i]; if (!class) continue; if (class->default_user != 0) { rc = write_default_user_to_cil(out, pdb->p_class_val_to_name[i], class); if (rc != 0) { goto exit; } } } /* default_role */ for (i=0; i < pdb->p_classes.nprim; i++) { class = pdb->class_val_to_struct[i]; if (!class) continue; if (class->default_role != 0) { rc = write_default_role_to_cil(out, pdb->p_class_val_to_name[i], class); if (rc != 0) { goto exit; } } } /* default_type */ for (i=0; i < pdb->p_classes.nprim; i++) { class = pdb->class_val_to_struct[i]; if (!class) continue; if (class->default_type != 0) { rc = write_default_type_to_cil(out, pdb->p_class_val_to_name[i], class); if (rc != 0) { goto exit; } } } if (!pdb->mls) { return 0; } /* default_range */ for (i=0; i < pdb->p_classes.nprim; i++) { class = pdb->class_val_to_struct[i]; if (!class) continue; if (class->default_range) { rc = write_default_range_to_cil(out, pdb->p_class_val_to_name[i], class); if (rc != 0) { goto exit; } } } exit: if (rc != 0) { ERR(NULL, "Error writing default rules to CIL"); } return rc; } static void write_default_mls_level(FILE *out) { sepol_printf(out, "(sensitivity s0)\n"); sepol_printf(out, "(sensitivityorder (s0))\n"); sepol_printf(out, "(level %s (s0))\n", DEFAULT_LEVEL); } static int map_count_sensitivity_aliases(__attribute__((unused)) char *key, void *data, void *args) { level_datum_t *sens = data; unsigned *count = args; if (sens->isalias) (*count)++; return SEPOL_OK; } static int map_sensitivity_aliases_to_strs(char *key, void *data, void *args) { level_datum_t *sens = data; struct strs *strs = args; int rc = 0; if (sens->isalias) { rc = strs_add(strs, key); } return rc; } static int write_sensitivity_rules_to_cil(FILE *out, struct policydb *pdb) { level_datum_t *level; char *prev, *name, *actual; struct strs *strs = NULL; unsigned i, num = 0; int rc = 0; /* sensitivities */ for (i=0; i < pdb->p_levels.nprim; i++) { name = pdb->p_sens_val_to_name[i]; sepol_printf(out, "(sensitivity %s)\n", name); } /* sensitivityorder */ sepol_printf(out, "(sensitivityorder ("); prev = NULL; for (i=0; i < pdb->p_levels.nprim; i++) { name = pdb->p_sens_val_to_name[i]; if (prev) { sepol_printf(out, "%s ", prev); } prev = name; } if (prev) { sepol_printf(out, "%s", prev); } sepol_printf(out, "))\n"); rc = hashtab_map(pdb->p_levels.table, map_count_sensitivity_aliases, &num); if (rc != 0) { goto exit; } if (num == 0) { /* No aliases, so skip sensitivity alias rules */ rc = 0; goto exit; } rc = strs_init(&strs, num); if (rc != 0) { goto exit; } rc = hashtab_map(pdb->p_levels.table, map_sensitivity_aliases_to_strs, strs); if (rc != 0) { goto exit; } strs_sort(strs); /* sensitivity aliases */ for (i=0; i < num; i++) { name = strs_read_at_index(strs, i); sepol_printf(out, "(sensitivityalias %s)\n", name); } /* sensitivity aliases to actual */ for (i=0; i < num; i++) { name = strs_read_at_index(strs, i); level = hashtab_search(pdb->p_levels.table, name); if (!level) { rc = -1; goto exit; } actual = pdb->p_sens_val_to_name[level->level->sens - 1]; sepol_printf(out, "(sensitivityaliasactual %s %s)\n", name, actual); } exit: strs_destroy(&strs); if (rc != 0) { ERR(NULL, "Error writing sensitivity rules to CIL"); } return rc; } static int map_count_category_aliases(__attribute__((unused)) char *key, void *data, void *args) { cat_datum_t *cat = data; unsigned *count = args; if (cat->isalias) (*count)++; return SEPOL_OK; } static int map_category_aliases_to_strs(char *key, void *data, void *args) { cat_datum_t *cat = data; struct strs *strs = args; int rc = 0; if (cat->isalias) { rc = strs_add(strs, key); } return rc; } static int write_category_rules_to_cil(FILE *out, struct policydb *pdb) { cat_datum_t *cat; char *prev, *name, *actual; struct strs *strs = NULL; unsigned i, num = 0; int rc = 0; /* categories */ for (i=0; i < pdb->p_cats.nprim; i++) { name = pdb->p_cat_val_to_name[i]; sepol_printf(out, "(category %s)\n", name); } /* categoryorder */ sepol_printf(out, "(categoryorder ("); prev = NULL; for (i=0; i < pdb->p_cats.nprim; i++) { name = pdb->p_cat_val_to_name[i]; if (prev) { sepol_printf(out, "%s ", prev); } prev = name; } if (prev) { sepol_printf(out, "%s", prev); } sepol_printf(out, "))\n"); rc = hashtab_map(pdb->p_cats.table, map_count_category_aliases, &num); if (rc != 0) { goto exit; } if (num == 0) { /* No aliases, so skip category alias rules */ rc = 0; goto exit; } rc = strs_init(&strs, num); if (rc != 0) { goto exit; } rc = hashtab_map(pdb->p_cats.table, map_category_aliases_to_strs, strs); if (rc != 0) { goto exit; } strs_sort(strs); /* category aliases */ for (i=0; i < num; i++) { name = strs_read_at_index(strs, i); sepol_printf(out, "(categoryalias %s)\n", name); } /* category aliases to actual */ for (i=0; i < num; i++) { name = strs_read_at_index(strs, i); cat = hashtab_search(pdb->p_cats.table, name); if (!cat) { rc = -1; goto exit; } actual = pdb->p_cat_val_to_name[cat->s.value - 1]; sepol_printf(out, "(categoryaliasactual %s %s)\n", name, actual); } exit: strs_destroy(&strs); if (rc != 0) { ERR(NULL, "Error writing category rules to CIL"); } return rc; } static size_t cats_ebitmap_len(struct ebitmap *cats, char **val_to_name) { struct ebitmap_node *node; uint32_t i, start, range; size_t len = 0; range = 0; ebitmap_for_each_positive_bit(cats, node, i) { if (range == 0) start = i; range++; if (ebitmap_get_bit(cats, i+1)) continue; len += strlen(val_to_name[start]); if (range > 2) { len += strlen(val_to_name[i-1]) + strlen("(range ) "); } else if (range == 2) { len += strlen(val_to_name[i-1]) + 2; } else if (range == 1) { len += 1; } range = 0; } if (len > 0) { len += 2; /* For '(' and ')'. '\0' overwrites last ' ' */ } return len; } static char *cats_ebitmap_to_str(struct ebitmap *cats, char **val_to_name) { struct ebitmap_node *node; uint32_t i, start, range; char *catsbuf = NULL, *p; int len, remaining; remaining = (int)cats_ebitmap_len(cats, val_to_name); if (remaining == 0) { goto exit; } catsbuf = malloc(remaining); if (!catsbuf) { goto exit; } p = catsbuf; *p++ = '('; remaining--; range = 0; ebitmap_for_each_positive_bit(cats, node, i) { if (range == 0) start = i; range++; if (ebitmap_get_bit(cats, i+1)) continue; if (range > 1) { if (range == 2) { len = snprintf(p, remaining, "%s %s ", val_to_name[start], val_to_name[i]); } else { len = snprintf(p, remaining, "(range %s %s) ", val_to_name[start], val_to_name[i]); } } else { len = snprintf(p, remaining, "%s ", val_to_name[start]); } if (len < 0 || len >= remaining) { goto exit; } p += len; remaining -= len; range = 0; } *(p-1) = ')'; /* Remove trailing ' ' */ *p = '\0'; return catsbuf; exit: free(catsbuf); return NULL; } static int write_sensitivitycategory_rules_to_cil(FILE *out, struct policydb *pdb) { level_datum_t *level; char *name, *cats; unsigned i; int rc = 0; /* sensitivities */ for (i=0; i < pdb->p_levels.nprim; i++) { name = pdb->p_sens_val_to_name[i]; if (!name) continue; level = hashtab_search(pdb->p_levels.table, name); if (!level) { rc = -1; goto exit; } if (level->isalias) continue; if (!ebitmap_is_empty(&level->level->cat)) { cats = cats_ebitmap_to_str(&level->level->cat, pdb->p_cat_val_to_name); sepol_printf(out, "(sensitivitycategory %s %s)\n", name, cats); free(cats); } } exit: if (rc != 0) { ERR(NULL, "Error writing sensitivitycategory rules to CIL"); } return rc; } static int write_mls_rules_to_cil(FILE *out, struct policydb *pdb) { int rc = 0; if (!pdb->mls) { sepol_printf(out, "(mls false)\n"); /* CIL requires MLS, even if the kernel binary won't have it */ write_default_mls_level(out); return 0; } sepol_printf(out, "(mls true)\n"); rc = write_sensitivity_rules_to_cil(out, pdb); if (rc != 0) { goto exit; } rc = write_category_rules_to_cil(out, pdb); if (rc != 0) { goto exit; } rc = write_sensitivitycategory_rules_to_cil(out, pdb); if (rc != 0) { goto exit; } exit: if (rc != 0) { ERR(NULL, "Error writing mls rules to CIL"); } return rc; } static int write_polcap_rules_to_cil(FILE *out, struct policydb *pdb) { struct strs *strs; struct ebitmap_node *node; const char *name; uint32_t i; int rc = 0; rc = strs_init(&strs, 32); if (rc != 0) { goto exit; } ebitmap_for_each_positive_bit(&pdb->policycaps, node, i) { name = sepol_polcap_getname(i); if (name == NULL) { ERR(NULL, "Unknown policy capability id: %i", i); rc = -1; goto exit; } rc = strs_create_and_add(strs, "(policycap %s)", name); if (rc != 0) { goto exit; } } strs_sort(strs); strs_write_each(strs, out); exit: strs_free_all(strs); strs_destroy(&strs); if (rc != 0) { ERR(NULL, "Error writing polcap rules to CIL"); } return rc; } static int write_type_attributes_to_cil(FILE *out, struct policydb *pdb) { type_datum_t *type; char *name; struct strs *strs; unsigned i, num; int rc = 0; rc = strs_init(&strs, pdb->p_types.nprim); if (rc != 0) { goto exit; } for (i=0; i < pdb->p_types.nprim; i++) { type = pdb->type_val_to_struct[i]; if (type && type->flavor == TYPE_ATTRIB) { rc = strs_add(strs, pdb->p_type_val_to_name[i]); if (rc != 0) { goto exit; } } } strs_sort(strs); num = strs_num_items(strs); for (i = 0; i < num; i++) { name = strs_read_at_index(strs, i); if (!name) { rc = -1; goto exit; } sepol_printf(out, "(typeattribute %s)\n", name); } exit: strs_destroy(&strs); if (rc != 0) { ERR(NULL, "Error writing typeattribute rules to CIL"); } return rc; } static int write_role_attributes_to_cil(FILE *out, struct policydb *pdb) { role_datum_t *role; char *name; struct strs *strs; unsigned i, num; int rc = 0; rc = strs_init(&strs, pdb->p_roles.nprim); if (rc != 0) { goto exit; } for (i=0; i < pdb->p_roles.nprim; i++) { role = pdb->role_val_to_struct[i]; if (role && role->flavor == ROLE_ATTRIB) { rc = strs_add(strs, pdb->p_role_val_to_name[i]); if (rc != 0) { goto exit; } } } strs_sort(strs); num = strs_num_items(strs); for (i=0; istate ? "true" : "false"; return strs_create_and_add(strs, "(boolean %s %s)", key, value); } static int write_boolean_decl_rules_to_cil(FILE *out, struct policydb *pdb) { struct strs *strs; int rc = 0; rc = strs_init(&strs, 32); if (rc != 0) { goto exit; } rc = hashtab_map(pdb->p_bools.table, map_boolean_to_strs, strs); if (rc != 0) { goto exit; } strs_sort(strs); strs_write_each(strs, out); exit: strs_free_all(strs); strs_destroy(&strs); if (rc != 0) { ERR(NULL, "Error writing boolean declarations to CIL"); } return rc; } static int write_type_decl_rules_to_cil(FILE *out, struct policydb *pdb) { type_datum_t *type; struct strs *strs; char *name; unsigned i, num; int rc = 0; rc = strs_init(&strs, pdb->p_types.nprim); if (rc != 0) { goto exit; } for (i=0; i < pdb->p_types.nprim; i++) { type = pdb->type_val_to_struct[i]; if (type && type->flavor == TYPE_TYPE && type->primary) { rc = strs_add(strs, pdb->p_type_val_to_name[i]); if (rc != 0) { goto exit; } } } strs_sort(strs); num = strs_num_items(strs); for (i=0; iprimary == 0 && datum->flavor == TYPE_TYPE) (*count)++; return SEPOL_OK; } static int map_type_aliases_to_strs(char *key, void *data, void *args) { type_datum_t *datum = data; struct strs *strs = args; int rc = 0; if (datum->primary == 0 && datum->flavor == TYPE_TYPE) rc = strs_add(strs, key); return rc; } static int write_type_alias_rules_to_cil(FILE *out, struct policydb *pdb) { type_datum_t *alias; struct strs *strs = NULL; char *name; char *type; unsigned i, num = 0; int rc = 0; rc = hashtab_map(pdb->p_types.table, map_count_type_aliases, &num); if (rc != 0) { goto exit; } rc = strs_init(&strs, num); if (rc != 0) { goto exit; } rc = hashtab_map(pdb->p_types.table, map_type_aliases_to_strs, strs); if (rc != 0) { goto exit; } strs_sort(strs); for (i=0; ip_types.table, name); if (!alias) { rc = -1; goto exit; } type = pdb->p_type_val_to_name[alias->s.value - 1]; sepol_printf(out, "(typealiasactual %s %s)\n", name, type); } exit: strs_destroy(&strs); if (rc != 0) { ERR(NULL, "Error writing type alias rules to CIL"); } return rc; } static int write_type_bounds_rules_to_cil(FILE *out, struct policydb *pdb) { type_datum_t *type; struct strs *strs; char *parent; char *child; unsigned i, num; int rc = 0; rc = strs_init(&strs, pdb->p_types.nprim); if (rc != 0) { goto exit; } for (i=0; i < pdb->p_types.nprim; i++) { type = pdb->type_val_to_struct[i]; if (type && type->flavor == TYPE_TYPE) { if (type->bounds > 0) { rc = strs_add(strs, pdb->p_type_val_to_name[i]); if (rc != 0) { goto exit; } } } } strs_sort(strs); num = strs_num_items(strs); for (i=0; ip_types.table, child); if (!type) { rc = -1; goto exit; } parent = pdb->p_type_val_to_name[type->bounds - 1]; sepol_printf(out, "(typebounds %s %s)\n", parent, child); } exit: strs_destroy(&strs); if (rc != 0) { ERR(NULL, "Error writing type bounds rules to CIL"); } return rc; } static int write_type_attribute_sets_to_cil(FILE *out, struct policydb *pdb) { type_datum_t *attr; struct strs *strs; ebitmap_t *typemap; char *name, *types; unsigned i; int rc; rc = strs_init(&strs, pdb->p_types.nprim); if (rc != 0) { goto exit; } for (i=0; i < pdb->p_types.nprim; i++) { attr = pdb->type_val_to_struct[i]; if (!attr || attr->flavor != TYPE_ATTRIB) continue; name = pdb->p_type_val_to_name[i]; typemap = &pdb->attr_type_map[i]; if (ebitmap_is_empty(typemap)) continue; types = ebitmap_to_str(typemap, pdb->p_type_val_to_name, 1); if (!types) { rc = -1; goto exit; } rc = strs_create_and_add(strs, "(typeattributeset %s (%s))", name, types); free(types); if (rc != 0) { goto exit; } } strs_sort(strs); strs_write_each(strs, out); exit: strs_free_all(strs); strs_destroy(&strs); if (rc != 0) { ERR(NULL, "Error writing typeattributeset rules to CIL"); } return rc; } static int write_type_permissive_rules_to_cil(FILE *out, struct policydb *pdb) { struct strs *strs; char *name; struct ebitmap_node *node; unsigned i, num; int rc = 0; rc = strs_init(&strs, pdb->p_types.nprim); if (rc != 0) { goto exit; } ebitmap_for_each_positive_bit(&pdb->permissive_map, node, i) { rc = strs_add(strs, pdb->p_type_val_to_name[i-1]); if (rc != 0) { goto exit; } } strs_sort(strs); num = strs_num_items(strs); for (i=0; ispecified != AVTAB_XPERMS_IOCTLFUNCTION) && (xperms->specified != AVTAB_XPERMS_IOCTLDRIVER) && (xperms->specified != AVTAB_XPERMS_NLMSG)) { return NULL; } retry: if (__builtin_mul_overflow(size, 2, &size)) goto err; p = realloc(buffer, size); if (!p) goto err; buffer = p; remaining = size; in_range = 0; for (bit = 0; bit < sizeof(xperms->perms)*8; bit++) { len = 0; if (!xperm_test(bit, xperms->perms)) continue; if (in_range && next_bit_in_range(bit, xperms->perms)) { /* continue until high value found */ continue; } else if (next_bit_in_range(bit, xperms->perms)) { /* low value */ low_bit = bit; in_range = 1; continue; } if ((xperms->specified == AVTAB_XPERMS_IOCTLFUNCTION) || (xperms->specified == AVTAB_XPERMS_NLMSG)) { value = xperms->driver<<8 | bit; if (in_range) { low_value = xperms->driver<<8 | low_bit; len = snprintf(p, remaining, " (range 0x%hx 0x%hx)", low_value, value); in_range = 0; } else { len = snprintf(p, remaining, " 0x%hx", value); } } else if (xperms->specified == AVTAB_XPERMS_IOCTLDRIVER) { value = bit << 8; if (in_range) { low_value = low_bit << 8; len = snprintf(p, remaining, " (range 0x%hx 0x%hx)", low_value, (uint16_t) (value|0xff)); in_range = 0; } else { len = snprintf(p, remaining, " (range 0x%hx 0x%hx)", value, (uint16_t) (value|0xff)); } } if (len < 0) goto err; if ((size_t)len >= remaining) goto retry; p += len; remaining -= len; } if (remaining < 2) goto retry; buffer[0] = '('; *p++ = ')'; *p = '\0'; return buffer; err: free(buffer); return NULL; } static char *avtab_node_to_str(struct policydb *pdb, avtab_key_t *key, avtab_datum_t *datum) { uint32_t data = datum->data; type_datum_t *type; const char *flavor, *tgt; char *src, *class, *perms, *new, *xperm; char *rule = NULL; switch (0xFFF & key->specified) { case AVTAB_ALLOWED: flavor = "allow"; break; case AVTAB_AUDITALLOW: flavor = "auditallow"; break; case AVTAB_AUDITDENY: flavor = "dontaudit"; data = ~data; break; case AVTAB_XPERMS_ALLOWED: flavor = "allowx"; break; case AVTAB_XPERMS_AUDITALLOW: flavor = "auditallowx"; break; case AVTAB_XPERMS_DONTAUDIT: flavor = "dontauditx"; break; case AVTAB_TRANSITION: flavor = "typetransition"; break; case AVTAB_MEMBER: flavor = "typemember"; break; case AVTAB_CHANGE: flavor = "typechange"; break; default: ERR(NULL, "Unknown avtab type: %i", key->specified); goto exit; } src = pdb->p_type_val_to_name[key->source_type - 1]; tgt = pdb->p_type_val_to_name[key->target_type - 1]; if (key->source_type == key->target_type && !(key->specified & AVTAB_TYPE)) { type = pdb->type_val_to_struct[key->source_type - 1]; if (type->flavor != TYPE_ATTRIB) { tgt = "self"; } } class = pdb->p_class_val_to_name[key->target_class - 1]; if (key->specified & AVTAB_AV) { perms = sepol_av_to_string(pdb, key->target_class, data); if (perms == NULL) { ERR(NULL, "Failed to generate permission string"); goto exit; } if (*perms == '\0') { ERR(NULL, "No permissions in permission string"); free(perms); goto exit; } rule = create_str("(%s %s %s (%s (%s)))", flavor, src, tgt, class, perms+1); free(perms); } else if (key->specified & AVTAB_XPERMS) { perms = xperms_to_str(datum->xperms); if (perms == NULL) { ERR(NULL, "Failed to generate extended permission string"); goto exit; } if (datum->xperms->specified == AVTAB_XPERMS_IOCTLFUNCTION || datum->xperms->specified == AVTAB_XPERMS_IOCTLDRIVER) { xperm = (char *) "ioctl"; } else if (datum->xperms->specified == AVTAB_XPERMS_NLMSG) { xperm = (char *) "nlmsg"; } else { ERR(NULL, "Unknown extended permission"); goto exit; } rule = create_str("(%s %s %s (%s %s (%s)))", flavor, src, tgt, xperm, class, perms); free(perms); } else { new = pdb->p_type_val_to_name[data - 1]; rule = create_str("(%s %s %s %s %s)", flavor, src, tgt, class, new); } if (!rule) { goto exit; } return rule; exit: return NULL; } struct map_avtab_args { struct policydb *pdb; uint32_t flavor; struct strs *strs; }; static int map_avtab_write_helper(avtab_key_t *key, avtab_datum_t *datum, void *args) { struct map_avtab_args *map_args = args; uint32_t flavor = map_args->flavor; struct policydb *pdb = map_args->pdb; struct strs *strs = map_args->strs; char *rule; int rc = 0; if (key->specified & flavor) { rule = avtab_node_to_str(pdb, key, datum); if (!rule) { rc = -1; goto exit; } rc = strs_add(strs, rule); if (rc != 0) { free(rule); goto exit; } } exit: return rc; } static int write_avtab_flavor_to_cil(FILE *out, struct policydb *pdb, uint32_t flavor, int indent) { struct map_avtab_args args; struct strs *strs; int rc = 0; rc = strs_init(&strs, 1000); if (rc != 0) { goto exit; } args.pdb = pdb; args.flavor = flavor; args.strs = strs; rc = avtab_map(&pdb->te_avtab, map_avtab_write_helper, &args); if (rc != 0) { goto exit; } strs_sort(strs); strs_write_each_indented(strs, out, indent); exit: strs_free_all(strs); strs_destroy(&strs); return rc; } static int write_avtab_to_cil(FILE *out, struct policydb *pdb, int indent) { unsigned i; int rc = 0; for (i = 0; i < AVTAB_FLAVORS_SZ; i++) { rc = write_avtab_flavor_to_cil(out, pdb, avtab_flavors[i], indent); if (rc != 0) { goto exit; } } exit: if (rc != 0) { ERR(NULL, "Error writing avtab rules to CIL"); } return rc; } struct map_filename_trans_args { struct policydb *pdb; struct strs *strs; }; static int map_filename_trans_to_str(hashtab_key_t key, void *data, void *arg) { filename_trans_key_t *ft = (filename_trans_key_t *)key; filename_trans_datum_t *datum = data; struct map_filename_trans_args *map_args = arg; struct policydb *pdb = map_args->pdb; struct strs *strs = map_args->strs; char *src, *tgt, *class, *filename, *new; struct ebitmap_node *node; uint32_t bit; int rc; tgt = pdb->p_type_val_to_name[ft->ttype - 1]; class = pdb->p_class_val_to_name[ft->tclass - 1]; filename = ft->name; do { new = pdb->p_type_val_to_name[datum->otype - 1]; ebitmap_for_each_positive_bit(&datum->stypes, node, bit) { src = pdb->p_type_val_to_name[bit]; rc = strs_create_and_add(strs, "(typetransition %s %s %s \"%s\" %s)", src, tgt, class, filename, new); if (rc) return rc; } datum = datum->next; } while (datum); return 0; } static int write_filename_trans_rules_to_cil(FILE *out, struct policydb *pdb) { struct map_filename_trans_args args; struct strs *strs; int rc = 0; rc = strs_init(&strs, 100); if (rc != 0) { goto exit; } args.pdb = pdb; args.strs = strs; rc = hashtab_map(pdb->filename_trans, map_filename_trans_to_str, &args); if (rc != 0) { goto exit; } strs_sort(strs); strs_write_each(strs, out); exit: strs_free_all(strs); strs_destroy(&strs); if (rc != 0) { ERR(NULL, "Error writing filename typetransition rules to CIL"); } return rc; } static char *level_to_str(struct policydb *pdb, struct mls_level *level) { ebitmap_t *cats = &level->cat; char *level_str = NULL; char *sens_str = pdb->p_sens_val_to_name[level->sens - 1]; char *cats_str; if (!ebitmap_is_empty(cats)) { cats_str = cats_ebitmap_to_str(cats, pdb->p_cat_val_to_name); level_str = create_str("(%s %s)", sens_str, cats_str); free(cats_str); } else { level_str = create_str("(%s)", sens_str); } return level_str; } static char *range_to_str(struct policydb *pdb, mls_range_t *range) { char *low = NULL; char *high = NULL; char *range_str = NULL; low = level_to_str(pdb, &range->level[0]); if (!low) { goto exit; } high = level_to_str(pdb, &range->level[1]); if (!high) { goto exit; } range_str = create_str("(%s %s)", low, high); exit: free(low); free(high); return range_str; } struct map_range_trans_args { struct policydb *pdb; struct strs *strs; }; static int map_range_trans_to_str(hashtab_key_t key, void *data, void *arg) { range_trans_t *rt = (range_trans_t *)key; mls_range_t *mls_range = data; struct map_range_trans_args *map_args = arg; struct policydb *pdb = map_args->pdb; struct strs *strs = map_args->strs; char *src, *tgt, *class, *range; int rc; src = pdb->p_type_val_to_name[rt->source_type - 1]; tgt = pdb->p_type_val_to_name[rt->target_type - 1]; class = pdb->p_class_val_to_name[rt->target_class - 1]; range = range_to_str(pdb, mls_range); if (!range) { rc = -1; goto exit; } rc = strs_create_and_add(strs, "(rangetransition %s %s %s %s)", src, tgt, class, range); free(range); if (rc != 0) { goto exit; } exit: return rc; } static int write_range_trans_rules_to_cil(FILE *out, struct policydb *pdb) { struct map_range_trans_args args; struct strs *strs; int rc = 0; rc = strs_init(&strs, 100); if (rc != 0) { goto exit; } args.pdb = pdb; args.strs = strs; rc = hashtab_map(pdb->range_tr, map_range_trans_to_str, &args); if (rc != 0) { goto exit; } strs_sort(strs); strs_write_each(strs, out); exit: strs_free_all(strs); strs_destroy(&strs); if (rc != 0) { ERR(NULL, "Error writing range transition rules to CIL"); } return rc; } static int write_cond_av_list_to_cil(FILE *out, struct policydb *pdb, cond_av_list_t *cond_list, int indent) { cond_av_list_t *cond_av; avtab_ptr_t node; uint32_t flavor; avtab_key_t *key; avtab_datum_t *datum; struct strs *strs; char *rule; unsigned i; int rc; for (i = 0; i < AVTAB_FLAVORS_SZ; i++) { flavor = avtab_flavors[i]; rc = strs_init(&strs, 64); if (rc != 0) { goto exit; } for (cond_av = cond_list; cond_av != NULL; cond_av = cond_av->next) { node = cond_av->node; key = &node->key; datum = &node->datum; if (key->specified & flavor) { rule = avtab_node_to_str(pdb, key, datum); if (!rule) { rc = -1; goto exit; } rc = strs_add(strs, rule); if (rc != 0) { free(rule); goto exit; } } } strs_sort(strs); strs_write_each_indented(strs, out, indent); strs_free_all(strs); strs_destroy(&strs); } return 0; exit: strs_free_all(strs); strs_destroy(&strs); return rc; } struct cond_data { char *expr; struct cond_node *cond; }; static int cond_node_cmp(const void *a, const void *b) { const struct cond_data *aa = a; const struct cond_data *bb = b; return strcmp(aa->expr, bb->expr); } static int write_cond_nodes_to_cil(FILE *out, struct policydb *pdb) { struct cond_data *cond_data; char *expr; struct cond_node *cond; unsigned i, num = 0; int rc = 0; for (cond = pdb->cond_list; cond != NULL; cond = cond->next) { num++; } cond_data = calloc(num, sizeof(struct cond_data)); if (!cond_data) { rc = -1; goto exit; } i = 0; for (cond = pdb->cond_list; cond != NULL; cond = cond->next) { cond_data[i].cond = cond; expr = cond_expr_to_str(pdb, cond->expr); if (!expr) { num = i; goto exit; } cond_data[i].expr = expr; i++; } qsort(cond_data, num, sizeof(*cond_data), cond_node_cmp); for (i=0; itrue_list != NULL) { sepol_indent(out, 1); sepol_printf(out, "(true\n"); rc = write_cond_av_list_to_cil(out, pdb, cond->true_list, 2); if (rc != 0) { goto exit; } sepol_indent(out, 1); sepol_printf(out, ")\n"); } if (cond->false_list != NULL) { sepol_indent(out, 1); sepol_printf(out, "(false\n"); rc = write_cond_av_list_to_cil(out, pdb, cond->false_list, 2); if (rc != 0) { goto exit; } sepol_indent(out, 1); sepol_printf(out, ")\n"); } sepol_printf(out, ")\n"); } exit: if (cond_data) { for (i=0; ip_roles.nprim); if (rc != 0) { goto exit; } for (i=0; i < pdb->p_roles.nprim; i++) { role = pdb->role_val_to_struct[i]; if (role && role->flavor == ROLE_ROLE) { rc = strs_add(strs, pdb->p_role_val_to_name[i]); if (rc != 0) { goto exit; } } } strs_sort(strs); num = strs_num_items(strs); for (i=0; ip_roles.table, child); if (!role) { rc = -1; goto exit; } if (role->bounds > 0) { parent = pdb->p_role_val_to_name[role->bounds - 1]; sepol_printf(out, "(rolebounds %s %s)\n", parent, child); } } for (i=0; ip_roles.table, name); if (!role) { rc = -1; goto exit; } types = &role->types.types; if (types && !ebitmap_is_empty(types)) { rc = strs_init(&type_strs, pdb->p_types.nprim); if (rc != 0) { goto exit; } rc = ebitmap_to_strs(types, type_strs, pdb->p_type_val_to_name); if (rc != 0) { strs_destroy(&type_strs); goto exit; } strs_sort(type_strs); num_types = strs_num_items(type_strs); for (j=0; jp_types.nprim); if (rc != 0) { goto exit; } for (i=0; i < pdb->p_types.nprim; i++) { type_datum = pdb->type_val_to_struct[i]; if (type_datum && type_datum->flavor == TYPE_TYPE && type_datum->primary) { rc = strs_add(strs, pdb->p_type_val_to_name[i]); if (rc != 0) { goto exit; } } } strs_sort(strs); num = strs_num_items(strs); for (i=0; irole_tr; struct strs *strs; char *role, *type, *class, *new; int rc = 0; rc = strs_init(&strs, 32); if (rc != 0) { goto exit; } while (curr) { role = pdb->p_role_val_to_name[curr->role - 1]; type = pdb->p_type_val_to_name[curr->type - 1]; class = pdb->p_class_val_to_name[curr->tclass - 1]; new = pdb->p_role_val_to_name[curr->new_role - 1]; rc = strs_create_and_add(strs, "(roletransition %s %s %s %s)", role, type, class, new); if (rc != 0) { goto exit; } curr = curr->next; } strs_sort(strs); strs_write_each(strs, out); exit: strs_free_all(strs); strs_destroy(&strs); if (rc != 0) { ERR(NULL, "Error writing role transition rules to CIL"); } return rc; } static int write_role_allow_rules_to_cil(FILE *out, struct policydb *pdb) { role_allow_t *curr = pdb->role_allow; struct strs *strs; char *role, *new; int rc = 0; rc = strs_init(&strs, 32); if (rc != 0) { goto exit; } while (curr) { role = pdb->p_role_val_to_name[curr->role - 1]; new = pdb->p_role_val_to_name[curr->new_role - 1]; rc = strs_create_and_add(strs, "(roleallow %s %s)", role, new); if (rc != 0) { goto exit; } curr = curr->next; } strs_sort(strs); strs_write_each(strs, out); exit: strs_free_all(strs); strs_destroy(&strs); if (rc != 0) { ERR(NULL, "Error writing role allow rules to CIL"); } return rc; } static int write_user_decl_rules_to_cil(FILE *out, struct policydb *pdb) { struct user_datum *user; struct strs *strs, *role_strs; char *name, *role, *level, *range; struct ebitmap *roles; unsigned i, j, num, num_roles; int rc = 0; rc = strs_init(&strs, pdb->p_users.nprim); if (rc != 0) { goto exit; } for (i=0; i < pdb->p_users.nprim; i++) { if (!pdb->p_user_val_to_name[i]) continue; rc = strs_add(strs, pdb->p_user_val_to_name[i]); if (rc != 0) { goto exit; } } strs_sort(strs); num = strs_num_items(strs); for (i=0; ip_users.table, name); if (!user) { rc = -1; goto exit; } roles = &user->roles.roles; if (roles && !ebitmap_is_empty(roles)) { rc = strs_init(&role_strs, pdb->p_roles.nprim); if (rc != 0) { goto exit; } rc = ebitmap_to_strs(roles, role_strs, pdb->p_role_val_to_name); if (rc != 0) { strs_destroy(&role_strs); goto exit; } rc = strs_add(role_strs, (char *)DEFAULT_OBJECT); if (rc != 0) { strs_destroy(&role_strs); goto exit; } strs_sort(role_strs); num_roles = strs_num_items(role_strs); for (j=0; jp_users.table, name); if (!user) { rc = -1; goto exit; } sepol_printf(out, "(userlevel %s ", name); if (pdb->mls) { level = level_to_str(pdb, &user->exp_dfltlevel); if (!level) { rc = -1; goto exit; } sepol_printf(out, "%s", level); free(level); } else { sepol_printf(out, "%s", DEFAULT_LEVEL); } sepol_printf(out, ")\n"); } for (i=0; ip_users.table, name); if (!user) { rc = -1; goto exit; } sepol_printf(out, "(userrange %s ", name); if (pdb->mls) { range = range_to_str(pdb, &user->exp_range); if (!range) { rc = -1; goto exit; } sepol_printf(out, "%s", range); free(range); } else { sepol_printf(out, "(%s %s)", DEFAULT_LEVEL, DEFAULT_LEVEL); } sepol_printf(out, ")\n"); } exit: if (strs) strs_destroy(&strs); if (rc != 0) { ERR(NULL, "Error writing user declarations to CIL"); } return rc; } static char *context_to_str(struct policydb *pdb, struct context_struct *con) { char *user, *role, *type, *range; char *ctx = NULL; user = pdb->p_user_val_to_name[con->user - 1]; role = pdb->p_role_val_to_name[con->role - 1]; type = pdb->p_type_val_to_name[con->type - 1]; if (pdb->mls) { range = range_to_str(pdb, &con->range); } else { range = create_str("(%s %s)", DEFAULT_LEVEL, DEFAULT_LEVEL); } if (!range) { goto exit; } ctx = create_str("(%s %s %s %s)", user, role, type, range); free(range); exit: return ctx; } static int write_sid_context_rules_to_cil(FILE *out, struct policydb *pdb, const char *const *sid_to_str, unsigned num_sids) { struct ocontext *isid; struct strs *strs; char *sid; char unknown[18]; char *ctx, *rule; unsigned i; int rc = -1; rc = strs_init(&strs, 32); if (rc != 0) { goto exit; } for (isid = pdb->ocontexts[0]; isid != NULL; isid = isid->next) { i = isid->sid[0]; if (i < num_sids && sid_to_str[i]) { sid = (char *)sid_to_str[i]; } else { snprintf(unknown, 18, "%s%u", "UNKNOWN", i); sid = unknown; } ctx = context_to_str(pdb, &isid->context[0]); if (!ctx) { rc = -1; goto exit; } rule = create_str("(sidcontext %s %s)", sid, ctx); free(ctx); if (!rule) { rc = -1; goto exit; } rc = strs_add_at_index(strs, rule, i); if (rc != 0) { free(rule); goto exit; } } strs_write_each(strs, out); exit: strs_free_all(strs); strs_destroy(&strs); if (rc != 0) { ERR(NULL, "Error writing sidcontext rules to CIL"); } return rc; } static int write_selinux_isid_rules_to_cil(FILE *out, struct policydb *pdb) { return write_sid_context_rules_to_cil(out, pdb, selinux_sid_to_str, SELINUX_SID_SZ); } static int write_selinux_fsuse_rules_to_cil(FILE *out, struct policydb *pdb) { struct ocontext *fsuse; const char *behavior; char *name, *ctx; int rc = 0; for (fsuse = pdb->ocontexts[5]; fsuse != NULL; fsuse = fsuse->next) { switch (fsuse->v.behavior) { case SECURITY_FS_USE_XATTR: behavior = "xattr"; break; case SECURITY_FS_USE_TRANS: behavior = "trans"; break; case SECURITY_FS_USE_TASK: behavior = "task"; break; default: ERR(NULL, "Unknown fsuse behavior: %i", fsuse->v.behavior); rc = -1; goto exit; } name = fsuse->u.name; ctx = context_to_str(pdb, &fsuse->context[0]); if (!ctx) { rc = -1; goto exit; } sepol_printf(out, "(fsuse %s %s %s)\n", behavior, name, ctx); free(ctx); } exit: if (rc != 0) { ERR(NULL, "Error writing fsuse rules to CIL"); } return rc; } static int write_genfscon_rules_to_cil(FILE *out, struct policydb *pdb) { struct genfs *genfs; struct ocontext *ocon; struct strs *strs; char *fstype, *name, *ctx; uint32_t sclass; const char *file_type; int rc; rc = strs_init(&strs, 32); if (rc != 0) { goto exit; } for (genfs = pdb->genfs; genfs != NULL; genfs = genfs->next) { for (ocon = genfs->head; ocon != NULL; ocon = ocon->next) { fstype = genfs->fstype; name = ocon->u.name; sclass = ocon->v.sclass; file_type = NULL; if (sclass) { const char *class_name = pdb->p_class_val_to_name[sclass-1]; if (strcmp(class_name, "file") == 0) { file_type = "file"; } else if (strcmp(class_name, "dir") == 0) { file_type = "dir"; } else if (strcmp(class_name, "chr_file") == 0) { file_type = "char"; } else if (strcmp(class_name, "blk_file") == 0) { file_type = "block"; } else if (strcmp(class_name, "sock_file") == 0) { file_type = "socket"; } else if (strcmp(class_name, "fifo_file") == 0) { file_type = "pipe"; } else if (strcmp(class_name, "lnk_file") == 0) { file_type = "symlink"; } else { rc = -1; goto exit; } } ctx = context_to_str(pdb, &ocon->context[0]); if (!ctx) { rc = -1; goto exit; } if (file_type) { rc = strs_create_and_add(strs, "(genfscon %s \"%s\" %s %s)", fstype, name, file_type, ctx); } else { rc = strs_create_and_add(strs, "(genfscon %s \"%s\" %s)", fstype, name, ctx); } free(ctx); if (rc != 0) { goto exit; } } } strs_sort(strs); strs_write_each(strs, out); exit: strs_free_all(strs); strs_destroy(&strs); if (rc != 0) { ERR(NULL, "Error writing genfscon rules to CIL"); } return rc; } static int write_selinux_port_rules_to_cil(FILE *out, struct policydb *pdb) { struct ocontext *portcon; const char *protocol; uint16_t low; uint16_t high; char low_high_str[44]; /* 2^64 <= 20 digits so "(low high)" <= 44 chars */ char *ctx; int rc = 0; for (portcon = pdb->ocontexts[2]; portcon != NULL; portcon = portcon->next) { switch (portcon->u.port.protocol) { case IPPROTO_TCP: protocol = "tcp"; break; case IPPROTO_UDP: protocol = "udp"; break; case IPPROTO_DCCP: protocol = "dccp"; break; case IPPROTO_SCTP: protocol = "sctp"; break; default: ERR(NULL, "Unknown portcon protocol: %i", portcon->u.port.protocol); rc = -1; goto exit; } low = portcon->u.port.low_port; high = portcon->u.port.high_port; if (low == high) { rc = snprintf(low_high_str, 44, "%u", low); } else { rc = snprintf(low_high_str, 44, "(%u %u)", low, high); } if (rc < 0 || rc >= 44) { rc = -1; goto exit; } ctx = context_to_str(pdb, &portcon->context[0]); if (!ctx) { rc = -1; goto exit; } sepol_printf(out, "(portcon %s %s %s)\n", protocol, low_high_str, ctx); free(ctx); } rc = 0; exit: if (rc != 0) { ERR(NULL, "Error writing portcon rules to CIL"); } return rc; } static int write_selinux_netif_rules_to_cil(FILE *out, struct policydb *pdb) { struct ocontext *netif; char *name, *ctx1, *ctx2; int rc = 0; for (netif = pdb->ocontexts[3]; netif != NULL; netif = netif->next) { name = netif->u.name; ctx1 = context_to_str(pdb, &netif->context[0]); if (!ctx1) { rc = -1; goto exit; } ctx2 = context_to_str(pdb, &netif->context[1]); if (!ctx2) { free(ctx1); rc = -1; goto exit; } sepol_printf(out, "(netifcon %s %s %s)\n", name, ctx1, ctx2); free(ctx1); free(ctx2); } exit: if (rc != 0) { ERR(NULL, "Error writing netifcon rules to CIL"); } return rc; } static int write_selinux_node_rules_to_cil(FILE *out, struct policydb *pdb) { struct ocontext *node; char addr[INET_ADDRSTRLEN]; char mask[INET_ADDRSTRLEN]; char *ctx; int rc = 0; for (node = pdb->ocontexts[4]; node != NULL; node = node->next) { if (inet_ntop(AF_INET, &node->u.node.addr, addr, INET_ADDRSTRLEN) == NULL) { ERR(NULL, "Nodecon address is invalid: %m"); rc = -1; goto exit; } if (inet_ntop(AF_INET, &node->u.node.mask, mask, INET_ADDRSTRLEN) == NULL) { ERR(NULL, "Nodecon mask is invalid: %m"); rc = -1; goto exit; } ctx = context_to_str(pdb, &node->context[0]); if (!ctx) { rc = -1; goto exit; } sepol_printf(out, "(nodecon (%s) (%s) %s)\n", addr, mask, ctx); free(ctx); } exit: if (rc != 0) { ERR(NULL, "Error writing nodecon rules to CIL"); } return rc; } static int write_selinux_node6_rules_to_cil(FILE *out, struct policydb *pdb) { struct ocontext *node; char addr[INET6_ADDRSTRLEN]; char mask[INET6_ADDRSTRLEN]; char *ctx; int rc = 0; for (node = pdb->ocontexts[6]; node != NULL; node = node->next) { if (inet_ntop(AF_INET6, &node->u.node6.addr, addr, INET6_ADDRSTRLEN) == NULL) { ERR(NULL, "Nodecon address is invalid: %m"); rc = -1; goto exit; } if (inet_ntop(AF_INET6, &node->u.node6.mask, mask, INET6_ADDRSTRLEN) == NULL) { ERR(NULL, "Nodecon mask is invalid: %m"); rc = -1; goto exit; } ctx = context_to_str(pdb, &node->context[0]); if (!ctx) { rc = -1; goto exit; } sepol_printf(out, "(nodecon (%s) (%s) %s)\n", addr, mask, ctx); free(ctx); } exit: if (rc != 0) { ERR(NULL, "Error writing nodecon rules to CIL"); } return rc; } static int write_selinux_ibpkey_rules_to_cil(FILE *out, struct policydb *pdb) { struct ocontext *ibpkeycon; char subnet_prefix_str[INET6_ADDRSTRLEN]; struct in6_addr subnet_prefix = IN6ADDR_ANY_INIT; uint16_t low; uint16_t high; char low_high_str[44]; /* 2^64 <= 20 digits so "(low high)" <= 44 chars */ char *ctx; int rc = 0; for (ibpkeycon = pdb->ocontexts[OCON_IBPKEY]; ibpkeycon != NULL; ibpkeycon = ibpkeycon->next) { memcpy(&subnet_prefix.s6_addr, &ibpkeycon->u.ibpkey.subnet_prefix, sizeof(ibpkeycon->u.ibpkey.subnet_prefix)); if (inet_ntop(AF_INET6, &subnet_prefix.s6_addr, subnet_prefix_str, INET6_ADDRSTRLEN) == NULL) { ERR(NULL, "ibpkeycon subnet_prefix is invalid: %m"); rc = -1; goto exit; } low = ibpkeycon->u.ibpkey.low_pkey; high = ibpkeycon->u.ibpkey.high_pkey; if (low == high) { rc = snprintf(low_high_str, 44, "%u", low); } else { rc = snprintf(low_high_str, 44, "(%u %u)", low, high); } if (rc < 0 || rc >= 44) { rc = -1; goto exit; } ctx = context_to_str(pdb, &ibpkeycon->context[0]); if (!ctx) { rc = -1; goto exit; } sepol_printf(out, "(ibpkeycon %s %s %s)\n", subnet_prefix_str, low_high_str, ctx); free(ctx); } rc = 0; exit: if (rc != 0) { ERR(NULL, "Error writing ibpkeycon rules to CIL"); } return rc; } static int write_selinux_ibendport_rules_to_cil(FILE *out, struct policydb *pdb) { struct ocontext *ibendportcon; char port_str[4]; char *ctx; int rc = 0; for (ibendportcon = pdb->ocontexts[OCON_IBENDPORT]; ibendportcon != NULL; ibendportcon = ibendportcon->next) { rc = snprintf(port_str, 4, "%u", ibendportcon->u.ibendport.port); if (rc < 0 || rc >= 4) { rc = -1; goto exit; } ctx = context_to_str(pdb, &ibendportcon->context[0]); if (!ctx) { rc = -1; goto exit; } sepol_printf(out, "(ibendportcon %s %s %s)\n", ibendportcon->u.ibendport.dev_name, port_str, ctx); free(ctx); } rc = 0; exit: if (rc != 0) { ERR(NULL, "Error writing ibendportcon rules to CIL"); } return rc; } static int write_xen_isid_rules_to_cil(FILE *out, struct policydb *pdb) { return write_sid_context_rules_to_cil(out, pdb, xen_sid_to_str, XEN_SID_SZ); } static int write_xen_pirq_rules_to_cil(FILE *out, struct policydb *pdb) { struct ocontext *pirq; char pirq_str[21]; /* 2^64-1 <= 20 digits */ char *ctx; int rc = 0; for (pirq = pdb->ocontexts[1]; pirq != NULL; pirq = pirq->next) { rc = snprintf(pirq_str, 21, "%i", pirq->u.pirq); if (rc < 0 || rc >= 21) { rc = -1; goto exit; } ctx = context_to_str(pdb, &pirq->context[0]); if (!ctx) { rc = -1; goto exit; } sepol_printf(out, "(pirqcon %s %s)\n", pirq_str, ctx); free(ctx); } rc = 0; exit: if (rc != 0) { ERR(NULL, "Error writing pirqcon rules to CIL"); } return rc; } static int write_xen_ioport_rules_to_cil(FILE *out, struct policydb *pdb) { struct ocontext *ioport; uint32_t low; uint32_t high; char low_high_str[40]; /* 2^64-1 <= 16 digits (hex) so (low high) < 40 chars */ char *ctx; int rc = 0; for (ioport = pdb->ocontexts[2]; ioport != NULL; ioport = ioport->next) { low = ioport->u.ioport.low_ioport; high = ioport->u.ioport.high_ioport; if (low == high) { rc = snprintf(low_high_str, 40, "0x%x", low); } else { rc = snprintf(low_high_str, 40, "(0x%x 0x%x)", low, high); } if (rc < 0 || rc >= 40) { rc = -1; goto exit; } ctx = context_to_str(pdb, &ioport->context[0]); if (!ctx) { rc = -1; goto exit; } sepol_printf(out, "(ioportcon %s %s)\n", low_high_str, ctx); free(ctx); } rc = 0; exit: if (rc != 0) { ERR(NULL, "Error writing ioportcon rules to CIL"); } return rc; } static int write_xen_iomem_rules_to_cil(FILE *out, struct policydb *pdb) { struct ocontext *iomem; uint64_t low; uint64_t high; char low_high_str[40]; /* 2^64-1 <= 16 digits (hex) so (low high) < 40 chars */ char *ctx; int rc = 0; for (iomem = pdb->ocontexts[3]; iomem != NULL; iomem = iomem->next) { low = iomem->u.iomem.low_iomem; high = iomem->u.iomem.high_iomem; if (low == high) { rc = snprintf(low_high_str, 40, "0x%"PRIx64, low); } else { rc = snprintf(low_high_str, 40, "(0x%"PRIx64" 0x%"PRIx64")", low, high); } if (rc < 0 || rc >= 40) { rc = -1; goto exit; } ctx = context_to_str(pdb, &iomem->context[0]); if (!ctx) { rc = -1; goto exit; } sepol_printf(out, "(iomemcon %s %s)\n", low_high_str, ctx); free(ctx); } rc = 0; exit: if (rc != 0) { ERR(NULL, "Error writing iomemcon rules to CIL"); } return rc; } static int write_xen_pcidevice_rules_to_cil(FILE *out, struct policydb *pdb) { struct ocontext *pcid; char device_str[20]; /* 2^64-1 <= 16 digits (hex) so (low high) < 19 chars */ char *ctx; int rc = 0; for (pcid = pdb->ocontexts[4]; pcid != NULL; pcid = pcid->next) { rc = snprintf(device_str, 20, "0x%lx", (unsigned long)pcid->u.device); if (rc < 0 || rc >= 20) { rc = -1; goto exit; } ctx = context_to_str(pdb, &pcid->context[0]); if (!ctx) { rc = -1; goto exit; } sepol_printf(out, "(pcidevicecon %s %s)\n", device_str, ctx); free(ctx); } rc = 0; exit: if (rc != 0) { ERR(NULL, "Error writing pcidevicecon rules to CIL"); } return rc; } static int write_xen_devicetree_rules_to_cil(FILE *out, struct policydb *pdb) { struct ocontext *dtree; char *name, *ctx; int rc = 0; for (dtree = pdb->ocontexts[5]; dtree != NULL; dtree = dtree->next) { name = dtree->u.name; ctx = context_to_str(pdb, &dtree->context[0]); if (!ctx) { rc = -1; goto exit; } sepol_printf(out, "(devicetreecon \"%s\" %s)\n", name, ctx); free(ctx); } exit: if (rc != 0) { ERR(NULL, "Error writing devicetreecon rules to CIL"); } return rc; } int sepol_kernel_policydb_to_cil(FILE *out, struct policydb *pdb) { struct strs *mls_constraints = NULL; struct strs *non_mls_constraints = NULL; struct strs *mls_validatetrans = NULL; struct strs *non_mls_validatetrans = NULL; int rc = 0; rc = strs_init(&mls_constraints, 32); if (rc != 0) { goto exit; } rc = strs_init(&non_mls_constraints, 32); if (rc != 0) { goto exit; } rc = strs_init(&mls_validatetrans, 32); if (rc != 0) { goto exit; } rc = strs_init(&non_mls_validatetrans, 32); if (rc != 0) { goto exit; } if (pdb == NULL) { ERR(NULL, "No policy"); rc = -1; goto exit; } if (pdb->policy_type != SEPOL_POLICY_KERN) { ERR(NULL, "Policy is not a kernel policy"); rc = -1; goto exit; } if (pdb->policyvers >= POLICYDB_VERSION_AVTAB && pdb->policyvers <= POLICYDB_VERSION_PERMISSIVE) { /* * For policy versions between 20 and 23, attributes exist in the policy, * but only in the type_attr_map. This means that there are gaps in both * the type_val_to_struct and p_type_val_to_name arrays and policy rules * can refer to those gaps. */ ERR(NULL, "Writing policy versions between 20 and 23 as CIL is not supported"); rc = -1; goto exit; } rc = constraint_rules_to_strs(pdb, mls_constraints, non_mls_constraints); if (rc != 0) { goto exit; } rc = validatetrans_rules_to_strs(pdb, mls_validatetrans, non_mls_validatetrans); if (rc != 0) { goto exit; } rc = write_handle_unknown_to_cil(out, pdb); if (rc != 0) { goto exit; } rc = write_class_decl_rules_to_cil(out, pdb); if (rc != 0) { goto exit; } rc = write_sid_decl_rules_to_cil(out, pdb); if (rc != 0) { goto exit; } rc = write_default_rules_to_cil(out, pdb); if (rc != 0) { goto exit; } rc = write_mls_rules_to_cil(out, pdb); if (rc != 0) { goto exit; } strs_write_each(mls_constraints, out); strs_write_each(mls_validatetrans, out); rc = write_polcap_rules_to_cil(out, pdb); if (rc != 0) { goto exit; } rc = write_type_attributes_to_cil(out, pdb); if (rc != 0) { goto exit; } rc = write_role_attributes_to_cil(out, pdb); if (rc != 0) { goto exit; } rc = write_boolean_decl_rules_to_cil(out, pdb); if (rc != 0) { goto exit; } rc = write_type_decl_rules_to_cil(out, pdb); if (rc != 0) { goto exit; } rc = write_type_alias_rules_to_cil(out, pdb); if (rc != 0) { goto exit; } rc = write_type_bounds_rules_to_cil(out, pdb); if (rc != 0) { goto exit; } rc = write_type_attribute_sets_to_cil(out, pdb); if (rc != 0) { goto exit; } rc = write_type_permissive_rules_to_cil(out, pdb); if (rc != 0) { goto exit; } rc = write_avtab_to_cil(out, pdb, 0); if (rc != 0) { goto exit; } rc = write_filename_trans_rules_to_cil(out, pdb); if (rc != 0) { goto exit; } if (pdb->mls) { rc = write_range_trans_rules_to_cil(out, pdb); if (rc != 0) { goto exit; } } rc = write_cond_nodes_to_cil(out, pdb); if (rc != 0) { goto exit; } rc = write_role_decl_rules_to_cil(out, pdb); if (rc != 0) { goto exit; } rc = write_role_transition_rules_to_cil(out, pdb); if (rc != 0) { goto exit; } rc = write_role_allow_rules_to_cil(out, pdb); if (rc != 0) { goto exit; } rc = write_user_decl_rules_to_cil(out, pdb); if (rc != 0) { goto exit; } strs_write_each(non_mls_constraints, out); strs_write_each(non_mls_validatetrans, out); rc = sort_ocontexts(pdb); if (rc != 0) { goto exit; } if (pdb->target_platform == SEPOL_TARGET_SELINUX) { rc = write_selinux_isid_rules_to_cil(out, pdb); if (rc != 0) { goto exit; } rc = write_selinux_fsuse_rules_to_cil(out, pdb); if (rc != 0) { goto exit; } rc = write_genfscon_rules_to_cil(out, pdb); if (rc != 0) { goto exit; } rc = write_selinux_port_rules_to_cil(out, pdb); if (rc != 0) { goto exit; } rc = write_selinux_netif_rules_to_cil(out, pdb); if (rc != 0) { goto exit; } rc = write_selinux_node_rules_to_cil(out, pdb); if (rc != 0) { goto exit; } rc = write_selinux_node6_rules_to_cil(out, pdb); if (rc != 0) { goto exit; } rc = write_selinux_ibpkey_rules_to_cil(out, pdb); if (rc != 0) { goto exit; } rc = write_selinux_ibendport_rules_to_cil(out, pdb); if (rc != 0) { goto exit; } } else if (pdb->target_platform == SEPOL_TARGET_XEN) { rc = write_xen_isid_rules_to_cil(out, pdb); if (rc != 0) { goto exit; } rc = write_xen_pirq_rules_to_cil(out, pdb); if (rc != 0) { goto exit; } rc = write_xen_ioport_rules_to_cil(out, pdb); if (rc != 0) { goto exit; } rc = write_xen_iomem_rules_to_cil(out, pdb); if (rc != 0) { goto exit; } rc = write_xen_pcidevice_rules_to_cil(out, pdb); if (rc != 0) { goto exit; } rc = write_xen_devicetree_rules_to_cil(out, pdb); if (rc != 0) { goto exit; } } exit: strs_free_all(mls_constraints); strs_destroy(&mls_constraints); strs_free_all(non_mls_constraints); strs_destroy(&non_mls_constraints); strs_free_all(mls_validatetrans); strs_destroy(&mls_validatetrans); strs_free_all(non_mls_validatetrans); strs_destroy(&non_mls_validatetrans); return rc; } libsepol-3.8.1/src/kernel_to_common.c000066400000000000000000000275421476211737200176450ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #ifndef IPPROTO_DCCP #define IPPROTO_DCCP 33 #endif #ifndef IPPROTO_SCTP #define IPPROTO_SCTP 132 #endif #include #include #include #include "debug.h" #include "private.h" #include "kernel_to_common.h" void sepol_indent(FILE *out, int indent) { if (fprintf(out, "%*s", indent * 4, "") < 0) { ERR(NULL, "Failed to write to output"); } } void sepol_printf(FILE *out, const char *fmt, ...) { va_list argptr; va_start(argptr, fmt); if (vfprintf(out, fmt, argptr) < 0) { ERR(NULL, "Failed to write to output"); } va_end(argptr); } char *create_str(const char *fmt, ...) { char *str; va_list vargs; int rc; va_start(vargs, fmt); rc = vasprintf(&str, fmt, vargs); va_end(vargs); if (rc == -1) return NULL; return str; } int strs_init(struct strs **strs, size_t size) { struct strs *new; if (size == 0) { size = 1; } *strs = NULL; new = malloc(sizeof(struct strs)); if (!new) { ERR(NULL, "Out of memory"); return -1; } new->list = calloc(size, sizeof(char *)); if (!new->list) { ERR(NULL, "Out of memory"); free(new); return -1; } new->num = 0; new->size = size; *strs = new; return 0; } void strs_destroy(struct strs **strs) { if (!strs || !*strs) { return; } free((*strs)->list); (*strs)->list = NULL; (*strs)->num = 0; (*strs)->size = 0; free(*strs); *strs = NULL; } void strs_free_all(struct strs *strs) { if (!strs) { return; } while (strs->num > 0) { strs->num--; free(strs->list[strs->num]); } } int strs_add(struct strs *strs, char *s) { if (strs->num + 1 > strs->size) { char **new; size_t i = strs->size; strs->size *= 2; new = reallocarray(strs->list, strs->size, sizeof(char *)); if (!new) { ERR(NULL, "Out of memory"); return -1; } strs->list = new; memset(&strs->list[i], 0, sizeof(char *)*(strs->size-i)); } strs->list[strs->num] = s; strs->num++; return 0; } int strs_create_and_add(struct strs *strs, const char *fmt, ...) { char *str; va_list vargs; int rc; va_start(vargs, fmt); rc = vasprintf(&str, fmt, vargs); va_end(vargs); if (rc == -1) goto exit; rc = strs_add(strs, str); if (rc != 0) { free(str); goto exit; } return 0; exit: return rc; } char *strs_remove_last(struct strs *strs) { if (strs->num == 0) { return NULL; } strs->num--; return strs->list[strs->num]; } int strs_add_at_index(struct strs *strs, char *s, size_t index) { if (index >= strs->size) { char **new; size_t i = strs->size; while (index >= strs->size) { strs->size *= 2; } new = reallocarray(strs->list, strs->size, sizeof(char *)); if (!new) { ERR(NULL, "Out of memory"); return -1; } strs->list = new; memset(&strs->list[i], 0, sizeof(char *)*(strs->size - i)); } strs->list[index] = s; if (index >= strs->num) { strs->num = index+1; } return 0; } char *strs_read_at_index(struct strs *strs, size_t index) { if (index >= strs->num) { return NULL; } return strs->list[index]; } static int strs_cmp(const void *a, const void *b) { char *const *aa = a; char *const *bb = b; return strcmp(*aa,*bb); } void strs_sort(struct strs *strs) { if (strs->num == 0) { return; } qsort(strs->list, strs->num, sizeof(char *), strs_cmp); } unsigned strs_num_items(const struct strs *strs) { return strs->num; } size_t strs_len_items(const struct strs *strs) { unsigned i; size_t len = 0; for (i=0; inum; i++) { if (!strs->list[i]) continue; len += strlen(strs->list[i]); } return len; } char *strs_to_str(const struct strs *strs) { char *str = NULL; size_t len = 0; char *p; unsigned i; int rc; if (strs->num == 0) { goto exit; } /* strs->num added because either ' ' or '\0' follows each item */ len = strs_len_items(strs) + strs->num; str = malloc(len); if (!str) { ERR(NULL, "Out of memory"); goto exit; } p = str; for (i=0; inum; i++) { if (!strs->list[i]) continue; len = strlen(strs->list[i]); rc = snprintf(p, len+1, "%s", strs->list[i]); if (rc < 0 || rc > (int)len) { free(str); str = NULL; goto exit; } p += len; if (i < strs->num - 1) { *p++ = ' '; } } *p = '\0'; exit: return str; } void strs_write_each(const struct strs *strs, FILE *out) { unsigned i; for (i=0; inum; i++) { if (!strs->list[i]) { continue; } sepol_printf(out, "%s\n",strs->list[i]); } } void strs_write_each_indented(const struct strs *strs, FILE *out, int indent) { unsigned i; for (i=0; inum; i++) { if (!strs->list[i]) { continue; } sepol_indent(out, indent); sepol_printf(out, "%s\n",strs->list[i]); } } int hashtab_ordered_to_strs(char *key, void *data, void *args) { struct strs *strs = (struct strs *)args; symtab_datum_t *datum = data; return strs_add_at_index(strs, key, datum->value-1); } int ebitmap_to_strs(const struct ebitmap *map, struct strs *strs, char **val_to_name) { struct ebitmap_node *node; uint32_t i; int rc; ebitmap_for_each_positive_bit(map, node, i) { if (!val_to_name[i]) continue; rc = strs_add(strs, val_to_name[i]); if (rc != 0) { return -1; } } return 0; } char *ebitmap_to_str(const struct ebitmap *map, char **val_to_name, int sort) { struct strs *strs; char *str = NULL; int rc; rc = strs_init(&strs, 32); if (rc != 0) { goto exit; } rc = ebitmap_to_strs(map, strs, val_to_name); if (rc != 0) { goto exit; } if (sort) { strs_sort(strs); } str = strs_to_str(strs); exit: strs_destroy(&strs); return str; } int strs_stack_init(struct strs **stack) { return strs_init(stack, STACK_SIZE); } void strs_stack_destroy(struct strs **stack) { return strs_destroy(stack); } int strs_stack_push(struct strs *stack, char *s) { return strs_add(stack, s); } char *strs_stack_pop(struct strs *stack) { return strs_remove_last(stack); } int strs_stack_empty(const struct strs *stack) { return strs_num_items(stack) == 0; } static int compare_ranges(uint64_t l1, uint64_t h1, uint64_t l2, uint64_t h2) { uint64_t d1, d2; d1 = h1-l1; d2 = h2-l2; if (d1 < d2) { return -1; } else if (d1 > d2) { return 1; } else { if (l1 < l2) { return -1; } else if (l1 > l2) { return 1; } } return 0; } static int fsuse_data_cmp(const void *a, const void *b) { struct ocontext *const *aa = a; struct ocontext *const *bb = b; if ((*aa)->v.behavior != (*bb)->v.behavior) { if ((*aa)->v.behavior < (*bb)->v.behavior) { return -1; } else { return 1; } } return strcmp((*aa)->u.name, (*bb)->u.name); } static int portcon_data_cmp(const void *a, const void *b) { struct ocontext *const *aa = a; struct ocontext *const *bb = b; int rc; rc = compare_ranges((*aa)->u.port.low_port, (*aa)->u.port.high_port, (*bb)->u.port.low_port, (*bb)->u.port.high_port); if (rc == 0) { if ((*aa)->u.port.protocol < (*bb)->u.port.protocol) { rc = -1; } else if ((*aa)->u.port.protocol > (*bb)->u.port.protocol) { rc = 1; } } return rc; } static int netif_data_cmp(const void *a, const void *b) { struct ocontext *const *aa = a; struct ocontext *const *bb = b; return strcmp((*aa)->u.name, (*bb)->u.name); } static int node_data_cmp(const void *a, const void *b) { struct ocontext *const *aa = a; struct ocontext *const *bb = b; int rc; rc = memcmp(&(*aa)->u.node.mask, &(*bb)->u.node.mask, sizeof((*aa)->u.node.mask)); if (rc > 0) { return -1; } else if (rc < 0) { return 1; } return memcmp(&(*aa)->u.node.addr, &(*bb)->u.node.addr, sizeof((*aa)->u.node.addr)); } static int node6_data_cmp(const void *a, const void *b) { struct ocontext *const *aa = a; struct ocontext *const *bb = b; int rc; rc = memcmp(&(*aa)->u.node6.mask, &(*bb)->u.node6.mask, sizeof((*aa)->u.node6.mask)); if (rc > 0) { return -1; } else if (rc < 0) { return 1; } return memcmp(&(*aa)->u.node6.addr, &(*bb)->u.node6.addr, sizeof((*aa)->u.node6.addr)); } static int ibpkey_data_cmp(const void *a, const void *b) { int rc; struct ocontext *const *aa = a; struct ocontext *const *bb = b; rc = (*aa)->u.ibpkey.subnet_prefix - (*bb)->u.ibpkey.subnet_prefix; if (rc) return rc; return compare_ranges((*aa)->u.ibpkey.low_pkey, (*aa)->u.ibpkey.high_pkey, (*bb)->u.ibpkey.low_pkey, (*bb)->u.ibpkey.high_pkey); } static int ibendport_data_cmp(const void *a, const void *b) { int rc; struct ocontext *const *aa = a; struct ocontext *const *bb = b; rc = strcmp((*aa)->u.ibendport.dev_name, (*bb)->u.ibendport.dev_name); if (rc) return rc; return spaceship_cmp((*aa)->u.ibendport.port, (*bb)->u.ibendport.port); } static int pirq_data_cmp(const void *a, const void *b) { struct ocontext *const *aa = a; struct ocontext *const *bb = b; if ((*aa)->u.pirq < (*bb)->u.pirq) { return -1; } else if ((*aa)->u.pirq > (*bb)->u.pirq) { return 1; } return 0; } static int ioport_data_cmp(const void *a, const void *b) { struct ocontext *const *aa = a; struct ocontext *const *bb = b; return compare_ranges((*aa)->u.ioport.low_ioport, (*aa)->u.ioport.high_ioport, (*bb)->u.ioport.low_ioport, (*bb)->u.ioport.high_ioport); } static int iomem_data_cmp(const void *a, const void *b) { struct ocontext *const *aa = a; struct ocontext *const *bb = b; return compare_ranges((*aa)->u.iomem.low_iomem, (*aa)->u.iomem.high_iomem, (*bb)->u.iomem.low_iomem, (*bb)->u.iomem.high_iomem); } static int pcid_data_cmp(const void *a, const void *b) { struct ocontext *const *aa = a; struct ocontext *const *bb = b; if ((*aa)->u.device < (*bb)->u.device) { return -1; } else if ((*aa)->u.device > (*bb)->u.device) { return 1; } return 0; } static int dtree_data_cmp(const void *a, const void *b) { struct ocontext *const *aa = a; struct ocontext *const *bb = b; return strcmp((*aa)->u.name, (*bb)->u.name); } static int sort_ocontext_data(struct ocontext **ocons, int (*cmp)(const void *, const void *)) { struct ocontext *ocon; struct ocontext **data; unsigned i, num; num = 0; for (ocon = *ocons; ocon != NULL; ocon = ocon->next) { num++; } if (num == 0) { return 0; } data = calloc(num, sizeof(*data)); if (!data) { ERR(NULL, "Out of memory"); return -1; } i = 0; for (ocon = *ocons; ocon != NULL; ocon = ocon->next) { data[i] = ocon; i++; } qsort(data, num, sizeof(*data), cmp); *ocons = data[0]; for (i=1; i < num; i++) { data[i-1]->next = data[i]; } data[num-1]->next = NULL; free(data); return 0; } int sort_ocontexts(struct policydb *pdb) { int rc = 0; if (pdb->target_platform == SEPOL_TARGET_SELINUX) { rc = sort_ocontext_data(&pdb->ocontexts[5], fsuse_data_cmp); if (rc != 0) { goto exit; } rc = sort_ocontext_data(&pdb->ocontexts[2], portcon_data_cmp); if (rc != 0) { goto exit; } rc = sort_ocontext_data(&pdb->ocontexts[3], netif_data_cmp); if (rc != 0) { goto exit; } rc = sort_ocontext_data(&pdb->ocontexts[4], node_data_cmp); if (rc != 0) { goto exit; } rc = sort_ocontext_data(&pdb->ocontexts[6], node6_data_cmp); if (rc != 0) { goto exit; } rc = sort_ocontext_data(&pdb->ocontexts[OCON_IBPKEY], ibpkey_data_cmp); if (rc != 0) { goto exit; } rc = sort_ocontext_data(&pdb->ocontexts[OCON_IBENDPORT], ibendport_data_cmp); if (rc != 0) { goto exit; } } else if (pdb->target_platform == SEPOL_TARGET_XEN) { rc = sort_ocontext_data(&pdb->ocontexts[1], pirq_data_cmp); if (rc != 0) { goto exit; } rc = sort_ocontext_data(&pdb->ocontexts[2], ioport_data_cmp); if (rc != 0) { goto exit; } rc = sort_ocontext_data(&pdb->ocontexts[3], iomem_data_cmp); if (rc != 0) { goto exit; } rc = sort_ocontext_data(&pdb->ocontexts[4], pcid_data_cmp); if (rc != 0) { goto exit; } rc = sort_ocontext_data(&pdb->ocontexts[5], dtree_data_cmp); if (rc != 0) { goto exit; } } exit: if (rc != 0) { ERR(NULL, "Error sorting ocontexts"); } return rc; } libsepol-3.8.1/src/kernel_to_common.h000066400000000000000000000053671476211737200176530ustar00rootroot00000000000000#include #include #include #include #include #define STACK_SIZE 16 #define DEFAULT_LEVEL "systemlow" #define DEFAULT_OBJECT "object_r" // initial sid names aren't actually stored in the pp files, need to a have // a mapping, taken from the linux kernel static const char * const selinux_sid_to_str[] = { NULL, "kernel", "security", "unlabeled", NULL, "file", NULL, "init", "any_socket", "port", "netif", "netmsg", "node", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "devnull", }; #define SELINUX_SID_SZ (sizeof(selinux_sid_to_str)/sizeof(selinux_sid_to_str[0])) static const char * const xen_sid_to_str[] = { "null", "xen", "dom0", "domio", "domxen", "unlabeled", "security", "ioport", "iomem", "irq", "device", "domU", "domDM", }; #define XEN_SID_SZ (sizeof(xen_sid_to_str)/sizeof(xen_sid_to_str[0])) static const uint32_t avtab_flavors[] = { AVTAB_ALLOWED, AVTAB_AUDITALLOW, AVTAB_AUDITDENY, AVTAB_XPERMS_ALLOWED, AVTAB_XPERMS_AUDITALLOW, AVTAB_XPERMS_DONTAUDIT, AVTAB_TRANSITION, AVTAB_MEMBER, AVTAB_CHANGE, }; #define AVTAB_FLAVORS_SZ (sizeof(avtab_flavors)/sizeof(avtab_flavors[0])) struct strs { char **list; unsigned num; size_t size; }; void sepol_indent(FILE *out, int indent); __attribute__ ((format(printf, 2, 3))) void sepol_printf(FILE *out, const char *fmt, ...); __attribute__ ((format(printf, 1, 2))) char *create_str(const char *fmt, ...); int strs_init(struct strs **strs, size_t size); void strs_destroy(struct strs **strs); void strs_free_all(struct strs *strs); int strs_add(struct strs *strs, char *s); __attribute__ ((format(printf, 2, 3))) int strs_create_and_add(struct strs *strs, const char *fmt, ...); char *strs_remove_last(struct strs *strs); int strs_add_at_index(struct strs *strs, char *s, size_t index); char *strs_read_at_index(struct strs *strs, size_t index); void strs_sort(struct strs *strs); unsigned strs_num_items(const struct strs *strs); size_t strs_len_items(const struct strs *strs); char *strs_to_str(const struct strs *strs); void strs_write_each(const struct strs *strs, FILE *out); void strs_write_each_indented(const struct strs *strs, FILE *out, int indent); int hashtab_ordered_to_strs(char *key, void *data, void *args); int ebitmap_to_strs(const struct ebitmap *map, struct strs *strs, char **val_to_name); char *ebitmap_to_str(const struct ebitmap *map, char **val_to_name, int sort); int strs_stack_init(struct strs **stack); void strs_stack_destroy(struct strs **stack); int strs_stack_push(struct strs *stack, char *s); char *strs_stack_pop(struct strs *stack); int strs_stack_empty(const struct strs *stack); int sort_ocontexts(struct policydb *pdb); libsepol-3.8.1/src/kernel_to_conf.c000066400000000000000000002046201476211737200172740ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include #ifndef IPPROTO_DCCP #define IPPROTO_DCCP 33 #endif #ifndef IPPROTO_SCTP #define IPPROTO_SCTP 132 #endif #include #include #include #include #include #include #include #include #include "debug.h" #include "kernel_to_common.h" static char *cond_expr_to_str(struct policydb *pdb, struct cond_expr *expr) { struct cond_expr *curr; struct strs *stack; char *new_val; char *str = NULL; int rc; rc = strs_stack_init(&stack); if (rc != 0) { goto exit; } for (curr = expr; curr != NULL; curr = curr->next) { if (curr->expr_type == COND_BOOL) { char *val1 = pdb->p_bool_val_to_name[curr->boolean - 1]; new_val = create_str("%s", val1); } else { const char *op; uint32_t num_params; char *val1 = NULL; char *val2 = NULL; switch(curr->expr_type) { case COND_NOT: op = "!"; num_params = 1; break; case COND_OR: op = "||"; num_params = 2; break; case COND_AND: op = "&&"; num_params = 2; break; case COND_XOR: op = "^"; num_params = 2; break; case COND_EQ: op = "=="; num_params = 2; break; case COND_NEQ: op = "!="; num_params = 2; break; default: ERR(NULL, "Unknown conditional operator: %i", curr->expr_type); goto exit; } if (num_params == 2) { val2 = strs_stack_pop(stack); if (!val2) { ERR(NULL, "Invalid conditional expression"); goto exit; } } val1 = strs_stack_pop(stack); if (!val1) { ERR(NULL, "Invalid conditional expression"); free(val2); goto exit; } if (num_params == 2) { new_val = create_str("(%s %s %s)", val1, op, val2); free(val2); } else { new_val = create_str("%s %s", op, val1); } free(val1); } if (!new_val) { ERR(NULL, "Invalid conditional expression"); goto exit; } rc = strs_stack_push(stack, new_val); if (rc != 0) { ERR(NULL, "Out of memory"); goto exit; } } new_val = strs_stack_pop(stack); if (!new_val || !strs_stack_empty(stack)) { ERR(NULL, "Invalid conditional expression"); goto exit; } str = new_val; strs_stack_destroy(&stack); return str; exit: if (stack) { while ((new_val = strs_stack_pop(stack)) != NULL) { free(new_val); } strs_stack_destroy(&stack); } return NULL; } static char *constraint_expr_to_str(struct policydb *pdb, struct constraint_expr *expr, int *use_mls) { struct constraint_expr *curr; struct strs *stack = NULL; char *new_val = NULL; const char *op; char *str = NULL; int rc; *use_mls = 0; rc = strs_stack_init(&stack); if (rc != 0) { goto exit; } for (curr = expr; curr; curr = curr->next) { if (curr->expr_type == CEXPR_ATTR || curr->expr_type == CEXPR_NAMES) { const char *attr1 = NULL; const char *attr2 = NULL; switch (curr->op) { case CEXPR_EQ: op = "=="; break; case CEXPR_NEQ: op = "!="; break; case CEXPR_DOM: op = "dom"; break; case CEXPR_DOMBY: op = "domby"; break; case CEXPR_INCOMP: op = "incomp"; break; default: ERR(NULL, "Unknown constraint operator: %i", curr->op); goto exit; } switch (curr->attr) { case CEXPR_USER: attr1 ="u1"; attr2 ="u2"; break; case CEXPR_USER | CEXPR_TARGET: attr1 ="u2"; attr2 =""; break; case CEXPR_USER | CEXPR_XTARGET: attr1 ="u3"; attr2 =""; break; case CEXPR_ROLE: attr1 ="r1"; attr2 ="r2"; break; case CEXPR_ROLE | CEXPR_TARGET: attr1 ="r2"; attr2 =""; break; case CEXPR_ROLE | CEXPR_XTARGET: attr1 ="r3"; attr2 =""; break; case CEXPR_TYPE: attr1 ="t1"; attr2 ="t2"; break; case CEXPR_TYPE | CEXPR_TARGET: attr1 ="t2"; attr2 =""; break; case CEXPR_TYPE | CEXPR_XTARGET: attr1 ="t3"; attr2 =""; break; case CEXPR_L1L2: attr1 ="l1"; attr2 ="l2"; break; case CEXPR_L1H2: attr1 ="l1"; attr2 ="h2"; break; case CEXPR_H1L2: attr1 ="h1"; attr2 ="l2"; break; case CEXPR_H1H2: attr1 ="h1"; attr2 ="h2"; break; case CEXPR_L1H1: attr1 ="l1"; attr2 ="h1"; break; case CEXPR_L2H2: attr1 ="l2"; attr2 ="h2"; break; default: ERR(NULL, "Unknown constraint attribute: %i", curr->attr); goto exit; } if (curr->attr >= CEXPR_L1L2) { *use_mls = 1; } if (curr->expr_type == CEXPR_ATTR) { new_val = create_str("%s %s %s", attr1, op, attr2); } else { char *names = NULL; if (curr->attr & CEXPR_TYPE) { struct type_set *ts = curr->type_names; names = ebitmap_to_str(&ts->types, pdb->p_type_val_to_name, 1); } else if (curr->attr & CEXPR_USER) { names = ebitmap_to_str(&curr->names, pdb->p_user_val_to_name, 1); } else if (curr->attr & CEXPR_ROLE) { names = ebitmap_to_str(&curr->names, pdb->p_role_val_to_name, 1); } if (!names) { names = strdup("NO_IDENTIFIER"); if (!names) { ERR(NULL, "Out of memory"); goto exit; } } if (strchr(names, ' ')) { new_val = create_str("%s %s { %s }", attr1, op, names); } else { new_val = create_str("%s %s %s", attr1, op, names); } free(names); } } else { uint32_t num_params; char *val1 = NULL; char *val2 = NULL; switch (curr->expr_type) { case CEXPR_NOT: op = "not"; num_params = 1; break; case CEXPR_AND: op = "and"; num_params = 2; break; case CEXPR_OR: op = "or"; num_params = 2; break; default: ERR(NULL, "Unknown constraint expression type: %i", curr->expr_type); goto exit; } if (num_params == 2) { val2 = strs_stack_pop(stack); if (!val2) { ERR(NULL, "Invalid constraint expression"); goto exit; } } val1 = strs_stack_pop(stack); if (!val1) { ERR(NULL, "Invalid constraint expression"); goto exit; } if (num_params == 2) { new_val = create_str("(%s %s %s)", val1, op, val2); free(val2); } else { new_val = create_str("%s (%s)", op, val1); } free(val1); } if (!new_val) { goto exit; } rc = strs_stack_push(stack, new_val); if (rc != 0) { ERR(NULL, "Out of memory"); goto exit; } } new_val = strs_stack_pop(stack); if (!new_val || !strs_stack_empty(stack)) { ERR(NULL, "Invalid constraint expression"); goto exit; } str = new_val; strs_stack_destroy(&stack); return str; exit: if (stack) { while ((new_val = strs_stack_pop(stack)) != NULL) { free(new_val); } strs_stack_destroy(&stack); } return NULL; } static int class_constraint_rules_to_strs(struct policydb *pdb, char *classkey, class_datum_t *class, struct constraint_node *constraint_rules, struct strs *mls_list, struct strs *non_mls_list) { struct constraint_node *curr; struct strs *strs; const char *flavor, *perm_prefix, *perm_suffix; char *perms, *expr; int is_mls; int rc = 0; for (curr = constraint_rules; curr != NULL; curr = curr->next) { if (curr->permissions == 0) { continue; } expr = constraint_expr_to_str(pdb, curr->expr, &is_mls); if (!expr) { rc = -1; goto exit; } perms = sepol_av_to_string(pdb, class->s.value, curr->permissions); if (!perms) { ERR(NULL, "Failed to generate permission string"); rc = -1; goto exit; } if (*perms == '\0') { ERR(NULL, "No permissions in permission string"); free(perms); rc = -1; goto exit; } if (strchr(perms, ' ')) { perm_prefix = "{ "; perm_suffix = " }"; } else { perm_prefix = ""; perm_suffix = ""; } if (is_mls) { flavor = "mlsconstrain"; strs = mls_list; } else { flavor = "constrain"; strs = non_mls_list; } rc = strs_create_and_add(strs, "%s %s %s%s%s %s;", flavor, classkey, perm_prefix, perms+1, perm_suffix, expr); free(perms); free(expr); if (rc != 0) { goto exit; } } return 0; exit: ERR(NULL, "Error gathering constraint rules"); return rc; } static int class_validatetrans_rules_to_strs(struct policydb *pdb, char *classkey, struct constraint_node *validatetrans_rules, struct strs *mls_list, struct strs *non_mls_list) { struct constraint_node *curr; struct strs *strs; const char *flavor; char *expr; int is_mls; int rc = 0; for (curr = validatetrans_rules; curr != NULL; curr = curr->next) { expr = constraint_expr_to_str(pdb, curr->expr, &is_mls); if (!expr) { rc = -1; goto exit; } if (is_mls) { flavor = "mlsvalidatetrans"; strs = mls_list; } else { flavor = "validatetrans"; strs = non_mls_list; } rc = strs_create_and_add(strs, "%s %s %s;", flavor, classkey, expr); free(expr); if (rc != 0) { goto exit; } } exit: return rc; } static int constraint_rules_to_strs(struct policydb *pdb, struct strs *mls_strs, struct strs *non_mls_strs) { class_datum_t *class; char *name; unsigned i; int rc = 0; for (i=0; i < pdb->p_classes.nprim; i++) { class = pdb->class_val_to_struct[i]; if (class && class->constraints) { name = pdb->p_class_val_to_name[i]; rc = class_constraint_rules_to_strs(pdb, name, class, class->constraints, mls_strs, non_mls_strs); if (rc != 0) { goto exit; } } } strs_sort(mls_strs); strs_sort(non_mls_strs); exit: return rc; } static int validatetrans_rules_to_strs(struct policydb *pdb, struct strs *mls_strs, struct strs *non_mls_strs) { class_datum_t *class; char *name; unsigned i; int rc = 0; for (i=0; i < pdb->p_classes.nprim; i++) { class = pdb->class_val_to_struct[i]; if (class && class->validatetrans) { name = pdb->p_class_val_to_name[i]; rc = class_validatetrans_rules_to_strs(pdb, name, class->validatetrans, mls_strs, non_mls_strs); if (rc != 0) { goto exit; } } } strs_sort(mls_strs); strs_sort(non_mls_strs); exit: return rc; } static int write_handle_unknown_to_conf(FILE *out, struct policydb *pdb) { const char *action; switch (pdb->handle_unknown) { case SEPOL_DENY_UNKNOWN: action = "deny"; break; case SEPOL_REJECT_UNKNOWN: action = "reject"; break; case SEPOL_ALLOW_UNKNOWN: action = "allow"; break; default: ERR(NULL, "Unknown value for handle-unknown: %i", pdb->handle_unknown); return -1; } sepol_printf(out, "# handle_unknown %s\n", action); return 0; } static int write_class_decl_rules_to_conf(FILE *out, struct policydb *pdb) { char *name; unsigned i; for (i=0; i < pdb->p_classes.nprim; i++) { name = pdb->p_class_val_to_name[i]; sepol_printf(out, "class %s\n", name); } return 0; } static int write_sids_to_conf(FILE *out, const char *const *sid_to_str, unsigned num_sids, struct ocontext *isids) { struct ocontext *isid; struct strs *strs; char *sid; char unknown[18]; unsigned i; int rc; rc = strs_init(&strs, num_sids+1); if (rc != 0) { goto exit; } for (isid = isids; isid != NULL; isid = isid->next) { i = isid->sid[0]; if (i < num_sids && sid_to_str[i]) { sid = strdup(sid_to_str[i]); } else { snprintf(unknown, sizeof(unknown), "%s%u", "UNKNOWN", i); sid = strdup(unknown); } if (!sid) { rc = -1; goto exit; } rc = strs_add_at_index(strs, sid, i); if (rc != 0) { free(sid); goto exit; } } for (i=0; itarget_platform == SEPOL_TARGET_SELINUX) { rc = write_sids_to_conf(out, selinux_sid_to_str, SELINUX_SID_SZ, pdb->ocontexts[0]); } else if (pdb->target_platform == SEPOL_TARGET_XEN) { rc = write_sids_to_conf(out, xen_sid_to_str, XEN_SID_SZ, pdb->ocontexts[0]); } else { ERR(NULL, "Unknown target platform: %i", pdb->target_platform); rc = -1; } return rc; } static char *class_or_common_perms_to_str(symtab_t *permtab) { struct strs *strs; char *perms = NULL; int rc = 0; rc = strs_init(&strs, permtab->nprim); if (rc != 0) { goto exit; } rc = hashtab_map(permtab->table, hashtab_ordered_to_strs, strs); if (rc != 0) { goto exit; } if (strs_num_items(strs) > 0) { perms = strs_to_str(strs); } exit: strs_destroy(&strs); return perms; } static int write_class_and_common_rules_to_conf(FILE *out, struct policydb *pdb) { class_datum_t *class; common_datum_t *common; int *used; char *name, *perms; unsigned i; int rc = 0; /* common */ used = calloc(pdb->p_commons.nprim, sizeof(*used)); if (!used) { ERR(NULL, "Out of memory"); rc = -1; goto exit; } for (i=0; i < pdb->p_classes.nprim; i++) { class = pdb->class_val_to_struct[i]; if (!class) continue; name = class->comkey; if (!name) continue; common = hashtab_search(pdb->p_commons.table, name); if (!common) { rc = -1; free(used); goto exit; } /* Only write common rule once */ if (!used[common->s.value-1]) { perms = class_or_common_perms_to_str(&common->permissions); if (!perms) { rc = -1; free(used); goto exit; } sepol_printf(out, "common %s { %s }\n", name, perms); free(perms); used[common->s.value-1] = 1; } } free(used); /* class */ for (i=0; i < pdb->p_classes.nprim; i++) { class = pdb->class_val_to_struct[i]; if (!class) continue; name = pdb->p_class_val_to_name[i]; perms = class_or_common_perms_to_str(&class->permissions); /* Do not write empty classes, their declaration was alreedy * printed in write_class_decl_rules_to_conf() */ if (perms || class->comkey) { sepol_printf(out, "class %s", name); if (class->comkey) { sepol_printf(out, " inherits %s", class->comkey); } if (perms) { sepol_printf(out, " { %s }", perms); free(perms); } sepol_printf(out, "\n"); } } exit: if (rc != 0) { ERR(NULL, "Error writing class rules to policy.conf"); } return rc; } static int write_default_user_to_conf(FILE *out, char *class_name, class_datum_t *class) { const char *dft; switch (class->default_user) { case DEFAULT_SOURCE: dft = "source"; break; case DEFAULT_TARGET: dft = "target"; break; default: ERR(NULL, "Unknown default role value: %i", class->default_user); return -1; } sepol_printf(out, "default_user { %s } %s;\n", class_name, dft); return 0; } static int write_default_role_to_conf(FILE *out, char *class_name, class_datum_t *class) { const char *dft; switch (class->default_role) { case DEFAULT_SOURCE: dft = "source"; break; case DEFAULT_TARGET: dft = "target"; break; default: ERR(NULL, "Unknown default role value: %i", class->default_role); return -1; } sepol_printf(out, "default_role { %s } %s;\n", class_name, dft); return 0; } static int write_default_type_to_conf(FILE *out, char *class_name, class_datum_t *class) { const char *dft; switch (class->default_type) { case DEFAULT_SOURCE: dft = "source"; break; case DEFAULT_TARGET: dft = "target"; break; default: ERR(NULL, "Unknown default type value: %i", class->default_type); return -1; } sepol_printf(out, "default_type { %s } %s;\n", class_name, dft); return 0; } static int write_default_range_to_conf(FILE *out, char *class_name, class_datum_t *class) { const char *dft; switch (class->default_range) { case DEFAULT_SOURCE_LOW: dft = "source low"; break; case DEFAULT_SOURCE_HIGH: dft = "source high"; break; case DEFAULT_SOURCE_LOW_HIGH: dft = "source low-high"; break; case DEFAULT_TARGET_LOW: dft = "target low"; break; case DEFAULT_TARGET_HIGH: dft = "target high"; break; case DEFAULT_TARGET_LOW_HIGH: dft = "target low-high"; break; case DEFAULT_GLBLUB: dft = "glblub"; break; default: ERR(NULL, "Unknown default type value: %i", class->default_range); return -1; } sepol_printf(out, "default_range { %s } %s;\n", class_name, dft); return 0; } static int write_default_rules_to_conf(FILE *out, struct policydb *pdb) { class_datum_t *class; unsigned i; int rc = 0; /* default_user */ for (i=0; i < pdb->p_classes.nprim; i++) { class = pdb->class_val_to_struct[i]; if (!class) continue; if (class->default_user != 0) { rc = write_default_user_to_conf(out, pdb->p_class_val_to_name[i], class); if (rc != 0) { goto exit; } } } /* default_role */ for (i=0; i < pdb->p_classes.nprim; i++) { class = pdb->class_val_to_struct[i]; if (!class) continue; if (class->default_role != 0) { rc = write_default_role_to_conf(out, pdb->p_class_val_to_name[i], class); if (rc != 0) { goto exit; } } } /* default_type */ for (i=0; i < pdb->p_classes.nprim; i++) { class = pdb->class_val_to_struct[i]; if (!class) continue; if (class->default_type != 0) { rc = write_default_type_to_conf(out, pdb->p_class_val_to_name[i], class); if (rc != 0) { goto exit; } } } if (!pdb->mls) { return 0; } /* default_range */ for (i=0; i < pdb->p_classes.nprim; i++) { class = pdb->class_val_to_struct[i]; if (!class) continue; if (class->default_range != 0) { rc = write_default_range_to_conf(out, pdb->p_class_val_to_name[i], class); if (rc != 0) { goto exit; } } } exit: if (rc != 0) { ERR(NULL, "Error writing default rules to policy.conf"); } return rc; } static int map_sensitivity_aliases_to_strs(char *key, void *data, void *args) { level_datum_t *sens = data; struct strs *strs = args; int rc = 0; if (sens->isalias) { rc = strs_add(strs, key); } return rc; } static int write_sensitivity_rules_to_conf(FILE *out, struct policydb *pdb) { level_datum_t *level; struct strs *strs; char **sens_alias_map = NULL; char *name, *prev, *alias; unsigned i, j, num; int rc = 0; rc = strs_init(&strs, pdb->p_levels.nprim); if (rc != 0) { goto exit; } rc = hashtab_map(pdb->p_levels.table, map_sensitivity_aliases_to_strs, strs); if (rc != 0) { goto exit; } num = strs_num_items(strs); if (num > 0) { sens_alias_map = calloc(pdb->p_levels.nprim, sizeof(*sens_alias_map)); if (!sens_alias_map) { rc = -1; goto exit; } /* map aliases to sensitivities */ for (i=0; i < num; i++) { name = strs_read_at_index(strs, i); level = hashtab_search(pdb->p_levels.table, name); if (!level) { rc = -1; goto exit; } j = level->level->sens - 1; if (!sens_alias_map[j]) { sens_alias_map[j] = strdup(name); if (!sens_alias_map[j]) { rc = -1; goto exit; } } else { alias = sens_alias_map[j]; sens_alias_map[j] = create_str("%s %s", alias, name); free(alias); if (!sens_alias_map[j]) { rc = -1; goto exit; } } } } /* sensitivities */ for (i=0; i < pdb->p_levels.nprim; i++) { name = pdb->p_sens_val_to_name[i]; if (!name) continue; level = hashtab_search(pdb->p_levels.table, name); if (!level) { rc = -1; goto exit; } if (level->isalias) continue; if (sens_alias_map && sens_alias_map[i]) { alias = sens_alias_map[i]; if (strchr(alias, ' ')) { sepol_printf(out, "sensitivity %s alias { %s };\n", name, alias); } else { sepol_printf(out, "sensitivity %s alias %s;\n", name, alias); } } else { sepol_printf(out, "sensitivity %s;\n", name); } } /* dominance */ sepol_printf(out, "dominance { "); prev = NULL; for (i=0; i < pdb->p_levels.nprim; i++) { name = pdb->p_sens_val_to_name[i]; if (!name) continue; level = hashtab_search(pdb->p_levels.table, name); if (!level) { rc = -1; goto exit; } if (level->isalias) continue; if (prev) { sepol_printf(out, "%s ", prev); } prev = name; } if (prev) { sepol_printf(out, "%s", prev); } sepol_printf(out, " }\n"); exit: if (sens_alias_map) { for (i=0; i < pdb->p_levels.nprim; i++) { free(sens_alias_map[i]); } free(sens_alias_map); } strs_destroy(&strs); if (rc != 0) { ERR(NULL, "Error writing sensitivity rules to CIL"); } return rc; } static int map_category_aliases_to_strs(char *key, void *data, void *args) { cat_datum_t *cat = data; struct strs *strs = args; int rc = 0; if (cat->isalias) { rc = strs_add(strs, key); } return rc; } static int write_category_rules_to_conf(FILE *out, struct policydb *pdb) { cat_datum_t *cat; struct strs *strs; char **cat_alias_map = NULL; char *name, *alias; unsigned i, j, num; int rc = 0; rc = strs_init(&strs, pdb->p_cats.nprim); if (rc != 0) { goto exit; } rc = hashtab_map(pdb->p_cats.table, map_category_aliases_to_strs, strs); if (rc != 0) { goto exit; } num = strs_num_items(strs); if (num > 0) { cat_alias_map = calloc(pdb->p_cats.nprim, sizeof(*cat_alias_map)); if (!cat_alias_map) { rc = -1; goto exit; } /* map aliases to categories */ for (i=0; i < num; i++) { name = strs_read_at_index(strs, i); cat = hashtab_search(pdb->p_cats.table, name); if (!cat) { rc = -1; goto exit; } j = cat->s.value - 1; if (!cat_alias_map[j]) { cat_alias_map[j] = strdup(name); if (!cat_alias_map[j]) { rc = -1; goto exit; } } else { alias = cat_alias_map[j]; cat_alias_map[j] = create_str("%s %s", alias, name); free(alias); if (!cat_alias_map[j]) { rc = -1; goto exit; } } } } /* categories */ for (i=0; i < pdb->p_cats.nprim; i++) { name = pdb->p_cat_val_to_name[i]; if (!name) continue; cat = hashtab_search(pdb->p_cats.table, name); if (!cat) { rc = -1; goto exit; } if (cat->isalias) continue; if (cat_alias_map && cat_alias_map[i]) { alias = cat_alias_map[i]; if (strchr(alias, ' ')) { sepol_printf(out, "category %s alias { %s };\n", name, alias); } else { sepol_printf(out, "category %s alias %s;\n", name, alias); } } else { sepol_printf(out, "category %s;\n", name); } } exit: if (cat_alias_map) { for (i=0; i < pdb->p_cats.nprim; i++) { free(cat_alias_map[i]); } free(cat_alias_map); } strs_destroy(&strs); if (rc != 0) { ERR(NULL, "Error writing category rules to policy.conf"); } return rc; } static size_t cats_ebitmap_len(struct ebitmap *cats, char **val_to_name) { struct ebitmap_node *node; uint32_t i, start, range; size_t len = 0; range = 0; ebitmap_for_each_positive_bit(cats, node, i) { if (range == 0) start = i; range++; if (ebitmap_get_bit(cats, i+1)) continue; len += strlen(val_to_name[start]) + 1; if (range > 1) { len += strlen(val_to_name[i]) + 1; } range = 0; } return len; } static char *cats_ebitmap_to_str(struct ebitmap *cats, char **val_to_name) { struct ebitmap_node *node; uint32_t i, start, range, first; char *catsbuf = NULL, *p; char sep; int len, remaining; remaining = (int)cats_ebitmap_len(cats, val_to_name); if (remaining == 0) { goto exit; } catsbuf = malloc(remaining); if (!catsbuf) { goto exit; } p = catsbuf; first = 1; range = 0; ebitmap_for_each_positive_bit(cats, node, i) { if (range == 0) start = i; range++; if (ebitmap_get_bit(cats, i+1)) continue; if (range > 1) { sep = (range == 2) ? ',' : '.'; len = snprintf(p, remaining, "%s%s%c%s", first ? "" : ",", val_to_name[start], sep, val_to_name[i]); } else { len = snprintf(p, remaining, "%s%s", first ? "" : ",", val_to_name[start]); } if (len < 0 || len >= remaining) { goto exit; } p += len; remaining -= len; first = 0; range = 0; } *p = '\0'; return catsbuf; exit: free(catsbuf); return NULL; } static int write_level_rules_to_conf(FILE *out, struct policydb *pdb) { level_datum_t *level; char *name, *cats; unsigned i; int rc = 0; for (i=0; i < pdb->p_levels.nprim; i++) { name = pdb->p_sens_val_to_name[i]; if (!name) continue; level = hashtab_search(pdb->p_levels.table, name); if (!level) { rc = -1; goto exit; } if (level->isalias) continue; if (!ebitmap_is_empty(&level->level->cat)) { cats = cats_ebitmap_to_str(&level->level->cat, pdb->p_cat_val_to_name); sepol_printf(out, "level %s:%s;\n", name, cats); free(cats); } else { sepol_printf(out, "level %s;\n", name); } } exit: if (rc != 0) { ERR(NULL, "Error writing level rules to policy.conf"); } return rc; } static int write_mls_rules_to_conf(FILE *out, struct policydb *pdb) { int rc = 0; if (!pdb->mls) { return 0; } rc = write_sensitivity_rules_to_conf(out, pdb); if (rc != 0) { goto exit; } rc = write_category_rules_to_conf(out, pdb); if (rc != 0) { goto exit; } rc = write_level_rules_to_conf(out, pdb); if (rc != 0) { goto exit; } exit: if (rc != 0) { ERR(NULL, "Error writing mls rules to policy.conf"); } return rc; } static int write_polcap_rules_to_conf(FILE *out, struct policydb *pdb) { struct strs *strs; struct ebitmap_node *node; const char *name; uint32_t i; int rc = 0; rc = strs_init(&strs, 32); if (rc != 0) { goto exit; } ebitmap_for_each_positive_bit(&pdb->policycaps, node, i) { name = sepol_polcap_getname(i); if (name == NULL) { ERR(NULL, "Unknown policy capability id: %i", i); rc = -1; goto exit; } rc = strs_create_and_add(strs, "policycap %s;", name); if (rc != 0) { goto exit; } } strs_sort(strs); strs_write_each(strs, out); exit: strs_free_all(strs); strs_destroy(&strs); if (rc != 0) { ERR(NULL, "Error writing polcap rules to policy.conf"); } return rc; } static int write_type_attributes_to_conf(FILE *out, struct policydb *pdb) { type_datum_t *type; char *name; struct strs *strs; unsigned i, num; int rc = 0; rc = strs_init(&strs, pdb->p_types.nprim); if (rc != 0) { goto exit; } for (i=0; i < pdb->p_types.nprim; i++) { type = pdb->type_val_to_struct[i]; if (type && type->flavor == TYPE_ATTRIB) { rc = strs_add(strs, pdb->p_type_val_to_name[i]); if (rc != 0) { goto exit; } } } strs_sort(strs); num = strs_num_items(strs); for (i = 0; i < num; i++) { name = strs_read_at_index(strs, i); if (!name) { rc = -1; goto exit; } sepol_printf(out, "attribute %s;\n", name); } exit: strs_destroy(&strs); if (rc != 0) { ERR(NULL, "Error writing typeattribute rules to policy.conf"); } return rc; } static int write_role_attributes_to_conf(FILE *out, struct policydb *pdb) { role_datum_t *role; char *name; struct strs *strs; unsigned i, num; int rc = 0; rc = strs_init(&strs, pdb->p_roles.nprim); if (rc != 0) { goto exit; } for (i=0; i < pdb->p_roles.nprim; i++) { role = pdb->role_val_to_struct[i]; if (role && role->flavor == ROLE_ATTRIB) { rc = strs_add(strs, pdb->p_role_val_to_name[i]); if (rc != 0) { goto exit; } } } strs_sort(strs); num = strs_num_items(strs); for (i=0; istate ? "true" : "false"; return strs_create_and_add(strs, "bool %s %s;", key, value); } static int write_boolean_decl_rules_to_conf(FILE *out, struct policydb *pdb) { struct strs *strs; int rc = 0; rc = strs_init(&strs, 32); if (rc != 0) { goto exit; } rc = hashtab_map(pdb->p_bools.table, map_boolean_to_strs, strs); if (rc != 0) { goto exit; } strs_sort(strs); strs_write_each(strs, out); exit: strs_free_all(strs); strs_destroy(&strs); if (rc != 0) { ERR(NULL, "Error writing boolean declarations to policy.conf"); } return rc; } static int write_type_decl_rules_to_conf(FILE *out, struct policydb *pdb) { type_datum_t *type; struct strs *strs; char *name; unsigned i, num; int rc = 0; rc = strs_init(&strs, pdb->p_types.nprim); if (rc != 0) { goto exit; } for (i=0; i < pdb->p_types.nprim; i++) { type = pdb->type_val_to_struct[i]; if (type && type->flavor == TYPE_TYPE && type->primary) { rc = strs_add(strs, pdb->p_type_val_to_name[i]); if (rc != 0) { goto exit; } } } strs_sort(strs); num = strs_num_items(strs); for (i=0; iprimary == 0 && datum->flavor == TYPE_TYPE) (*count)++; return SEPOL_OK; } static int map_type_aliases_to_strs(char *key, void *data, void *args) { type_datum_t *datum = data; struct strs *strs = args; int rc = 0; if (datum->primary == 0 && datum->flavor == TYPE_TYPE) rc = strs_add(strs, key); return rc; } static int write_type_alias_rules_to_conf(FILE *out, struct policydb *pdb) { type_datum_t *alias; struct strs *strs = NULL; char *name; char *type; unsigned i, num = 0; int rc = 0; rc = hashtab_map(pdb->p_types.table, map_count_type_aliases, &num); if (rc != 0) { goto exit; } rc = strs_init(&strs, num); if (rc != 0) { goto exit; } rc = hashtab_map(pdb->p_types.table, map_type_aliases_to_strs, strs); if (rc != 0) { goto exit; } strs_sort(strs); for (i=0; ip_types.table, name); if (!alias) { rc = -1; goto exit; } type = pdb->p_type_val_to_name[alias->s.value - 1]; sepol_printf(out, "typealias %s alias %s;\n", type, name); } exit: strs_destroy(&strs); if (rc != 0) { ERR(NULL, "Error writing type alias rules to policy.conf"); } return rc; } static int write_type_bounds_rules_to_conf(FILE *out, struct policydb *pdb) { type_datum_t *type; struct strs *strs; char *parent; char *child; unsigned i, num; int rc = 0; rc = strs_init(&strs, pdb->p_types.nprim); if (rc != 0) { goto exit; } for (i=0; i < pdb->p_types.nprim; i++) { type = pdb->type_val_to_struct[i]; if (type && type->flavor == TYPE_TYPE) { if (type->bounds > 0) { rc = strs_add(strs, pdb->p_type_val_to_name[i]); if (rc != 0) { goto exit; } } } } strs_sort(strs); num = strs_num_items(strs); for (i=0; ip_types.table, child); if (!type) { rc = -1; goto exit; } parent = pdb->p_type_val_to_name[type->bounds - 1]; sepol_printf(out, "typebounds %s %s;\n", parent, child); } exit: strs_destroy(&strs); if (rc != 0) { ERR(NULL, "Error writing type bounds rules to policy.conf"); } return rc; } static char *attr_strs_to_str(struct strs *strs) { char *str = NULL; size_t len = 0; char *p; unsigned i; int rc; if (strs->num == 0) { goto exit; } /* 2*strs->num - 1 because ", " follows all but last attr (followed by '\0') */ len = strs_len_items(strs) + 2*strs->num - 1; str = malloc(len); if (!str) { ERR(NULL, "Out of memory"); goto exit; } p = str; for (i=0; inum; i++) { if (!strs->list[i]) continue; len = strlen(strs->list[i]); rc = snprintf(p, len+1, "%s", strs->list[i]); if (rc < 0 || rc > (int)len) { free(str); str = NULL; goto exit; } p += len; if (i < strs->num - 1) { *p++ = ','; *p++ = ' '; } } *p = '\0'; exit: return str; } static char *attrmap_to_str(struct ebitmap *map, char **val_to_name) { struct strs *strs; char *str = NULL; int rc; rc = strs_init(&strs, 32); if (rc != 0) { goto exit; } rc = ebitmap_to_strs(map, strs, val_to_name); if (rc != 0) { goto exit; } strs_sort(strs); str = attr_strs_to_str(strs); exit: strs_destroy(&strs); return str; } static int write_type_attribute_sets_to_conf(FILE *out, struct policydb *pdb) { type_datum_t *type; struct strs *strs; ebitmap_t attrmap; char *name, *attrs; unsigned i; int rc; rc = strs_init(&strs, pdb->p_types.nprim); if (rc != 0) { goto exit; } for (i=0; i < pdb->p_types.nprim; i++) { type = pdb->type_val_to_struct[i]; if (!type || type->flavor != TYPE_TYPE || !type->primary) continue; if (ebitmap_cardinality(&pdb->type_attr_map[i]) == 1) continue; rc = ebitmap_cpy(&attrmap, &pdb->type_attr_map[i]); if (rc != 0) { goto exit; } rc = ebitmap_set_bit(&attrmap, i, 0); if (rc != 0) { ebitmap_destroy(&attrmap); goto exit; } name = pdb->p_type_val_to_name[i]; attrs = attrmap_to_str(&attrmap, pdb->p_type_val_to_name); ebitmap_destroy(&attrmap); if (!attrs) { rc = -1; goto exit; } rc = strs_create_and_add(strs, "typeattribute %s %s;", name, attrs); free(attrs); if (rc != 0) { goto exit; } } strs_sort(strs); strs_write_each(strs, out); exit: strs_free_all(strs); strs_destroy(&strs); if (rc != 0) { ERR(NULL, "Error writing typeattributeset rules to policy.conf"); } return rc; } static int write_type_permissive_rules_to_conf(FILE *out, struct policydb *pdb) { struct strs *strs; char *name; struct ebitmap_node *node; unsigned i, num; int rc = 0; rc = strs_init(&strs, pdb->p_types.nprim); if (rc != 0) { goto exit; } ebitmap_for_each_positive_bit(&pdb->permissive_map, node, i) { rc = strs_add(strs, pdb->p_type_val_to_name[i-1]); if (rc != 0) { goto exit; } } strs_sort(strs); num = strs_num_items(strs); for (i=0; idata; type_datum_t *type; const char *flavor, *src, *tgt, *class, *new; char *rule = NULL, *permstring; switch (0xFFF & key->specified) { case AVTAB_ALLOWED: flavor = "allow"; break; case AVTAB_AUDITALLOW: flavor = "auditallow"; break; case AVTAB_AUDITDENY: flavor = "dontaudit"; data = ~data; break; case AVTAB_XPERMS_ALLOWED: flavor = "allowxperm"; break; case AVTAB_XPERMS_AUDITALLOW: flavor = "auditallowxperm"; break; case AVTAB_XPERMS_DONTAUDIT: flavor = "dontauditxperm"; break; case AVTAB_TRANSITION: flavor = "type_transition"; break; case AVTAB_MEMBER: flavor = "type_member"; break; case AVTAB_CHANGE: flavor = "type_change"; break; default: ERR(NULL, "Unknown avtab type: %i", key->specified); goto exit; } src = pdb->p_type_val_to_name[key->source_type - 1]; tgt = pdb->p_type_val_to_name[key->target_type - 1]; if (key->source_type == key->target_type && !(key->specified & AVTAB_TYPE)) { type = pdb->type_val_to_struct[key->source_type - 1]; if (type->flavor != TYPE_ATTRIB) { tgt = "self"; } } class = pdb->p_class_val_to_name[key->target_class - 1]; if (key->specified & AVTAB_AV) { permstring = sepol_av_to_string(pdb, key->target_class, data); if (permstring == NULL) { ERR(NULL, "Failed to generate permission string"); goto exit; } if (*permstring == '\0') { ERR(NULL, "No permissions in permission string"); free(permstring); goto exit; } rule = create_str("%s %s %s:%s { %s };", flavor, src, tgt, class, permstring+1); free(permstring); } else if (key->specified & AVTAB_XPERMS) { permstring = sepol_extended_perms_to_string(datum->xperms); if (permstring == NULL) { ERR(NULL, "Failed to generate extended permission string"); goto exit; } rule = create_str("%s %s %s:%s %s;", flavor, src, tgt, class, permstring); free(permstring); } else { new = pdb->p_type_val_to_name[data - 1]; rule = create_str("%s %s %s:%s %s;", flavor, src, tgt, class, new); } if (!rule) { goto exit; } return rule; exit: return NULL; } struct map_avtab_args { struct policydb *pdb; uint32_t flavor; struct strs *strs; }; static int map_avtab_write_helper(avtab_key_t *key, avtab_datum_t *datum, void *args) { struct map_avtab_args *map_args = args; uint32_t flavor = map_args->flavor; struct policydb *pdb = map_args->pdb; struct strs *strs = map_args->strs; char *rule; int rc = 0; if (key->specified & flavor) { rule = avtab_node_to_str(pdb, key, datum); if (!rule) { rc = -1; goto exit; } rc = strs_add(strs, rule); if (rc != 0) { free(rule); goto exit; } } exit: return rc; } static int write_avtab_flavor_to_conf(FILE *out, struct policydb *pdb, uint32_t flavor, int indent) { struct map_avtab_args args; struct strs *strs; int rc = 0; rc = strs_init(&strs, 1000); if (rc != 0) { goto exit; } args.pdb = pdb; args.flavor = flavor; args.strs = strs; rc = avtab_map(&pdb->te_avtab, map_avtab_write_helper, &args); if (rc != 0) { goto exit; } strs_sort(strs); strs_write_each_indented(strs, out, indent); exit: strs_free_all(strs); strs_destroy(&strs); return rc; } static int write_avtab_to_conf(FILE *out, struct policydb *pdb, int indent) { unsigned i; int rc = 0; for (i = 0; i < AVTAB_FLAVORS_SZ; i++) { rc = write_avtab_flavor_to_conf(out, pdb, avtab_flavors[i], indent); if (rc != 0) { goto exit; } } exit: if (rc != 0) { ERR(NULL, "Error writing avtab rules to policy.conf"); } return rc; } struct map_filename_trans_args { struct policydb *pdb; struct strs *strs; }; static int map_filename_trans_to_str(hashtab_key_t key, void *data, void *arg) { filename_trans_key_t *ft = (filename_trans_key_t *)key; filename_trans_datum_t *datum = data; struct map_filename_trans_args *map_args = arg; struct policydb *pdb = map_args->pdb; struct strs *strs = map_args->strs; char *src, *tgt, *class, *filename, *new; struct ebitmap_node *node; uint32_t bit; int rc; tgt = pdb->p_type_val_to_name[ft->ttype - 1]; class = pdb->p_class_val_to_name[ft->tclass - 1]; filename = ft->name; do { new = pdb->p_type_val_to_name[datum->otype - 1]; ebitmap_for_each_positive_bit(&datum->stypes, node, bit) { src = pdb->p_type_val_to_name[bit]; rc = strs_create_and_add(strs, "type_transition %s %s:%s %s \"%s\";", src, tgt, class, new, filename); if (rc) return rc; } datum = datum->next; } while (datum); return 0; } static int write_filename_trans_rules_to_conf(FILE *out, struct policydb *pdb) { struct map_filename_trans_args args; struct strs *strs; int rc = 0; rc = strs_init(&strs, 100); if (rc != 0) { goto exit; } args.pdb = pdb; args.strs = strs; rc = hashtab_map(pdb->filename_trans, map_filename_trans_to_str, &args); if (rc != 0) { goto exit; } strs_sort(strs); strs_write_each(strs, out); exit: strs_free_all(strs); strs_destroy(&strs); if (rc != 0) { ERR(NULL, "Error writing filename typetransition rules to policy.conf"); } return rc; } static char *level_to_str(struct policydb *pdb, struct mls_level *level) { ebitmap_t *cats = &level->cat; char *level_str = NULL; char *sens_str = pdb->p_sens_val_to_name[level->sens - 1]; char *cats_str; if (!ebitmap_is_empty(cats)) { cats_str = cats_ebitmap_to_str(cats, pdb->p_cat_val_to_name); level_str = create_str("%s:%s", sens_str, cats_str); free(cats_str); } else { level_str = create_str("%s", sens_str); } return level_str; } static char *range_to_str(struct policydb *pdb, mls_range_t *range) { char *low = NULL; char *high = NULL; char *range_str = NULL; low = level_to_str(pdb, &range->level[0]); if (!low) { goto exit; } high = level_to_str(pdb, &range->level[1]); if (!high) { goto exit; } range_str = create_str("%s - %s", low, high); exit: free(low); free(high); return range_str; } struct map_range_trans_args { struct policydb *pdb; struct strs *strs; }; static int map_range_trans_to_str(hashtab_key_t key, void *data, void *arg) { range_trans_t *rt = (range_trans_t *)key; mls_range_t *mls_range = data; struct map_range_trans_args *map_args = arg; struct policydb *pdb = map_args->pdb; struct strs *strs = map_args->strs; char *src, *tgt, *class, *range; int rc; src = pdb->p_type_val_to_name[rt->source_type - 1]; tgt = pdb->p_type_val_to_name[rt->target_type - 1]; class = pdb->p_class_val_to_name[rt->target_class - 1]; range = range_to_str(pdb, mls_range); if (!range) { rc = -1; goto exit; } rc = strs_create_and_add(strs, "range_transition %s %s:%s %s;", src, tgt, class, range); free(range); if (rc != 0) { goto exit; } exit: return rc; } static int write_range_trans_rules_to_conf(FILE *out, struct policydb *pdb) { struct map_range_trans_args args; struct strs *strs; int rc = 0; rc = strs_init(&strs, 100); if (rc != 0) { goto exit; } args.pdb = pdb; args.strs = strs; rc = hashtab_map(pdb->range_tr, map_range_trans_to_str, &args); if (rc != 0) { goto exit; } strs_sort(strs); strs_write_each(strs, out); exit: strs_free_all(strs); strs_destroy(&strs); if (rc != 0) { ERR(NULL, "Error writing range transition rules to policy.conf"); } return rc; } static int write_cond_av_list_to_conf(FILE *out, struct policydb *pdb, cond_av_list_t *cond_list, int indent) { cond_av_list_t *cond_av; avtab_ptr_t node; uint32_t flavor; avtab_key_t *key; avtab_datum_t *datum; struct strs *strs; char *rule; unsigned i; int rc; for (i = 0; i < AVTAB_FLAVORS_SZ; i++) { flavor = avtab_flavors[i]; rc = strs_init(&strs, 64); if (rc != 0) { goto exit; } for (cond_av = cond_list; cond_av != NULL; cond_av = cond_av->next) { node = cond_av->node; key = &node->key; datum = &node->datum; if (key->specified & flavor) { rule = avtab_node_to_str(pdb, key, datum); if (!rule) { rc = -1; goto exit; } rc = strs_add(strs, rule); if (rc != 0) { free(rule); goto exit; } } } strs_sort(strs); strs_write_each_indented(strs, out, indent); strs_free_all(strs); strs_destroy(&strs); } return 0; exit: strs_free_all(strs); strs_destroy(&strs); return rc; } struct cond_data { char *expr; struct cond_node *cond; }; static int cond_node_cmp(const void *a, const void *b) { const struct cond_data *aa = a; const struct cond_data *bb = b; return strcmp(aa->expr, bb->expr); } static int write_cond_nodes_to_conf(FILE *out, struct policydb *pdb) { struct cond_data *cond_data; char *expr; struct cond_node *cond; unsigned i, num; int rc = 0; num = 0; for (cond = pdb->cond_list; cond != NULL; cond = cond->next) { num++; } if (num == 0) { return 0; } cond_data = calloc(num, sizeof(struct cond_data)); if (!cond_data) { rc = -1; goto exit; } i = 0; for (cond = pdb->cond_list; cond != NULL; cond = cond->next) { cond_data[i].cond = cond; expr = cond_expr_to_str(pdb, cond->expr); if (!expr) { num = i; goto exit; } cond_data[i].expr = expr; i++; } qsort(cond_data, num, sizeof(*cond_data), cond_node_cmp); for (i=0; itrue_list != NULL) { rc = write_cond_av_list_to_conf(out, pdb, cond->true_list, 1); if (rc != 0) { goto exit; } } if (cond->false_list != NULL) { sepol_printf(out, "} else {\n"); rc = write_cond_av_list_to_conf(out, pdb, cond->false_list, 1); if (rc != 0) { goto exit; } } sepol_printf(out, "}\n"); } exit: if (cond_data) { for (i=0; ip_roles.nprim); if (rc != 0) { goto exit; } /* Start at 1 to skip object_r */ for (i=1; i < pdb->p_roles.nprim; i++) { role = pdb->role_val_to_struct[i]; if (role && role->flavor == ROLE_ROLE) { rc = strs_add(strs, pdb->p_role_val_to_name[i]); if (rc != 0) { goto exit; } } } strs_sort(strs); num = strs_num_items(strs); for (i=0; ip_roles.table, name); if (!role) { rc = -1; goto exit; } if (ebitmap_is_empty(&role->types.types)) continue; types = ebitmap_to_str(&role->types.types, pdb->p_type_val_to_name, 1); if (!types) { rc = -1; goto exit; } if (strlen(types) > 900) { p1 = types; while (p1) { p2 = p1; while (p2 - p1 < 600) { p2 = strchr(p2, ' '); if (!p2) break; p2++; } if (p2) { *(p2-1) = '\0'; } sepol_printf(out, "role %s types { %s };\n", name, p1); p1 = p2; } } else { sepol_printf(out, "role %s types { %s };\n", name, types); } free(types); } exit: strs_destroy(&strs); if (rc != 0) { ERR(NULL, "Error writing role declarations to policy.conf"); } return rc; } static int write_role_transition_rules_to_conf(FILE *out, struct policydb *pdb) { role_trans_t *curr = pdb->role_tr; struct strs *strs; char *role, *type, *class, *new; int rc = 0; rc = strs_init(&strs, 32); if (rc != 0) { goto exit; } while (curr) { role = pdb->p_role_val_to_name[curr->role - 1]; type = pdb->p_type_val_to_name[curr->type - 1]; class = pdb->p_class_val_to_name[curr->tclass - 1]; new = pdb->p_role_val_to_name[curr->new_role - 1]; rc = strs_create_and_add(strs, "role_transition %s %s:%s %s;", role, type, class, new); if (rc != 0) { goto exit; } curr = curr->next; } strs_sort(strs); strs_write_each(strs, out); exit: strs_free_all(strs); strs_destroy(&strs); if (rc != 0) { ERR(NULL, "Error writing role transition rules to policy.conf"); } return rc; } static int write_role_allow_rules_to_conf(FILE *out, struct policydb *pdb) { role_allow_t *curr = pdb->role_allow; struct strs *strs; char *role, *new; int rc = 0; rc = strs_init(&strs, 32); if (rc != 0) { goto exit; } while (curr) { role = pdb->p_role_val_to_name[curr->role - 1]; new = pdb->p_role_val_to_name[curr->new_role - 1]; rc = strs_create_and_add(strs, "allow %s %s;", role, new); if (rc != 0) { goto exit; } curr = curr->next; } strs_sort(strs); strs_write_each(strs, out); exit: strs_free_all(strs); strs_destroy(&strs); if (rc != 0) { ERR(NULL, "Error writing role allow rules to policy.conf"); } return rc; } static int write_user_decl_rules_to_conf(FILE *out, struct policydb *pdb) { struct user_datum *user; struct strs *strs; char *name, *roles, *level, *range; unsigned i, num; int rc = 0; rc = strs_init(&strs, pdb->p_users.nprim); if (rc != 0) { goto exit; } for (i=0; i < pdb->p_users.nprim; i++) { if (!pdb->p_user_val_to_name[i]) continue; rc = strs_add(strs, pdb->p_user_val_to_name[i]); if (rc != 0) { goto exit; } } strs_sort(strs); num = strs_num_items(strs); for (i=0; ip_users.table, name); if (!user) { rc = -1; goto exit; } sepol_printf(out, "user %s", name); if (!ebitmap_is_empty(&user->roles.roles)) { roles = ebitmap_to_str(&user->roles.roles, pdb->p_role_val_to_name, 1); if (!roles) { rc = -1; goto exit; } if (strchr(roles, ' ')) { sepol_printf(out, " roles { %s }", roles); } else { sepol_printf(out, " roles %s", roles); } free(roles); } if (pdb->mls) { level = level_to_str(pdb, &user->exp_dfltlevel); if (!level) { rc = -1; goto exit; } sepol_printf(out, " level %s", level); free(level); range = range_to_str(pdb, &user->exp_range); if (!range) { rc = -1; goto exit; } sepol_printf(out, " range %s", range); free(range); } sepol_printf(out, ";\n"); } exit: if (strs) strs_destroy(&strs); if (rc != 0) { ERR(NULL, "Error writing user declarations to policy.conf"); } return rc; } static char *context_to_str(struct policydb *pdb, struct context_struct *con) { char *user, *role, *type, *range; char *ctx = NULL; user = pdb->p_user_val_to_name[con->user - 1]; role = pdb->p_role_val_to_name[con->role - 1]; type = pdb->p_type_val_to_name[con->type - 1]; if (pdb->mls) { range = range_to_str(pdb, &con->range); ctx = create_str("%s:%s:%s:%s", user, role, type, range); free(range); } else { ctx = create_str("%s:%s:%s", user, role, type); } return ctx; } static int write_sid_context_rules_to_conf(FILE *out, struct policydb *pdb, const char *const *sid_to_str, unsigned num_sids) { struct ocontext *isid; struct strs *strs; char *sid; char unknown[18]; char *ctx, *rule; unsigned i; int rc; rc = strs_init(&strs, 32); if (rc != 0) { goto exit; } for (isid = pdb->ocontexts[0]; isid != NULL; isid = isid->next) { i = isid->sid[0]; if (i < num_sids && sid_to_str[i]) { sid = (char *)sid_to_str[i]; } else { snprintf(unknown, sizeof(unknown), "%s%u", "UNKNOWN", i); sid = unknown; } ctx = context_to_str(pdb, &isid->context[0]); if (!ctx) { rc = -1; goto exit; } rule = create_str("sid %s %s", sid, ctx); free(ctx); if (!rule) { rc = -1; goto exit; } rc = strs_add_at_index(strs, rule, i); if (rc != 0) { free(rule); goto exit; } } strs_write_each(strs, out); exit: strs_free_all(strs); strs_destroy(&strs); if (rc != 0) { ERR(NULL, "Error writing sidcontext rules to policy.conf"); } return rc; } static int write_selinux_isid_rules_to_conf(FILE *out, struct policydb *pdb) { return write_sid_context_rules_to_conf(out, pdb, selinux_sid_to_str, SELINUX_SID_SZ); } static int write_selinux_fsuse_rules_to_conf(FILE *out, struct policydb *pdb) { struct ocontext *fsuse; const char *behavior; char *name, *ctx; int rc = 0; for (fsuse = pdb->ocontexts[5]; fsuse != NULL; fsuse = fsuse->next) { switch (fsuse->v.behavior) { case SECURITY_FS_USE_XATTR: behavior = "xattr"; break; case SECURITY_FS_USE_TRANS: behavior = "trans"; break; case SECURITY_FS_USE_TASK: behavior = "task"; break; default: ERR(NULL, "Unknown fsuse behavior: %i", fsuse->v.behavior); rc = -1; goto exit; } name = fsuse->u.name; ctx = context_to_str(pdb, &fsuse->context[0]); if (!ctx) { rc = -1; goto exit; } sepol_printf(out, "fs_use_%s %s %s;\n", behavior, name, ctx); free(ctx); } exit: if (rc != 0) { ERR(NULL, "Error writing fsuse rules to policy.conf"); } return rc; } static int write_genfscon_rules_to_conf(FILE *out, struct policydb *pdb) { struct genfs *genfs; struct ocontext *ocon; struct strs *strs; char *fstype, *name, *ctx; uint32_t sclass; const char *file_type; int rc; rc = strs_init(&strs, 32); if (rc != 0) { goto exit; } for (genfs = pdb->genfs; genfs != NULL; genfs = genfs->next) { for (ocon = genfs->head; ocon != NULL; ocon = ocon->next) { fstype = genfs->fstype; name = ocon->u.name; sclass = ocon->v.sclass; file_type = NULL; if (sclass) { const char *class_name = pdb->p_class_val_to_name[sclass-1]; if (strcmp(class_name, "file") == 0) { file_type = "--"; } else if (strcmp(class_name, "dir") == 0) { file_type = "-d"; } else if (strcmp(class_name, "chr_file") == 0) { file_type = "-c"; } else if (strcmp(class_name, "blk_file") == 0) { file_type = "-b"; } else if (strcmp(class_name, "sock_file") == 0) { file_type = "-s"; } else if (strcmp(class_name, "fifo_file") == 0) { file_type = "-p"; } else if (strcmp(class_name, "lnk_file") == 0) { file_type = "-l"; } else { rc = -1; goto exit; } } ctx = context_to_str(pdb, &ocon->context[0]); if (!ctx) { rc = -1; goto exit; } if (file_type) { rc = strs_create_and_add(strs, "genfscon %s \"%s\" %s %s", fstype, name, file_type, ctx); } else { rc = strs_create_and_add(strs, "genfscon %s \"%s\" %s", fstype, name, ctx); } free(ctx); if (rc != 0) { goto exit; } } } strs_sort(strs); strs_write_each(strs, out); exit: strs_free_all(strs); strs_destroy(&strs); if (rc != 0) { ERR(NULL, "Error writing genfscon rules to policy.conf"); } return rc; } static int write_selinux_port_rules_to_conf(FILE *out, struct policydb *pdb) { struct ocontext *portcon; const char *protocol; uint16_t low; uint16_t high; char low_high_str[44]; /* 2^64 <= 20 digits so "low-high" <= 44 chars */ char *ctx; int rc = 0; for (portcon = pdb->ocontexts[2]; portcon != NULL; portcon = portcon->next) { switch (portcon->u.port.protocol) { case IPPROTO_TCP: protocol = "tcp"; break; case IPPROTO_UDP: protocol = "udp"; break; case IPPROTO_DCCP: protocol = "dccp"; break; case IPPROTO_SCTP: protocol = "sctp"; break; default: ERR(NULL, "Unknown portcon protocol: %i", portcon->u.port.protocol); rc = -1; goto exit; } low = portcon->u.port.low_port; high = portcon->u.port.high_port; if (low == high) { rc = snprintf(low_high_str, 44, "%u", low); } else { rc = snprintf(low_high_str, 44, "%u-%u", low, high); } if (rc < 0 || rc >= 44) { rc = -1; goto exit; } ctx = context_to_str(pdb, &portcon->context[0]); if (!ctx) { rc = -1; goto exit; } sepol_printf(out, "portcon %s %s %s\n", protocol, low_high_str, ctx); free(ctx); } rc = 0; exit: if (rc != 0) { ERR(NULL, "Error writing portcon rules to policy.conf"); } return rc; } static int write_selinux_netif_rules_to_conf(FILE *out, struct policydb *pdb) { struct ocontext *netif; char *name, *ctx1, *ctx2; int rc = 0; for (netif = pdb->ocontexts[3]; netif != NULL; netif = netif->next) { name = netif->u.name; ctx1 = context_to_str(pdb, &netif->context[0]); if (!ctx1) { rc = -1; goto exit; } ctx2 = context_to_str(pdb, &netif->context[1]); if (!ctx2) { free(ctx1); rc = -1; goto exit; } sepol_printf(out, "netifcon %s %s %s\n", name, ctx1, ctx2); free(ctx1); free(ctx2); } exit: if (rc != 0) { ERR(NULL, "Error writing netifcon rules to policy.conf"); } return rc; } static int write_selinux_node_rules_to_conf(FILE *out, struct policydb *pdb) { struct ocontext *node; char addr[INET_ADDRSTRLEN]; char mask[INET_ADDRSTRLEN]; char *ctx; int rc = 0; for (node = pdb->ocontexts[4]; node != NULL; node = node->next) { if (inet_ntop(AF_INET, &node->u.node.addr, addr, INET_ADDRSTRLEN) == NULL) { ERR(NULL, "Nodecon address is invalid: %m"); rc = -1; goto exit; } if (inet_ntop(AF_INET, &node->u.node.mask, mask, INET_ADDRSTRLEN) == NULL) { ERR(NULL, "Nodecon mask is invalid: %m"); rc = -1; goto exit; } ctx = context_to_str(pdb, &node->context[0]); if (!ctx) { rc = -1; goto exit; } sepol_printf(out, "nodecon %s %s %s\n", addr, mask, ctx); free(ctx); } exit: if (rc != 0) { ERR(NULL, "Error writing nodecon rules to policy.conf"); } return rc; } static int write_selinux_node6_rules_to_conf(FILE *out, struct policydb *pdb) { struct ocontext *node6; char addr[INET6_ADDRSTRLEN]; char mask[INET6_ADDRSTRLEN]; char *ctx; int rc = 0; for (node6 = pdb->ocontexts[6]; node6 != NULL; node6 = node6->next) { if (inet_ntop(AF_INET6, &node6->u.node6.addr, addr, INET6_ADDRSTRLEN) == NULL) { ERR(NULL, "Nodecon address is invalid: %m"); rc = -1; goto exit; } if (inet_ntop(AF_INET6, &node6->u.node6.mask, mask, INET6_ADDRSTRLEN) == NULL) { ERR(NULL, "Nodecon mask is invalid: %m"); rc = -1; goto exit; } ctx = context_to_str(pdb, &node6->context[0]); if (!ctx) { rc = -1; goto exit; } sepol_printf(out, "nodecon %s %s %s\n", addr, mask, ctx); free(ctx); } exit: if (rc != 0) { ERR(NULL, "Error writing nodecon rules to policy.conf"); } return rc; } static int write_selinux_ibpkey_rules_to_conf(FILE *out, struct policydb *pdb) { struct ocontext *ibpkeycon; char subnet_prefix_str[INET6_ADDRSTRLEN]; struct in6_addr subnet_prefix = IN6ADDR_ANY_INIT; uint16_t low; uint16_t high; char low_high_str[44]; /* 2^64 <= 20 digits so "low-high" <= 44 chars */ char *ctx; int rc = 0; for (ibpkeycon = pdb->ocontexts[OCON_IBPKEY]; ibpkeycon != NULL; ibpkeycon = ibpkeycon->next) { memcpy(&subnet_prefix.s6_addr, &ibpkeycon->u.ibpkey.subnet_prefix, sizeof(ibpkeycon->u.ibpkey.subnet_prefix)); if (inet_ntop(AF_INET6, &subnet_prefix.s6_addr, subnet_prefix_str, INET6_ADDRSTRLEN) == NULL) { ERR(NULL, "ibpkeycon address is invalid: %m"); rc = -1; goto exit; } low = ibpkeycon->u.ibpkey.low_pkey; high = ibpkeycon->u.ibpkey.high_pkey; if (low == high) { rc = snprintf(low_high_str, 44, "%u", low); } else { rc = snprintf(low_high_str, 44, "%u-%u", low, high); } if (rc < 0 || rc >= 44) { rc = -1; goto exit; } ctx = context_to_str(pdb, &ibpkeycon->context[0]); if (!ctx) { rc = -1; goto exit; } sepol_printf(out, "ibpkeycon %s %s %s\n", subnet_prefix_str, low_high_str, ctx); free(ctx); } rc = 0; exit: if (rc != 0) { ERR(NULL, "Error writing ibpkeycon rules to policy.conf"); } return rc; } static int write_selinux_ibendport_rules_to_conf(FILE *out, struct policydb *pdb) { struct ocontext *ibendportcon; char port_str[4]; char *ctx; int rc = 0; for (ibendportcon = pdb->ocontexts[OCON_IBENDPORT]; ibendportcon != NULL; ibendportcon = ibendportcon->next) { rc = snprintf(port_str, 4, "%u", ibendportcon->u.ibendport.port); if (rc < 0 || rc >= 4) { rc = -1; goto exit; } ctx = context_to_str(pdb, &ibendportcon->context[0]); if (!ctx) { rc = -1; goto exit; } sepol_printf(out, "ibendportcon %s %s %s\n", ibendportcon->u.ibendport.dev_name, port_str, ctx); free(ctx); } rc = 0; exit: if (rc != 0) { ERR(NULL, "Error writing ibendportcon rules to policy.conf"); } return rc; } static int write_xen_isid_rules_to_conf(FILE *out, struct policydb *pdb) { return write_sid_context_rules_to_conf(out, pdb, xen_sid_to_str, XEN_SID_SZ); } static int write_xen_pirq_rules_to_conf(FILE *out, struct policydb *pdb) { struct ocontext *pirq; char pirq_str[21]; /* 2^64-1 <= 20 digits */ char *ctx; int rc = 0; for (pirq = pdb->ocontexts[1]; pirq != NULL; pirq = pirq->next) { rc = snprintf(pirq_str, 21, "%i", pirq->u.pirq); if (rc < 0 || rc >= 21) { rc = -1; goto exit; } ctx = context_to_str(pdb, &pirq->context[0]); if (!ctx) { rc = -1; goto exit; } sepol_printf(out, "pirqcon %s %s\n", pirq_str, ctx); free(ctx); } rc = 0; exit: if (rc != 0) { ERR(NULL, "Error writing pirqcon rules to policy.conf"); } return rc; } static int write_xen_ioport_rules_to_conf(FILE *out, struct policydb *pdb) { struct ocontext *ioport; uint32_t low; uint32_t high; char low_high_str[40]; /* 2^64-1 <= 16 digits (hex) so low-high < 40 chars */ char *ctx; int rc = 0; for (ioport = pdb->ocontexts[2]; ioport != NULL; ioport = ioport->next) { low = ioport->u.ioport.low_ioport; high = ioport->u.ioport.high_ioport; if (low == high) { rc = snprintf(low_high_str, 40, "0x%x", low); } else { rc = snprintf(low_high_str, 40, "0x%x-0x%x", low, high); } if (rc < 0 || rc >= 40) { rc = -1; goto exit; } ctx = context_to_str(pdb, &ioport->context[0]); if (!ctx) { rc = -1; goto exit; } sepol_printf(out, "ioportcon %s %s\n", low_high_str, ctx); free(ctx); } rc = 0; exit: if (rc != 0) { ERR(NULL, "Error writing ioportcon rules to policy.conf"); } return rc; } static int write_xen_iomem_rules_to_conf(FILE *out, struct policydb *pdb) { struct ocontext *iomem; uint64_t low; uint64_t high; char low_high_str[40]; /* 2^64-1 <= 16 digits (hex) so low-high < 40 chars */ char *ctx; int rc = 0; for (iomem = pdb->ocontexts[3]; iomem != NULL; iomem = iomem->next) { low = iomem->u.iomem.low_iomem; high = iomem->u.iomem.high_iomem; if (low == high) { rc = snprintf(low_high_str, 40, "0x%"PRIx64, low); } else { rc = snprintf(low_high_str, 40, "0x%"PRIx64"-0x%"PRIx64, low, high); } if (rc < 0 || rc >= 40) { rc = -1; goto exit; } ctx = context_to_str(pdb, &iomem->context[0]); if (!ctx) { rc = -1; goto exit; } sepol_printf(out, "iomemcon %s %s\n", low_high_str, ctx); free(ctx); } rc = 0; exit: if (rc != 0) { ERR(NULL, "Error writing iomemcon rules to policy.conf"); } return rc; } static int write_xen_pcidevice_rules_to_conf(FILE *out, struct policydb *pdb) { struct ocontext *pcid; char device_str[20]; /* 2^64-1 <= 16 digits (hex) so < 19 chars */ char *ctx; int rc = 0; for (pcid = pdb->ocontexts[4]; pcid != NULL; pcid = pcid->next) { rc = snprintf(device_str, 20, "0x%lx", (unsigned long)pcid->u.device); if (rc < 0 || rc >= 20) { rc = -1; goto exit; } ctx = context_to_str(pdb, &pcid->context[0]); if (!ctx) { rc = -1; goto exit; } sepol_printf(out, "pcidevicecon %s %s\n", device_str, ctx); free(ctx); } rc = 0; exit: if (rc != 0) { ERR(NULL, "Error writing pcidevicecon rules to policy.conf"); } return rc; } static int write_xen_devicetree_rules_to_conf(FILE *out, struct policydb *pdb) { struct ocontext *dtree; char *name, *ctx; int rc = 0; for (dtree = pdb->ocontexts[5]; dtree != NULL; dtree = dtree->next) { name = dtree->u.name; ctx = context_to_str(pdb, &dtree->context[0]); if (!ctx) { rc = -1; goto exit; } sepol_printf(out, "devicetreecon \"%s\" %s\n", name, ctx); free(ctx); } exit: if (rc != 0) { ERR(NULL, "Error writing devicetreecon rules to policy.conf"); } return rc; } int sepol_kernel_policydb_to_conf(FILE *out, struct policydb *pdb) { struct strs *mls_constraints = NULL; struct strs *non_mls_constraints = NULL; struct strs *mls_validatetrans = NULL; struct strs *non_mls_validatetrans = NULL; int rc = 0; rc = strs_init(&mls_constraints, 32); if (rc != 0) { goto exit; } rc = strs_init(&non_mls_constraints, 32); if (rc != 0) { goto exit; } rc = strs_init(&mls_validatetrans, 32); if (rc != 0) { goto exit; } rc = strs_init(&non_mls_validatetrans, 32); if (rc != 0) { goto exit; } if (pdb == NULL) { ERR(NULL, "No policy"); rc = -1; goto exit; } if (pdb->policy_type != SEPOL_POLICY_KERN) { ERR(NULL, "Policy is not a kernel policy"); rc = -1; goto exit; } if (pdb->policyvers >= POLICYDB_VERSION_AVTAB && pdb->policyvers <= POLICYDB_VERSION_PERMISSIVE) { /* * For policy versions between 20 and 23, attributes exist in the policy, * but only in the type_attr_map. This means that there are gaps in both * the type_val_to_struct and p_type_val_to_name arrays and policy rules * can refer to those gaps. */ ERR(NULL, "Writing policy versions between 20 and 23 as a policy.conf is not supported"); rc = -1; goto exit; } rc = constraint_rules_to_strs(pdb, mls_constraints, non_mls_constraints); if (rc != 0) { goto exit; } rc = validatetrans_rules_to_strs(pdb, mls_validatetrans, non_mls_validatetrans); if (rc != 0) { goto exit; } rc = write_handle_unknown_to_conf(out, pdb); if (rc != 0) { goto exit; } rc = write_class_decl_rules_to_conf(out, pdb); if (rc != 0) { goto exit; } rc = write_sid_decl_rules_to_conf(out, pdb); if (rc != 0) { goto exit; } rc = write_class_and_common_rules_to_conf(out, pdb); if (rc != 0) { goto exit; } rc = write_default_rules_to_conf(out, pdb); if (rc != 0) { goto exit; } rc = write_mls_rules_to_conf(out, pdb); if (rc != 0) { goto exit; } strs_write_each(mls_constraints, out); strs_write_each(mls_validatetrans, out); rc = write_polcap_rules_to_conf(out, pdb); if (rc != 0) { goto exit; } rc = write_type_attributes_to_conf(out, pdb); if (rc != 0) { goto exit; } rc = write_role_attributes_to_conf(out, pdb); if (rc != 0) { goto exit; } rc = write_boolean_decl_rules_to_conf(out, pdb); if (rc != 0) { goto exit; } rc = write_type_decl_rules_to_conf(out, pdb); if (rc != 0) { goto exit; } rc = write_type_alias_rules_to_conf(out, pdb); if (rc != 0) { goto exit; } rc = write_type_bounds_rules_to_conf(out, pdb); if (rc != 0) { goto exit; } rc = write_type_attribute_sets_to_conf(out, pdb); if (rc != 0) { goto exit; } rc = write_type_permissive_rules_to_conf(out, pdb); if (rc != 0) { goto exit; } rc = write_avtab_to_conf(out, pdb, 0); if (rc != 0) { goto exit; } write_filename_trans_rules_to_conf(out, pdb); if (pdb->mls) { rc = write_range_trans_rules_to_conf(out, pdb); if (rc != 0) { goto exit; } } rc = write_cond_nodes_to_conf(out, pdb); if (rc != 0) { goto exit; } rc = write_role_decl_rules_to_conf(out, pdb); if (rc != 0) { goto exit; } rc = write_role_transition_rules_to_conf(out, pdb); if (rc != 0) { goto exit; } rc = write_role_allow_rules_to_conf(out, pdb); if (rc != 0) { goto exit; } rc = write_user_decl_rules_to_conf(out, pdb); if (rc != 0) { goto exit; } strs_write_each(non_mls_constraints, out); strs_write_each(non_mls_validatetrans, out); rc = sort_ocontexts(pdb); if (rc != 0) { goto exit; } if (pdb->target_platform == SEPOL_TARGET_SELINUX) { rc = write_selinux_isid_rules_to_conf(out, pdb); if (rc != 0) { goto exit; } rc = write_selinux_fsuse_rules_to_conf(out, pdb); if (rc != 0) { goto exit; } rc = write_genfscon_rules_to_conf(out, pdb); if (rc != 0) { goto exit; } rc = write_selinux_port_rules_to_conf(out, pdb); if (rc != 0) { goto exit; } rc = write_selinux_netif_rules_to_conf(out, pdb); if (rc != 0) { goto exit; } rc = write_selinux_node_rules_to_conf(out, pdb); if (rc != 0) { goto exit; } rc = write_selinux_node6_rules_to_conf(out, pdb); if (rc != 0) { goto exit; } rc = write_selinux_ibpkey_rules_to_conf(out, pdb); if (rc != 0) { goto exit; } rc = write_selinux_ibendport_rules_to_conf(out, pdb); if (rc != 0) { goto exit; } } else if (pdb->target_platform == SEPOL_TARGET_XEN) { rc = write_xen_isid_rules_to_conf(out, pdb); if (rc != 0) { goto exit; } rc = write_genfscon_rules_to_conf(out, pdb); if (rc != 0) { goto exit; } rc = write_xen_pirq_rules_to_conf(out, pdb); if (rc != 0) { goto exit; } rc = write_xen_iomem_rules_to_conf(out, pdb); if (rc != 0) { goto exit; } rc = write_xen_ioport_rules_to_conf(out, pdb); if (rc != 0) { goto exit; } rc = write_xen_pcidevice_rules_to_conf(out, pdb); if (rc != 0) { goto exit; } rc = write_xen_devicetree_rules_to_conf(out, pdb); if (rc != 0) { goto exit; } } exit: strs_free_all(mls_constraints); strs_destroy(&mls_constraints); strs_free_all(non_mls_constraints); strs_destroy(&non_mls_constraints); strs_free_all(mls_validatetrans); strs_destroy(&mls_validatetrans); strs_free_all(non_mls_validatetrans); strs_destroy(&non_mls_validatetrans); return rc; } libsepol-3.8.1/src/libsepol.map.in000066400000000000000000000156531476211737200170640ustar00rootroot00000000000000LIBSEPOL_1.0 { global: cil_add_file; cil_db_destroy; cil_db_init; cil_set_disable_dontaudit; cil_set_disable_neverallow; cil_set_handle_unknown; cil_set_log_handler; cil_set_log_level; cil_set_preserve_tunables; expand_module_avrules; sepol_bool_clone; sepol_bool_compare; sepol_bool_compare2; sepol_bool_count; sepol_bool_create; sepol_bool_exists; sepol_bool_free; sepol_bool_get_name; sepol_bool_get_value; sepol_bool_iterate; sepol_bool_key_create; sepol_bool_key_extract; sepol_bool_key_free; sepol_bool_key_unpack; sepol_bool_query; sepol_bool_set; sepol_bool_set_name; sepol_bool_set_value; sepol_check_context; sepol_context_check; sepol_context_clone; sepol_context_create; sepol_context_free; sepol_context_from_string; sepol_context_get_mls; sepol_context_get_role; sepol_context_get_type; sepol_context_get_user; sepol_context_set_mls; sepol_context_set_role; sepol_context_set_type; sepol_context_set_user; sepol_context_to_string; sepol_debug; sepol_expand_module; sepol_get_disable_dontaudit; sepol_get_preserve_tunables; sepol_handle_create; sepol_handle_destroy; sepol_ibendport_alloc_ibdev_name; sepol_ibendport_clone; sepol_ibendport_compare; sepol_ibendport_compare2; sepol_ibendport_count; sepol_ibendport_create; sepol_ibendport_exists; sepol_ibendport_free; sepol_ibendport_get_con; sepol_ibendport_get_ibdev_name; sepol_ibendport_get_port; sepol_ibendport_iterate; sepol_ibendport_key_create; sepol_ibendport_key_extract; sepol_ibendport_key_free; sepol_ibendport_key_unpack; sepol_ibendport_modify; sepol_ibendport_query; sepol_ibendport_set_con; sepol_ibendport_set_ibdev_name; sepol_ibendport_set_port; sepol_ibpkey_clone; sepol_ibpkey_compare; sepol_ibpkey_compare2; sepol_ibpkey_count; sepol_ibpkey_create; sepol_ibpkey_exists; sepol_ibpkey_free; sepol_ibpkey_get_con; sepol_ibpkey_get_high; sepol_ibpkey_get_low; sepol_ibpkey_get_subnet_prefix; sepol_ibpkey_get_subnet_prefix_bytes; sepol_ibpkey_iterate; sepol_ibpkey_key_create; sepol_ibpkey_key_extract; sepol_ibpkey_key_free; sepol_ibpkey_key_unpack; sepol_ibpkey_modify; sepol_ibpkey_query; sepol_ibpkey_set_con; sepol_ibpkey_set_pkey; sepol_ibpkey_set_range; sepol_ibpkey_set_subnet_prefix; sepol_ibpkey_set_subnet_prefix_bytes; sepol_iface_clone; sepol_iface_compare; sepol_iface_compare2; sepol_iface_count; sepol_iface_create; sepol_iface_exists; sepol_iface_free; sepol_iface_get_ifcon; sepol_iface_get_msgcon; sepol_iface_get_name; sepol_iface_iterate; sepol_iface_key_create; sepol_iface_key_extract; sepol_iface_key_free; sepol_iface_key_unpack; sepol_iface_modify; sepol_iface_query; sepol_iface_set_ifcon; sepol_iface_set_msgcon; sepol_iface_set_name; sepol_link_modules; sepol_link_packages; sepol_mls_check; sepol_mls_contains; sepol_module_package_create; sepol_module_package_free; sepol_module_package_get_file_contexts; sepol_module_package_get_file_contexts_len; sepol_module_package_get_netfilter_contexts; sepol_module_package_get_netfilter_contexts_len; sepol_module_package_get_policy; sepol_module_package_get_seusers; sepol_module_package_get_seusers_len; sepol_module_package_get_user_extra; sepol_module_package_get_user_extra_len; sepol_module_package_info; sepol_module_package_read; sepol_module_package_set_file_contexts; sepol_module_package_set_netfilter_contexts; sepol_module_package_set_seusers; sepol_module_package_set_user_extra; sepol_module_package_write; sepol_msg_get_channel; sepol_msg_get_fname; sepol_msg_get_level; sepol_msg_set_callback; sepol_node_clone; sepol_node_compare; sepol_node_compare2; sepol_node_count; sepol_node_create; sepol_node_exists; sepol_node_free; sepol_node_get_addr; sepol_node_get_addr_bytes; sepol_node_get_con; sepol_node_get_mask; sepol_node_get_mask_bytes; sepol_node_get_proto; sepol_node_get_proto_str; sepol_node_iterate; sepol_node_key_create; sepol_node_key_extract; sepol_node_key_free; sepol_node_key_unpack; sepol_node_modify; sepol_node_query; sepol_node_set_addr; sepol_node_set_addr_bytes; sepol_node_set_con; sepol_node_set_mask; sepol_node_set_mask_bytes; sepol_node_set_proto; sepol_policydb_compat_net; sepol_policydb_create; sepol_policydb_free; sepol_policydb_from_image; sepol_policydb_mls_enabled; sepol_policydb_read; sepol_policydb_set_handle_unknown; sepol_policydb_set_target_platform; sepol_policydb_set_typevers; sepol_policydb_set_vers; sepol_policydb_to_image; sepol_policydb_write; sepol_policy_file_create; sepol_policy_file_free; sepol_policy_file_get_len; sepol_policy_file_set_fp; sepol_policy_file_set_handle; sepol_policy_file_set_mem; sepol_policy_kern_vers_max; sepol_policy_kern_vers_min; sepol_port_clone; sepol_port_compare; sepol_port_compare2; sepol_port_count; sepol_port_create; sepol_port_exists; sepol_port_free; sepol_port_get_con; sepol_port_get_high; sepol_port_get_low; sepol_port_get_proto; sepol_port_get_proto_str; sepol_port_iterate; sepol_port_key_create; sepol_port_key_extract; sepol_port_key_free; sepol_port_key_unpack; sepol_port_modify; sepol_port_query; sepol_port_set_con; sepol_port_set_port; sepol_port_set_proto; sepol_port_set_range; sepol_set_disable_dontaudit; sepol_set_expand_consume_base; sepol_set_policydb_from_file; sepol_set_preserve_tunables; sepol_user_add_role; sepol_user_clone; sepol_user_compare; sepol_user_compare2; sepol_user_count; sepol_user_create; sepol_user_del_role; sepol_user_exists; sepol_user_free; sepol_user_get_mlslevel; sepol_user_get_mlsrange; sepol_user_get_name; sepol_user_get_num_roles; sepol_user_get_roles; sepol_user_has_role; sepol_user_iterate; sepol_user_key_create; sepol_user_key_extract; sepol_user_key_free; sepol_user_key_unpack; sepol_user_modify; sepol_user_query; sepol_user_set_mlslevel; sepol_user_set_mlsrange; sepol_user_set_name; sepol_user_set_roles; local: *; }; LIBSEPOL_1.1 { global: cil_build_policydb; cil_compile; cil_userprefixes_to_string; cil_selinuxusers_to_string; cil_filecons_to_string; cil_set_target_platform; cil_set_policy_version; cil_set_mls; cil_set_attrs_expand_generated; cil_set_attrs_expand_size; cil_set_multiple_decls; cil_write_policy_conf; sepol_ppfile_to_module_package; sepol_module_package_to_cil; sepol_module_policydb_to_cil; sepol_kernel_policydb_to_cil; sepol_kernel_policydb_to_conf; sepol_polcap_getnum; sepol_polcap_getname; } LIBSEPOL_1.0; LIBSEPOL_3.0 { global: sepol_policydb_optimize; cil_write_parse_ast; cil_write_build_ast; cil_write_resolve_ast; cil_set_qualified_names; } LIBSEPOL_1.1; LIBSEPOL_3.4 { global: sepol_av_perm_to_string; sepol_change_sid; sepol_compute_av; sepol_compute_av_reason; sepol_compute_av_reason_buffer; sepol_context_to_sid; sepol_member_sid; sepol_sid_to_context; sepol_string_to_av_perm; sepol_string_to_security_class; sepol_validate_transition_reason_buffer; } LIBSEPOL_3.0; LIBSEPOL_3.6 { global: cil_write_post_ast; } LIBSEPOL_3.4; libsepol-3.8.1/src/libsepol.pc.in000066400000000000000000000003611476211737200166770ustar00rootroot00000000000000prefix=@prefix@ exec_prefix=${prefix} libdir=@libdir@ includedir=@includedir@ Name: libsepol Description: SELinux policy library Version: @VERSION@ URL: http://userspace.selinuxproject.org/ Libs: -L${libdir} -lsepol Cflags: -I${includedir} libsepol-3.8.1/src/link.c000066400000000000000000002102101476211737200152320ustar00rootroot00000000000000/* Authors: Karl MacMillan * Joshua Brindle * Jason Tang * * Copyright (C) 2004-2005 Tresys Technology, LLC * Copyright (C) 2007 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include #include #include "debug.h" #include "private.h" #undef min #define min(a,b) (((a) < (b)) ? (a) : (b)) typedef struct policy_module { policydb_t *policy; uint32_t num_decls; uint32_t *map[SYM_NUM]; uint32_t *avdecl_map; uint32_t **perm_map; uint32_t *perm_map_len; /* a pointer to within the base module's avrule_block chain to * where this module's global now resides */ avrule_block_t *base_global; } policy_module_t; typedef struct link_state { int verbose; policydb_t *base; avrule_block_t *last_avrule_block, *last_base_avrule_block; uint32_t next_decl_id, current_decl_id; /* temporary variables, used during hashtab_map() calls */ policy_module_t *cur; char *cur_mod_name; avrule_decl_t *dest_decl; class_datum_t *src_class, *dest_class; char *dest_class_name; char dest_class_req; /* flag indicating the class was not declared */ uint32_t symbol_num; /* used to report the name of the module if dependency error occurs */ policydb_t **decl_to_mod; /* error reporting fields */ sepol_handle_t *handle; } link_state_t; typedef struct missing_requirement { uint32_t symbol_type; uint32_t symbol_value; uint32_t perm_value; } missing_requirement_t; static const char * const symtab_names[SYM_NUM] = { "common", "class", "role", "type/attribute", "user", "bool", "level", "category" }; /* Deallocates all elements within a module, but NOT the policydb_t * structure within, as well as the pointer itself. */ static void policy_module_destroy(policy_module_t * mod) { unsigned int i; if (mod == NULL) { return; } for (i = 0; i < SYM_NUM; i++) { free(mod->map[i]); } for (i = 0; mod->perm_map != NULL && i < mod->policy->p_classes.nprim; i++) { free(mod->perm_map[i]); } free(mod->perm_map); free(mod->perm_map_len); free(mod->avdecl_map); free(mod); } /***** functions that copy identifiers from a module to base *****/ /* Note: there is currently no scoping for permissions, which causes some * strange side-effects. The current approach is this: * * a) perm is required and the class _and_ perm are declared in base: only add a mapping. * b) perm is required and the class and perm are _not_ declared in base: simply add the permissions * to the object class. This means that the requirements for the decl are the union of the permissions * required for all decls, but who cares. * c) perm is required, the class is declared in base, but the perm is not present. Nothing we can do * here because we can't mark a single permission as required, so we bail with a requirement error * _even_ if we are in an optional. * * A is correct behavior, b is wrong but not too bad, c is totall wrong for optionals. Fixing this requires * a format change. */ static int permission_copy_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) { char *perm_id = key, *new_id = NULL; perm_datum_t *perm, *new_perm = NULL, *dest_perm; link_state_t *state = (link_state_t *) data; class_datum_t *src_class = state->src_class; class_datum_t *dest_class = state->dest_class; policy_module_t *mod = state->cur; uint32_t sclassi = src_class->s.value - 1; int ret; perm = (perm_datum_t *) datum; dest_perm = hashtab_search(dest_class->permissions.table, perm_id); if (dest_perm == NULL && dest_class->comdatum != NULL) { dest_perm = hashtab_search(dest_class->comdatum->permissions.table, perm_id); } if (dest_perm == NULL) { /* If the object class was not declared in the base, add the perm * to the object class. */ if (state->dest_class_req) { /* If the class was required (not declared), insert the new permission */ new_id = strdup(perm_id); if (new_id == NULL) { ERR(state->handle, "Memory error"); ret = SEPOL_ERR; goto err; } new_perm = (perm_datum_t *) calloc(1, sizeof(perm_datum_t)); if (new_perm == NULL) { ERR(state->handle, "Memory error"); ret = SEPOL_ERR; goto err; } ret = hashtab_insert(dest_class->permissions.table, (hashtab_key_t) new_id, (hashtab_datum_t) new_perm); if (ret) { ERR(state->handle, "could not insert permission into class"); goto err; } new_perm->s.value = dest_class->permissions.nprim + 1; dest_perm = new_perm; } else { /* this is case c from above */ ERR(state->handle, "Module %s depends on permission %s in class %s, not satisfied", state->cur_mod_name, perm_id, state->dest_class_name); return SEPOL_EREQ; } } /* build the mapping for permissions encompassing this class. * unlike symbols, the permission map translates between * module permission bit to target permission bit. that bit * may have originated from the class -or- it could be from * the class's common parent.*/ if (perm->s.value > mod->perm_map_len[sclassi]) { uint32_t *newmap = calloc(perm->s.value, sizeof(*newmap)); if (newmap == NULL) { ERR(state->handle, "Out of memory!"); return -1; } if (mod->perm_map_len[sclassi] > 0) { memcpy(newmap, mod->perm_map[sclassi], mod->perm_map_len[sclassi] * sizeof(*newmap)); } free(mod->perm_map[sclassi]); mod->perm_map[sclassi] = newmap; mod->perm_map_len[sclassi] = perm->s.value; } mod->perm_map[sclassi][perm->s.value - 1] = dest_perm->s.value; return 0; err: free(new_id); free(new_perm); return ret; } static int class_copy_default_new_object(link_state_t *state, class_datum_t *olddatum, class_datum_t *newdatum) { if (olddatum->default_user) { if (newdatum->default_user && olddatum->default_user != newdatum->default_user) { ERR(state->handle, "Found conflicting default user definitions"); return SEPOL_ENOTSUP; } newdatum->default_user = olddatum->default_user; } if (olddatum->default_role) { if (newdatum->default_role && olddatum->default_role != newdatum->default_role) { ERR(state->handle, "Found conflicting default role definitions"); return SEPOL_ENOTSUP; } newdatum->default_role = olddatum->default_role; } if (olddatum->default_type) { if (newdatum->default_type && olddatum->default_type != newdatum->default_type) { ERR(state->handle, "Found conflicting default type definitions"); return SEPOL_ENOTSUP; } newdatum->default_type = olddatum->default_type; } if (olddatum->default_range) { if (newdatum->default_range && olddatum->default_range != newdatum->default_range) { ERR(state->handle, "Found conflicting default range definitions"); return SEPOL_ENOTSUP; } newdatum->default_range = olddatum->default_range; } return 0; } static int class_copy_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) { char *id = key, *new_id = NULL; class_datum_t *cladatum, *new_class = NULL; link_state_t *state = (link_state_t *) data; scope_datum_t *scope = NULL; int ret; cladatum = (class_datum_t *) datum; state->dest_class_req = 0; new_class = hashtab_search(state->base->p_classes.table, id); /* If there is not an object class already in the base symtab that means * that either a) a module is trying to declare a new object class (which * the compiler should prevent) or b) an object class was required that is * not in the base. */ if (new_class == NULL) { scope = hashtab_search(state->cur->policy->p_classes_scope.table, id); if (scope == NULL) { ret = SEPOL_ERR; goto err; } if (scope->scope == SCOPE_DECL) { /* disallow declarations in modules */ ERR(state->handle, "%s: Modules may not yet declare new classes.", state->cur_mod_name); ret = SEPOL_ENOTSUP; goto err; } else { /* It would be nice to error early here because the requirement is * not met, but we cannot because the decl might be optional (in which * case we should record the requirement so that it is just turned * off). Note: this will break horribly if modules can declare object * classes because the class numbers will be all wrong (i.e., they * might be assigned in the order they were required rather than the * current scheme which ensures correct numbering by ordering the * declarations properly). This can't be fixed until some infrastructure * for querying the object class numbers is in place. */ state->dest_class_req = 1; new_class = (class_datum_t *) calloc(1, sizeof(class_datum_t)); if (new_class == NULL) { ERR(state->handle, "Memory error"); ret = SEPOL_ERR; goto err; } if (symtab_init (&new_class->permissions, PERM_SYMTAB_SIZE)) { ret = SEPOL_ERR; goto err; } new_id = strdup(id); if (new_id == NULL) { ERR(state->handle, "Memory error"); symtab_destroy(&new_class->permissions); ret = SEPOL_ERR; goto err; } ret = hashtab_insert(state->base->p_classes.table, (hashtab_key_t) new_id, (hashtab_datum_t) new_class); if (ret) { ERR(state->handle, "could not insert new class into symtab"); symtab_destroy(&new_class->permissions); goto err; } new_class->s.value = ++(state->base->p_classes.nprim); } } state->cur->map[SYM_CLASSES][cladatum->s.value - 1] = new_class->s.value; /* copy permissions */ state->src_class = cladatum; state->dest_class = new_class; state->dest_class_name = (char *)key; /* copy default new object rules */ ret = class_copy_default_new_object(state, cladatum, new_class); if (ret) return ret; ret = hashtab_map(cladatum->permissions.table, permission_copy_callback, state); if (ret != 0) { return ret; } return 0; err: free(new_class); free(new_id); return ret; } static int role_copy_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) { int ret; char *id = key, *new_id = NULL; role_datum_t *role, *base_role, *new_role = NULL; link_state_t *state = (link_state_t *) data; role = (role_datum_t *) datum; base_role = hashtab_search(state->base->p_roles.table, id); if (base_role != NULL) { /* role already exists. check that it is what this * module expected. duplicate declarations (e.g., two * modules both declare role foo_r) is checked during * scope_copy_callback(). */ if (role->flavor == ROLE_ATTRIB && base_role->flavor != ROLE_ATTRIB) { ERR(state->handle, "%s: Expected %s to be a role attribute, but it was already declared as a regular role.", state->cur_mod_name, id); return -1; } else if (role->flavor != ROLE_ATTRIB && base_role->flavor == ROLE_ATTRIB) { ERR(state->handle, "%s: Expected %s to be a regular role, but it was already declared as a role attribute.", state->cur_mod_name, id); return -1; } } else { if (state->verbose) INFO(state->handle, "copying role %s", id); if ((new_id = strdup(id)) == NULL) { goto cleanup; } if ((new_role = (role_datum_t *) malloc(sizeof(*new_role))) == NULL) { goto cleanup; } role_datum_init(new_role); /* new_role's dominates, types and roles field will be copied * during role_fix_callback() */ new_role->flavor = role->flavor; new_role->s.value = state->base->p_roles.nprim + 1; ret = hashtab_insert(state->base->p_roles.table, (hashtab_key_t) new_id, (hashtab_datum_t) new_role); if (ret) { goto cleanup; } state->base->p_roles.nprim++; base_role = new_role; } if (state->dest_decl) { new_id = NULL; if ((new_role = malloc(sizeof(*new_role))) == NULL) { goto cleanup; } role_datum_init(new_role); new_role->flavor = base_role->flavor; new_role->s.value = base_role->s.value; if ((new_id = strdup(id)) == NULL) { goto cleanup; } if (hashtab_insert (state->dest_decl->p_roles.table, new_id, new_role)) { goto cleanup; } state->dest_decl->p_roles.nprim++; } state->cur->map[SYM_ROLES][role->s.value - 1] = base_role->s.value; return 0; cleanup: ERR(state->handle, "Out of memory!"); role_datum_destroy(new_role); free(new_id); free(new_role); return -1; } /* Copy types and attributes from a module into the base module. The * attributes are copied, but the types that make up this attribute * are delayed type_fix_callback(). */ static int type_copy_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) { int ret; char *id = key, *new_id = NULL; type_datum_t *type, *base_type, *new_type = NULL; link_state_t *state = (link_state_t *) data; type = (type_datum_t *) datum; if ((type->flavor == TYPE_TYPE && !type->primary) || type->flavor == TYPE_ALIAS) { /* aliases are handled later, in alias_copy_callback() */ return 0; } base_type = hashtab_search(state->base->p_types.table, id); if (base_type != NULL) { /* type already exists. check that it is what this * module expected. duplicate declarations (e.g., two * modules both declare type foo_t) is checked during * scope_copy_callback(). */ if (type->flavor == TYPE_ATTRIB && base_type->flavor != TYPE_ATTRIB) { ERR(state->handle, "%s: Expected %s to be an attribute, but it was already declared as a type.", state->cur_mod_name, id); return -1; } else if (type->flavor != TYPE_ATTRIB && base_type->flavor == TYPE_ATTRIB) { ERR(state->handle, "%s: Expected %s to be a type, but it was already declared as an attribute.", state->cur_mod_name, id); return -1; } base_type->flags |= type->flags; } else { if (state->verbose) INFO(state->handle, "copying type %s", id); if ((new_id = strdup(id)) == NULL) { goto cleanup; } if ((new_type = (type_datum_t *) calloc(1, sizeof(*new_type))) == NULL) { goto cleanup; } new_type->primary = type->primary; new_type->flags = type->flags; new_type->flavor = type->flavor; /* for attributes, the writing of new_type->types is done in type_fix_callback() */ new_type->s.value = state->base->p_types.nprim + 1; ret = hashtab_insert(state->base->p_types.table, (hashtab_key_t) new_id, (hashtab_datum_t) new_type); if (ret) { goto cleanup; } state->base->p_types.nprim++; base_type = new_type; } if (state->dest_decl) { new_id = NULL; if ((new_type = calloc(1, sizeof(*new_type))) == NULL) { goto cleanup; } new_type->primary = type->primary; new_type->flavor = type->flavor; new_type->flags = type->flags; new_type->s.value = base_type->s.value; if ((new_id = strdup(id)) == NULL) { goto cleanup; } if (hashtab_insert (state->dest_decl->p_types.table, new_id, new_type)) { goto cleanup; } state->dest_decl->p_types.nprim++; } state->cur->map[SYM_TYPES][type->s.value - 1] = base_type->s.value; return 0; cleanup: ERR(state->handle, "Out of memory!"); free(new_id); free(new_type); return -1; } static int user_copy_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) { int ret; char *id = key, *new_id = NULL; user_datum_t *user, *base_user, *new_user = NULL; link_state_t *state = (link_state_t *) data; user = (user_datum_t *) datum; base_user = hashtab_search(state->base->p_users.table, id); if (base_user == NULL) { if (state->verbose) INFO(state->handle, "copying user %s", id); if ((new_id = strdup(id)) == NULL) { goto cleanup; } if ((new_user = (user_datum_t *) malloc(sizeof(*new_user))) == NULL) { goto cleanup; } user_datum_init(new_user); /* new_users's roles and MLS fields will be copied during user_fix_callback(). */ new_user->s.value = state->base->p_users.nprim + 1; ret = hashtab_insert(state->base->p_users.table, (hashtab_key_t) new_id, (hashtab_datum_t) new_user); if (ret) { goto cleanup; } state->base->p_users.nprim++; base_user = new_user; } if (state->dest_decl) { new_id = NULL; if ((new_user = malloc(sizeof(*new_user))) == NULL) { goto cleanup; } user_datum_init(new_user); new_user->s.value = base_user->s.value; if ((new_id = strdup(id)) == NULL) { goto cleanup; } if (hashtab_insert (state->dest_decl->p_users.table, new_id, new_user)) { goto cleanup; } state->dest_decl->p_users.nprim++; } state->cur->map[SYM_USERS][user->s.value - 1] = base_user->s.value; return 0; cleanup: ERR(state->handle, "Out of memory!"); user_datum_destroy(new_user); free(new_id); free(new_user); return -1; } static int bool_copy_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) { int ret; char *id = key, *new_id = NULL; cond_bool_datum_t *booldatum, *base_bool, *new_bool = NULL; link_state_t *state = (link_state_t *) data; scope_datum_t *scope; booldatum = (cond_bool_datum_t *) datum; base_bool = hashtab_search(state->base->p_bools.table, id); if (base_bool == NULL) { if (state->verbose) INFO(state->handle, "copying boolean %s", id); if ((new_id = strdup(id)) == NULL) { goto cleanup; } if ((new_bool = (cond_bool_datum_t *) malloc(sizeof(*new_bool))) == NULL) { goto cleanup; } new_bool->s.value = state->base->p_bools.nprim + 1; ret = hashtab_insert(state->base->p_bools.table, (hashtab_key_t) new_id, (hashtab_datum_t) new_bool); if (ret) { goto cleanup; } state->base->p_bools.nprim++; base_bool = new_bool; base_bool->flags = booldatum->flags; base_bool->state = booldatum->state; } else if ((booldatum->flags & COND_BOOL_FLAGS_TUNABLE) != (base_bool->flags & COND_BOOL_FLAGS_TUNABLE)) { /* A mismatch between boolean/tunable declaration * and usage(for example a boolean used in the * tunable_policy() or vice versa). * * This is not allowed and bail out with errors */ ERR(state->handle, "%s: Mismatch between boolean/tunable definition " "and usage for %s", state->cur_mod_name, id); return -1; } /* Get the scope info for this boolean to see if this is the declaration, * if so set the state */ scope = hashtab_search(state->cur->policy->p_bools_scope.table, id); if (!scope) return SEPOL_ERR; if (scope->scope == SCOPE_DECL) { base_bool->state = booldatum->state; /* Only the declaration rather than requirement * decides if it is a boolean or tunable. */ base_bool->flags = booldatum->flags; } state->cur->map[SYM_BOOLS][booldatum->s.value - 1] = base_bool->s.value; return 0; cleanup: ERR(state->handle, "Out of memory!"); cond_destroy_bool(new_id, new_bool, NULL); return -1; } static int sens_copy_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) { char *id = key; level_datum_t *level, *base_level; link_state_t *state = (link_state_t *) data; scope_datum_t *scope; level = (level_datum_t *) datum; base_level = hashtab_search(state->base->p_levels.table, id); if (!base_level) { scope = hashtab_search(state->cur->policy->p_sens_scope.table, id); if (!scope) return SEPOL_ERR; if (scope->scope == SCOPE_DECL) { /* disallow declarations in modules */ ERR(state->handle, "%s: Modules may not declare new sensitivities.", state->cur_mod_name); return SEPOL_ENOTSUP; } else if (scope->scope == SCOPE_REQ) { /* unmet requirement */ ERR(state->handle, "%s: Sensitivity %s not declared by base.", state->cur_mod_name, id); return SEPOL_ENOTSUP; } else { ERR(state->handle, "%s: has an unknown scope: %d", state->cur_mod_name, scope->scope); return SEPOL_ENOTSUP; } } state->cur->map[SYM_LEVELS][level->level->sens - 1] = base_level->level->sens; return 0; } static int cat_copy_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) { char *id = key; cat_datum_t *cat, *base_cat; link_state_t *state = (link_state_t *) data; scope_datum_t *scope; cat = (cat_datum_t *) datum; base_cat = hashtab_search(state->base->p_cats.table, id); if (!base_cat) { scope = hashtab_search(state->cur->policy->p_cat_scope.table, id); if (!scope) return SEPOL_ERR; if (scope->scope == SCOPE_DECL) { /* disallow declarations in modules */ ERR(state->handle, "%s: Modules may not declare new categories.", state->cur_mod_name); return SEPOL_ENOTSUP; } else if (scope->scope == SCOPE_REQ) { /* unmet requirement */ ERR(state->handle, "%s: Category %s not declared by base.", state->cur_mod_name, id); return SEPOL_ENOTSUP; } else { /* unknown scope? malformed policy? */ ERR(state->handle, "%s: has an unknown scope: %d", state->cur_mod_name, scope->scope); return SEPOL_ENOTSUP; } } state->cur->map[SYM_CATS][cat->s.value - 1] = base_cat->s.value; return 0; } static int (*const copy_callback_f[SYM_NUM]) (hashtab_key_t key, hashtab_datum_t datum, void *datap) = { NULL, class_copy_callback, role_copy_callback, type_copy_callback, user_copy_callback, bool_copy_callback, sens_copy_callback, cat_copy_callback}; /* * The boundaries have to be copied after the types/roles/users are copied, * because it refers hashtab to lookup destinated objects. */ static int type_bounds_copy_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) { link_state_t *state = (link_state_t *) data; type_datum_t *type = (type_datum_t *) datum; type_datum_t *dest; uint32_t bounds_val; if (!type->bounds) return 0; bounds_val = state->cur->map[SYM_TYPES][type->bounds - 1]; dest = hashtab_search(state->base->p_types.table, key); if (!dest) { ERR(state->handle, "Type lookup failed for %s", (char *)key); return -1; } if (dest->bounds != 0 && dest->bounds != bounds_val) { ERR(state->handle, "Inconsistent boundary for %s", (char *)key); return -1; } dest->bounds = bounds_val; return 0; } static int role_bounds_copy_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) { link_state_t *state = (link_state_t *) data; role_datum_t *role = (role_datum_t *) datum; role_datum_t *dest; uint32_t bounds_val; if (!role->bounds) return 0; bounds_val = state->cur->map[SYM_ROLES][role->bounds - 1]; dest = hashtab_search(state->base->p_roles.table, key); if (!dest) { ERR(state->handle, "Role lookup failed for %s", (char *)key); return -1; } if (dest->bounds != 0 && dest->bounds != bounds_val) { ERR(state->handle, "Inconsistent boundary for %s", (char *)key); return -1; } dest->bounds = bounds_val; return 0; } static int user_bounds_copy_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) { link_state_t *state = (link_state_t *) data; user_datum_t *user = (user_datum_t *) datum; user_datum_t *dest; uint32_t bounds_val; if (!user->bounds) return 0; bounds_val = state->cur->map[SYM_USERS][user->bounds - 1]; dest = hashtab_search(state->base->p_users.table, key); if (!dest) { ERR(state->handle, "User lookup failed for %s", (char *)key); return -1; } if (dest->bounds != 0 && dest->bounds != bounds_val) { ERR(state->handle, "Inconsistent boundary for %s", (char *)key); return -1; } dest->bounds = bounds_val; return 0; } /* The aliases have to be copied after the types and attributes to be * certain that the base symbol table will have the type that the * alias refers. Otherwise, we won't be able to find the type value * for the alias. We can't depend on the declaration ordering because * of the hash table. */ static int alias_copy_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) { char *id = key, *new_id = NULL, *target_id; type_datum_t *type, *base_type, *new_type = NULL, *target_type; link_state_t *state = (link_state_t *) data; policy_module_t *mod = state->cur; int primval; type = (type_datum_t *) datum; /* there are 2 kinds of aliases. Ones with their own value (TYPE_ALIAS) * and ones with the value of their primary (TYPE_TYPE && type->primary = 0) */ if (! (type->flavor == TYPE_ALIAS || (type->flavor == TYPE_TYPE && !type->primary))) { /* ignore types and attributes -- they were handled in * type_copy_callback() */ return 0; } if (type->flavor == TYPE_ALIAS) primval = type->primary; else primval = type->s.value; target_id = mod->policy->p_type_val_to_name[primval - 1]; target_type = hashtab_search(state->base->p_types.table, target_id); if (target_type == NULL) { ERR(state->handle, "%s: Could not find type %s for alias %s.", state->cur_mod_name, target_id, id); return -1; } if (!strcmp(id, target_id)) { ERR(state->handle, "%s: Self aliasing of %s.", state->cur_mod_name, id); return -1; } target_type->flags |= type->flags; base_type = hashtab_search(state->base->p_types.table, id); if (base_type == NULL) { if (state->verbose) INFO(state->handle, "copying alias %s", id); if ((new_type = (type_datum_t *) calloc(1, sizeof(*new_type))) == NULL) { goto cleanup; } /* the linked copy always has TYPE_ALIAS style aliases */ new_type->primary = target_type->s.value; new_type->flags = target_type->flags; new_type->flavor = TYPE_ALIAS; new_type->s.value = state->base->p_types.nprim + 1; if ((new_id = strdup(id)) == NULL) { goto cleanup; } if (hashtab_insert (state->base->p_types.table, new_id, new_type)) { goto cleanup; } state->base->p_types.nprim++; base_type = new_type; } else { /* if this already exists and isn't an alias it was required by another module (or base) * and inserted into the hashtable as a type, fix it up now */ if (base_type->flavor == TYPE_ALIAS) { /* error checking */ assert(base_type->primary == target_type->s.value); assert(base_type->primary == mod->map[SYM_TYPES][primval - 1]); assert(mod->map[SYM_TYPES][type->s.value - 1] == base_type->primary); return 0; } if (base_type->flavor == TYPE_ATTRIB) { ERR(state->handle, "%s is an alias of an attribute, not allowed", id); return -1; } base_type->flavor = TYPE_ALIAS; base_type->primary = target_type->s.value; base_type->flags |= target_type->flags; } /* the aliases map points from its value to its primary so when this module * references this type the value it gets back from the map is the primary */ mod->map[SYM_TYPES][type->s.value - 1] = base_type->primary; return 0; cleanup: ERR(state->handle, "Out of memory!"); free(new_id); free(new_type); return -1; } /*********** callbacks that fix bitmaps ***********/ static int ebitmap_convert(const ebitmap_t *src, ebitmap_t *dst, const uint32_t *map) { unsigned int bit; ebitmap_node_t *node; ebitmap_for_each_positive_bit(src, node, bit) { assert(map[bit]); if (ebitmap_set_bit(dst, map[bit] - 1, 1)) return -1; } return 0; } static int type_set_convert(const type_set_t * types, type_set_t * dst, const policy_module_t * mod) { if (ebitmap_convert(&types->types, &dst->types, mod->map[SYM_TYPES])) goto cleanup; if (ebitmap_convert(&types->negset, &dst->negset, mod->map[SYM_TYPES])) goto cleanup; dst->flags = types->flags; return 0; cleanup: return -1; } /* OR 2 typemaps together and at the same time map the src types to * the correct values in the dst typeset. */ static int type_set_or_convert(const type_set_t * types, type_set_t * dst, const policy_module_t * mod) { type_set_t ts_tmp; type_set_init(&ts_tmp); if (type_set_convert(types, &ts_tmp, mod) == -1) { goto cleanup; } if (type_set_or_eq(dst, &ts_tmp)) { goto cleanup; } type_set_destroy(&ts_tmp); return 0; cleanup: type_set_destroy(&ts_tmp); return -1; } static int role_set_or_convert(role_set_t * roles, role_set_t * dst, policy_module_t * mod, link_state_t * state) { ebitmap_t tmp; ebitmap_init(&tmp); if (ebitmap_convert(&roles->roles, &tmp, mod->map[SYM_ROLES])) goto cleanup; if (ebitmap_union(&dst->roles, &tmp)) { goto cleanup; } dst->flags |= roles->flags; ebitmap_destroy(&tmp); return 0; cleanup: ERR(state->handle, "Out of memory!"); ebitmap_destroy(&tmp); return -1; } static int mls_level_convert(mls_semantic_level_t * src, mls_semantic_level_t * dst, policy_module_t * mod, link_state_t * state) { mls_semantic_cat_t *src_cat, *new_cat; if (!mod->policy->mls) return 0; /* Required not declared. */ if (!src->sens) return 0; assert(mod->map[SYM_LEVELS][src->sens - 1]); dst->sens = mod->map[SYM_LEVELS][src->sens - 1]; for (src_cat = src->cat; src_cat; src_cat = src_cat->next) { new_cat = (mls_semantic_cat_t *) malloc(sizeof(mls_semantic_cat_t)); if (!new_cat) { ERR(state->handle, "Out of memory"); return -1; } mls_semantic_cat_init(new_cat); new_cat->next = dst->cat; dst->cat = new_cat; assert(mod->map[SYM_CATS][src_cat->low - 1]); dst->cat->low = mod->map[SYM_CATS][src_cat->low - 1]; assert(mod->map[SYM_CATS][src_cat->high - 1]); dst->cat->high = mod->map[SYM_CATS][src_cat->high - 1]; } return 0; } static int mls_range_convert(mls_semantic_range_t * src, mls_semantic_range_t * dst, policy_module_t * mod, link_state_t * state) { int ret; ret = mls_level_convert(&src->level[0], &dst->level[0], mod, state); if (ret) return ret; ret = mls_level_convert(&src->level[1], &dst->level[1], mod, state); if (ret) return ret; return 0; } static int role_fix_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) { char *id = key; role_datum_t *role, *dest_role = NULL; link_state_t *state = (link_state_t *) data; ebitmap_t e_tmp; policy_module_t *mod = state->cur; hashtab_t role_tab; role = (role_datum_t *) datum; if (state->dest_decl == NULL) role_tab = state->base->p_roles.table; else role_tab = state->dest_decl->p_roles.table; dest_role = hashtab_search(role_tab, id); assert(dest_role != NULL); if (state->verbose) { INFO(state->handle, "fixing role %s", id); } ebitmap_init(&e_tmp); if (ebitmap_convert(&role->dominates, &e_tmp, mod->map[SYM_ROLES])) goto cleanup; if (ebitmap_union(&dest_role->dominates, &e_tmp)) { goto cleanup; } if (type_set_or_convert(&role->types, &dest_role->types, mod)) { goto cleanup; } ebitmap_destroy(&e_tmp); if (role->flavor == ROLE_ATTRIB) { ebitmap_init(&e_tmp); if (ebitmap_convert(&role->roles, &e_tmp, mod->map[SYM_ROLES])) goto cleanup; if (ebitmap_union(&dest_role->roles, &e_tmp)) { goto cleanup; } ebitmap_destroy(&e_tmp); } return 0; cleanup: ERR(state->handle, "Out of memory!"); ebitmap_destroy(&e_tmp); return -1; } static int type_fix_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) { char *id = key; type_datum_t *type, *new_type = NULL; link_state_t *state = (link_state_t *) data; ebitmap_t e_tmp; policy_module_t *mod = state->cur; symtab_t *typetab; type = (type_datum_t *) datum; if (state->dest_decl == NULL) typetab = &state->base->p_types; else typetab = &state->dest_decl->p_types; /* only fix attributes */ if (type->flavor != TYPE_ATTRIB) { return 0; } new_type = hashtab_search(typetab->table, id); assert(new_type != NULL && new_type->flavor == TYPE_ATTRIB); if (state->verbose) { INFO(state->handle, "fixing attribute %s", id); } ebitmap_init(&e_tmp); if (ebitmap_convert(&type->types, &e_tmp, mod->map[SYM_TYPES])) goto cleanup; if (ebitmap_union(&new_type->types, &e_tmp)) { goto cleanup; } ebitmap_destroy(&e_tmp); return 0; cleanup: ERR(state->handle, "Out of memory!"); ebitmap_destroy(&e_tmp); return -1; } static int user_fix_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) { char *id = key; user_datum_t *user, *new_user = NULL; link_state_t *state = (link_state_t *) data; policy_module_t *mod = state->cur; symtab_t *usertab; user = (user_datum_t *) datum; if (state->dest_decl == NULL) usertab = &state->base->p_users; else usertab = &state->dest_decl->p_users; new_user = hashtab_search(usertab->table, id); assert(new_user != NULL); if (state->verbose) { INFO(state->handle, "fixing user %s", id); } if (role_set_or_convert(&user->roles, &new_user->roles, mod, state)) { goto cleanup; } if (mls_range_convert(&user->range, &new_user->range, mod, state)) goto cleanup; if (mls_level_convert(&user->dfltlevel, &new_user->dfltlevel, mod, state)) goto cleanup; return 0; cleanup: ERR(state->handle, "Out of memory!"); return -1; } static int (*const fix_callback_f[SYM_NUM]) (hashtab_key_t key, hashtab_datum_t datum, void *datap) = { NULL, NULL, role_fix_callback, type_fix_callback, user_fix_callback, NULL, NULL, NULL}; /*********** functions that copy AV rules ***********/ static int copy_avrule_list(avrule_t * list, avrule_t ** dst, policy_module_t * module, link_state_t * state) { unsigned int i; avrule_t *cur, *new_rule = NULL, *tail; class_perm_node_t *cur_perm, *new_perm, *tail_perm = NULL; tail = *dst; while (tail && tail->next) { tail = tail->next; } cur = list; while (cur) { if ((new_rule = (avrule_t *) malloc(sizeof(avrule_t))) == NULL) { goto cleanup; } avrule_init(new_rule); new_rule->specified = cur->specified; new_rule->flags = cur->flags; if (type_set_convert (&cur->stypes, &new_rule->stypes, module) == -1 || type_set_convert(&cur->ttypes, &new_rule->ttypes, module) == -1) { goto cleanup; } cur_perm = cur->perms; tail_perm = NULL; while (cur_perm) { if ((new_perm = (class_perm_node_t *) malloc(sizeof(class_perm_node_t))) == NULL) { goto cleanup; } class_perm_node_init(new_perm); new_perm->tclass = module->map[SYM_CLASSES][cur_perm->tclass - 1]; assert(new_perm->tclass); if (new_rule->specified & AVRULE_AV) { for (i = 0; i < module->perm_map_len[cur_perm->tclass - 1]; i++) { if (!(cur_perm->data & (UINT32_C(1) << i))) continue; new_perm->data |= (UINT32_C(1) << (module-> perm_map[cur_perm->tclass - 1][i] - 1)); } } else { new_perm->data = module->map[SYM_TYPES][cur_perm->data - 1]; } if (new_rule->perms == NULL) { new_rule->perms = new_perm; } else { assert(tail_perm); tail_perm->next = new_perm; } tail_perm = new_perm; cur_perm = cur_perm->next; } if (cur->xperms) { new_rule->xperms = calloc(1, sizeof(*new_rule->xperms)); if (!new_rule->xperms) goto cleanup; memcpy(new_rule->xperms, cur->xperms, sizeof(*new_rule->xperms)); } new_rule->line = cur->line; new_rule->source_line = cur->source_line; if (cur->source_filename) { new_rule->source_filename = strdup(cur->source_filename); if (!new_rule->source_filename) goto cleanup; } cur = cur->next; if (*dst == NULL) { *dst = new_rule; } else { tail->next = new_rule; } tail = new_rule; } return 0; cleanup: ERR(state->handle, "Out of memory!"); avrule_destroy(new_rule); free(new_rule); return -1; } static int copy_role_trans_list(role_trans_rule_t * list, role_trans_rule_t ** dst, policy_module_t * module, link_state_t * state) { role_trans_rule_t *cur, *new_rule = NULL, *tail; cur = list; tail = *dst; while (tail && tail->next) { tail = tail->next; } while (cur) { if ((new_rule = (role_trans_rule_t *) malloc(sizeof(role_trans_rule_t))) == NULL) { goto cleanup; } role_trans_rule_init(new_rule); if (role_set_or_convert (&cur->roles, &new_rule->roles, module, state) || type_set_or_convert(&cur->types, &new_rule->types, module)) { goto cleanup; } if (ebitmap_convert(&cur->classes, &new_rule->classes, module->map[SYM_CLASSES])) goto cleanup; new_rule->new_role = module->map[SYM_ROLES][cur->new_role - 1]; if (*dst == NULL) { *dst = new_rule; } else { tail->next = new_rule; } tail = new_rule; cur = cur->next; } return 0; cleanup: ERR(state->handle, "Out of memory!"); role_trans_rule_list_destroy(new_rule); return -1; } static int copy_role_allow_list(role_allow_rule_t * list, role_allow_rule_t ** dst, policy_module_t * module, link_state_t * state) { role_allow_rule_t *cur, *new_rule = NULL, *tail; cur = list; tail = *dst; while (tail && tail->next) { tail = tail->next; } while (cur) { if ((new_rule = (role_allow_rule_t *) malloc(sizeof(role_allow_rule_t))) == NULL) { goto cleanup; } role_allow_rule_init(new_rule); if (role_set_or_convert (&cur->roles, &new_rule->roles, module, state) || role_set_or_convert(&cur->new_roles, &new_rule->new_roles, module, state)) { goto cleanup; } if (*dst == NULL) { *dst = new_rule; } else { tail->next = new_rule; } tail = new_rule; cur = cur->next; } return 0; cleanup: ERR(state->handle, "Out of memory!"); role_allow_rule_list_destroy(new_rule); return -1; } static int copy_filename_trans_list(filename_trans_rule_t * list, filename_trans_rule_t ** dst, policy_module_t * module, link_state_t * state) { filename_trans_rule_t *cur, *new_rule, *tail; cur = list; tail = *dst; while (tail && tail->next) tail = tail->next; while (cur) { new_rule = malloc(sizeof(*new_rule)); if (!new_rule) goto err; filename_trans_rule_init(new_rule); if (*dst == NULL) *dst = new_rule; else tail->next = new_rule; tail = new_rule; new_rule->name = strdup(cur->name); if (!new_rule->name) goto err; if (type_set_or_convert(&cur->stypes, &new_rule->stypes, module) || type_set_or_convert(&cur->ttypes, &new_rule->ttypes, module)) goto err; new_rule->tclass = module->map[SYM_CLASSES][cur->tclass - 1]; new_rule->otype = module->map[SYM_TYPES][cur->otype - 1]; new_rule->flags = cur->flags; cur = cur->next; } return 0; err: ERR(state->handle, "Out of memory!"); return -1; } static int copy_range_trans_list(range_trans_rule_t * rules, range_trans_rule_t ** dst, policy_module_t * mod, link_state_t * state) { range_trans_rule_t *rule, *new_rule = NULL; for (rule = rules; rule; rule = rule->next) { new_rule = (range_trans_rule_t *) malloc(sizeof(range_trans_rule_t)); if (!new_rule) goto cleanup; range_trans_rule_init(new_rule); new_rule->next = *dst; *dst = new_rule; if (type_set_convert(&rule->stypes, &new_rule->stypes, mod)) goto cleanup; if (type_set_convert(&rule->ttypes, &new_rule->ttypes, mod)) goto cleanup; if (ebitmap_convert(&rule->tclasses, &new_rule->tclasses, mod->map[SYM_CLASSES])) goto cleanup; if (mls_range_convert(&rule->trange, &new_rule->trange, mod, state)) goto cleanup; } return 0; cleanup: ERR(state->handle, "Out of memory!"); range_trans_rule_list_destroy(new_rule); return -1; } static int copy_cond_list(cond_node_t * list, cond_node_t ** dst, policy_module_t * module, link_state_t * state) { unsigned i; cond_node_t *cur, *new_node = NULL, *tail; cond_expr_t *cur_expr; tail = *dst; while (tail && tail->next) tail = tail->next; cur = list; while (cur) { new_node = (cond_node_t *) malloc(sizeof(cond_node_t)); if (!new_node) { goto cleanup; } memset(new_node, 0, sizeof(cond_node_t)); new_node->cur_state = cur->cur_state; new_node->expr = cond_copy_expr(cur->expr); if (!new_node->expr) goto cleanup; /* go back through and remap the expression */ for (cur_expr = new_node->expr; cur_expr != NULL; cur_expr = cur_expr->next) { /* expression nodes don't have a bool value of 0 - don't map them */ if (cur_expr->expr_type != COND_BOOL) continue; assert(module->map[SYM_BOOLS][cur_expr->boolean - 1] != 0); cur_expr->boolean = module->map[SYM_BOOLS][cur_expr->boolean - 1]; } new_node->nbools = cur->nbools; /* FIXME should COND_MAX_BOOLS be used here? */ for (i = 0; i < min(cur->nbools, COND_MAX_BOOLS); i++) { uint32_t remapped_id = module->map[SYM_BOOLS][cur->bool_ids[i] - 1]; assert(remapped_id != 0); new_node->bool_ids[i] = remapped_id; } new_node->expr_pre_comp = cur->expr_pre_comp; if (copy_avrule_list (cur->avtrue_list, &new_node->avtrue_list, module, state) || copy_avrule_list(cur->avfalse_list, &new_node->avfalse_list, module, state)) { goto cleanup; } if (*dst == NULL) { *dst = new_node; } else { tail->next = new_node; } tail = new_node; cur = cur->next; } return 0; cleanup: ERR(state->handle, "Out of memory!"); cond_node_destroy(new_node); free(new_node); return -1; } /*********** functions that copy avrule_decls from module to base ***********/ static int copy_identifiers(link_state_t * state, symtab_t * src_symtab, avrule_decl_t * dest_decl) { int i, ret; state->dest_decl = dest_decl; for (i = 0; i < SYM_NUM; i++) { if (copy_callback_f[i] != NULL) { ret = hashtab_map(src_symtab[i].table, copy_callback_f[i], state); if (ret) { return ret; } } } if (hashtab_map(src_symtab[SYM_TYPES].table, type_bounds_copy_callback, state)) return -1; if (hashtab_map(src_symtab[SYM_TYPES].table, alias_copy_callback, state)) return -1; if (hashtab_map(src_symtab[SYM_ROLES].table, role_bounds_copy_callback, state)) return -1; if (hashtab_map(src_symtab[SYM_USERS].table, user_bounds_copy_callback, state)) return -1; /* then fix bitmaps associated with those newly copied identifiers */ for (i = 0; i < SYM_NUM; i++) { if (fix_callback_f[i] != NULL && hashtab_map(src_symtab[i].table, fix_callback_f[i], state)) { return -1; } } return 0; } static int copy_scope_index(scope_index_t * src, scope_index_t * dest, policy_module_t * module, link_state_t * state) { unsigned int i, j; uint32_t largest_mapped_class_value = 0; ebitmap_node_t *node; /* copy the scoping information for this avrule decl block */ for (i = 0; i < SYM_NUM; i++) { ebitmap_t *srcmap = src->scope + i; ebitmap_t *destmap = dest->scope + i; if (copy_callback_f[i] == NULL) { continue; } ebitmap_for_each_positive_bit(srcmap, node, j) { assert(module->map[i][j] != 0); if (ebitmap_set_bit (destmap, module->map[i][j] - 1, 1) != 0) { goto cleanup; } if (i == SYM_CLASSES && largest_mapped_class_value < module->map[SYM_CLASSES][j]) { largest_mapped_class_value = module->map[SYM_CLASSES][j]; } } } /* next copy the enabled permissions data */ if ((dest->class_perms_map = calloc(largest_mapped_class_value, sizeof(*dest->class_perms_map))) == NULL) { goto cleanup; } dest->class_perms_len = largest_mapped_class_value; for (i = 0; i < src->class_perms_len; i++) { const ebitmap_t *srcmap = src->class_perms_map + i; ebitmap_t *destmap = dest->class_perms_map + module->map[SYM_CLASSES][i] - 1; if (ebitmap_convert(srcmap, destmap, module->perm_map[i])) goto cleanup; } return 0; cleanup: ERR(state->handle, "Out of memory!"); return -1; } static int copy_avrule_decl(link_state_t * state, policy_module_t * module, avrule_decl_t * src_decl, avrule_decl_t * dest_decl) { int ret; /* copy all of the RBAC and TE rules */ if (copy_avrule_list (src_decl->avrules, &dest_decl->avrules, module, state) == -1 || copy_role_trans_list(src_decl->role_tr_rules, &dest_decl->role_tr_rules, module, state) == -1 || copy_role_allow_list(src_decl->role_allow_rules, &dest_decl->role_allow_rules, module, state) == -1 || copy_cond_list(src_decl->cond_list, &dest_decl->cond_list, module, state) == -1) { return -1; } if (copy_filename_trans_list(src_decl->filename_trans_rules, &dest_decl->filename_trans_rules, module, state)) return -1; if (copy_range_trans_list(src_decl->range_tr_rules, &dest_decl->range_tr_rules, module, state)) return -1; /* finally copy any identifiers local to this declaration */ ret = copy_identifiers(state, src_decl->symtab, dest_decl); if (ret < 0) { return ret; } /* then copy required and declared scope indices here */ if (copy_scope_index(&src_decl->required, &dest_decl->required, module, state) == -1 || copy_scope_index(&src_decl->declared, &dest_decl->declared, module, state) == -1) { return -1; } return 0; } static int copy_avrule_block(link_state_t * state, policy_module_t * module, avrule_block_t * block) { avrule_block_t *new_block = avrule_block_create(); avrule_decl_t *decl, *last_decl = NULL; int ret; if (new_block == NULL) { ERR(state->handle, "Out of memory!"); ret = -1; goto cleanup; } new_block->flags = block->flags; for (decl = block->branch_list; decl != NULL; decl = decl->next) { avrule_decl_t *new_decl = avrule_decl_create(state->next_decl_id); if (new_decl == NULL) { ERR(state->handle, "Out of memory!"); ret = -1; goto cleanup; } if (module->policy->name != NULL) { new_decl->module_name = strdup(module->policy->name); if (new_decl->module_name == NULL) { ERR(state->handle, "Out of memory"); avrule_decl_destroy(new_decl); ret = -1; goto cleanup; } } if (last_decl == NULL) { new_block->branch_list = new_decl; } else { last_decl->next = new_decl; } last_decl = new_decl; state->base->decl_val_to_struct[state->next_decl_id - 1] = new_decl; state->decl_to_mod[state->next_decl_id] = module->policy; module->avdecl_map[decl->decl_id] = new_decl->decl_id; ret = copy_avrule_decl(state, module, decl, new_decl); if (ret) { avrule_decl_destroy(new_decl); goto cleanup; } state->next_decl_id++; } state->last_avrule_block->next = new_block; state->last_avrule_block = new_block; return 0; cleanup: avrule_block_list_destroy(new_block); return ret; } static int scope_copy_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) { unsigned int i; int ret; char *id = key, *new_id = NULL; scope_datum_t *scope, *base_scope; link_state_t *state = (link_state_t *) data; uint32_t symbol_num = state->symbol_num; uint32_t *avdecl_map = state->cur->avdecl_map; scope = (scope_datum_t *) datum; /* check if the base already has a scope entry */ base_scope = hashtab_search(state->base->scope[symbol_num].table, id); if (base_scope == NULL) { scope_datum_t *new_scope; if ((new_id = strdup(id)) == NULL) { goto cleanup; } if ((new_scope = (scope_datum_t *) calloc(1, sizeof(*new_scope))) == NULL) { free(new_id); goto cleanup; } ret = hashtab_insert(state->base->scope[symbol_num].table, (hashtab_key_t) new_id, (hashtab_datum_t) new_scope); if (ret) { free(new_id); free(new_scope); goto cleanup; } new_scope->scope = SCOPE_REQ; /* this is reset further down */ base_scope = new_scope; } if (base_scope->scope == SCOPE_REQ && scope->scope == SCOPE_DECL) { /* this module declared symbol, so overwrite the old * list with the new decl ids */ base_scope->scope = SCOPE_DECL; free(base_scope->decl_ids); base_scope->decl_ids = NULL; base_scope->decl_ids_len = 0; for (i = 0; i < scope->decl_ids_len; i++) { if (add_i_to_a(avdecl_map[scope->decl_ids[i]], &base_scope->decl_ids_len, &base_scope->decl_ids) == -1) { goto cleanup; } } } else if (base_scope->scope == SCOPE_DECL && scope->scope == SCOPE_REQ) { /* this module depended on a symbol that now exists, * so don't do anything */ } else if (base_scope->scope == SCOPE_REQ && scope->scope == SCOPE_REQ) { /* symbol is still required, so add to the list */ for (i = 0; i < scope->decl_ids_len; i++) { if (add_i_to_a(avdecl_map[scope->decl_ids[i]], &base_scope->decl_ids_len, &base_scope->decl_ids) == -1) { goto cleanup; } } } else { /* this module declared a symbol, and it was already * declared. only roles and users may be multiply * declared; for all others this is an error. */ if (symbol_num != SYM_ROLES && symbol_num != SYM_USERS) { ERR(state->handle, "%s: Duplicate declaration in module: %s %s", state->cur_mod_name, symtab_names[state->symbol_num], id); return -1; } for (i = 0; i < scope->decl_ids_len; i++) { if (add_i_to_a(avdecl_map[scope->decl_ids[i]], &base_scope->decl_ids_len, &base_scope->decl_ids) == -1) { goto cleanup; } } } return 0; cleanup: ERR(state->handle, "Out of memory!"); return -1; } /* Copy a module over to a base, remapping all values within. After * all identifiers and rules are done, copy the scoping information. * This is when it checks for duplicate declarations. */ static int copy_module(link_state_t * state, policy_module_t * module) { int i, ret; avrule_block_t *cur; state->cur = module; state->cur_mod_name = module->policy->name; /* first copy all of the identifiers */ ret = copy_identifiers(state, module->policy->symtab, NULL); if (ret) { return ret; } /* next copy all of the avrule blocks */ for (cur = module->policy->global; cur != NULL; cur = cur->next) { ret = copy_avrule_block(state, module, cur); if (ret) { return ret; } } /* then copy the scoping tables */ for (i = 0; i < SYM_NUM; i++) { state->symbol_num = i; if (hashtab_map (module->policy->scope[i].table, scope_copy_callback, state)) { return -1; } } return 0; } /***** functions that check requirements and enable blocks in a module ******/ /* borrowed from checkpolicy.c */ struct find_perm_arg { unsigned int valuep; hashtab_key_t key; }; static int find_perm(hashtab_key_t key, hashtab_datum_t datum, void *varg) { struct find_perm_arg *arg = varg; perm_datum_t *perdatum = (perm_datum_t *) datum; if (arg->valuep == perdatum->s.value) { arg->key = key; return 1; } return 0; } /* Check if the requirements are met for a single declaration. If all * are met return 1. For the first requirement found to be missing, * if 'missing_sym_num' and 'missing_value' are both not NULL then * write to them the symbol number and value for the missing * declaration. Then return 0 to indicate a missing declaration. * Note that if a declaration had no requirement at all (e.g., an ELSE * block) this returns 1. */ static int is_decl_requires_met(link_state_t * state, const avrule_decl_t * decl, struct missing_requirement *req) { /* (This algorithm is very unoptimized. It performs many * redundant checks. A very obvious improvement is to cache * which symbols have been verified, so that they do not need * to be re-checked.) */ unsigned int i, j; const ebitmap_t *bitmap; const char *id, *perm_id; const policydb_t *pol = state->base; ebitmap_node_t *node; /* check that all symbols have been satisfied */ for (i = 0; i < SYM_NUM; i++) { if (i == SYM_CLASSES) { /* classes will be checked during permissions * checking phase below */ continue; } bitmap = &decl->required.scope[i]; ebitmap_for_each_positive_bit(bitmap, node, j) { /* check base's scope table */ id = pol->sym_val_to_name[i][j]; if (!is_id_enabled(id, state->base, i)) { /* this symbol was not found */ if (req != NULL) { req->symbol_type = i; req->symbol_value = j + 1; } return 0; } } } /* check that all classes and permissions have been satisfied */ for (i = 0; i < decl->required.class_perms_len; i++) { const class_datum_t *cladatum = pol->class_val_to_struct[i]; const scope_datum_t *scope; bitmap = &decl->required.class_perms_map[i]; id = pol->p_class_val_to_name[i]; if (!is_id_enabled(id, state->base, SYM_CLASSES)) { return 0; } scope = hashtab_search(state->base->p_classes_scope.table, id); if (scope == NULL) { ERR(state->handle, "Could not find scope information for class %s", id); return -1; } ebitmap_for_each_positive_bit(bitmap, node, j) { struct find_perm_arg fparg; uint32_t perm_value = j + 1; int rc; fparg.valuep = perm_value; fparg.key = NULL; (void)hashtab_map(cladatum->permissions.table, find_perm, &fparg); if (fparg.key == NULL && cladatum->comdatum != NULL) { rc = hashtab_map(cladatum->comdatum->permissions.table, find_perm, &fparg); assert(rc == 1); } perm_id = fparg.key; assert(perm_id != NULL); if (!is_perm_existent(cladatum, perm_id)) { if (req != NULL) { req->symbol_type = SYM_CLASSES; req->symbol_value = i + 1; req->perm_value = perm_value; } return 0; } } } /* all requirements have been met */ return 1; } static int debug_requirements(link_state_t * state, policydb_t * p) { int ret; avrule_block_t *cur; missing_requirement_t req; memset(&req, 0, sizeof(req)); for (cur = p->global; cur != NULL; cur = cur->next) { if (cur->enabled != NULL || cur->branch_list == NULL) continue; ret = is_decl_requires_met(state, cur->branch_list, &req); if (ret < 0) { return ret; } else if (ret == 0) { const char *mod_name = cur->branch_list->module_name ? cur->branch_list->module_name : "BASE"; if (req.symbol_type == SYM_CLASSES) { struct find_perm_arg fparg; class_datum_t *cladatum; cladatum = p->class_val_to_struct[req.symbol_value - 1]; fparg.valuep = req.perm_value; fparg.key = NULL; (void)hashtab_map(cladatum->permissions.table, find_perm, &fparg); if (cur->flags & AVRULE_OPTIONAL) { ERR(state->handle, "%s[%d]'s optional requirements were not met: class %s, permission %s", mod_name, cur->branch_list->decl_id, p->p_class_val_to_name[req.symbol_value - 1], fparg.key); } else { ERR(state->handle, "%s[%d]'s global requirements were not met: class %s, permission %s", mod_name, cur->branch_list->decl_id, p->p_class_val_to_name[req.symbol_value - 1], fparg.key); } } else { if (cur->flags & AVRULE_OPTIONAL) { ERR(state->handle, "%s[%d]'s optional requirements were not met: %s %s", mod_name, cur->branch_list->decl_id, symtab_names[req.symbol_type], p->sym_val_to_name[req. symbol_type][req. symbol_value - 1]); } else { ERR(state->handle, "%s[%d]'s global requirements were not met: %s %s", mod_name, cur->branch_list->decl_id, symtab_names[req.symbol_type], p->sym_val_to_name[req. symbol_type][req. symbol_value - 1]); } } } } return 0; } static void print_missing_requirements(link_state_t * state, avrule_block_t * cur, missing_requirement_t * req) { policydb_t *p = state->base; const char *mod_name = cur->branch_list->module_name ? cur->branch_list->module_name : "BASE"; if (req->symbol_type == SYM_CLASSES) { struct find_perm_arg fparg; class_datum_t *cladatum; cladatum = p->class_val_to_struct[req->symbol_value - 1]; fparg.valuep = req->perm_value; fparg.key = NULL; (void)hashtab_map(cladatum->permissions.table, find_perm, &fparg); ERR(state->handle, "%s's global requirements were not met: class %s, permission %s", mod_name, p->p_class_val_to_name[req->symbol_value - 1], fparg.key); } else { ERR(state->handle, "%s's global requirements were not met: %s %s", mod_name, symtab_names[req->symbol_type], p->sym_val_to_name[req->symbol_type][req->symbol_value - 1]); } } /* Enable all of the avrule_decl blocks for the policy. This simple * algorithm is the following: * * 1) Enable all of the non-else avrule_decls for all blocks. * 2) Iterate through the non-else decls looking for decls whose requirements * are not met. * 2a) If the decl is non-optional, return immediately with an error. * 2b) If the decl is optional, disable the block and mark changed = 1 * 3) If changed == 1 goto 2. * 4) Iterate through all blocks looking for those that have no enabled * decl. If the block has an else decl, enable. * * This will correctly handle all dependencies, including mutual and * circular. The only downside is that it is slow. */ static int enable_avrules(link_state_t * state, policydb_t * pol) { int changed = 1; avrule_block_t *block; avrule_decl_t *decl; missing_requirement_t req; int ret = 0, rc; if (state->verbose) { INFO(state->handle, "Determining which avrules to enable."); } /* 1) enable all of the non-else blocks */ for (block = pol->global; block != NULL; block = block->next) { block->enabled = block->branch_list; if (!block->enabled) { ERR(state->handle, "Global block has no avrules!"); ret = SEPOL_ERR; goto out; } block->enabled->enabled = 1; for (decl = block->branch_list->next; decl != NULL; decl = decl->next) decl->enabled = 0; } /* 2) Iterate */ while (changed) { changed = 0; for (block = pol->global; block != NULL; block = block->next) { if (block->enabled == NULL) { continue; } decl = block->branch_list; if (state->verbose) { const char *mod_name = decl->module_name ? decl->module_name : "BASE"; INFO(state->handle, "check module %s decl %d", mod_name, decl->decl_id); } rc = is_decl_requires_met(state, decl, &req); if (rc < 0) { ret = SEPOL_ERR; goto out; } else if (rc == 0) { decl->enabled = 0; block->enabled = NULL; changed = 1; if (!(block->flags & AVRULE_OPTIONAL)) { print_missing_requirements(state, block, &req); ret = SEPOL_EREQ; goto out; } } } } /* 4) else handling * * Iterate through all of the blocks skipping the first (which is the * global block, is required to be present, and cannot have an else). * If the block is disabled and has an else decl, enable that. * * This code assumes that the second block in the branch list is the else * block. This is currently supported by the compiler. */ for (block = pol->global->next; block != NULL; block = block->next) { if (block->enabled == NULL) { if (block->branch_list->next != NULL) { block->enabled = block->branch_list->next; block->branch_list->next->enabled = 1; } } } out: if (state->verbose) debug_requirements(state, pol); return ret; } /*********** the main linking functions ***********/ /* Given a module's policy, normalize all conditional expressions * within. Return 0 on success, -1 on error. */ static int cond_normalize(policydb_t * p) { avrule_block_t *block; for (block = p->global; block != NULL; block = block->next) { avrule_decl_t *decl; for (decl = block->branch_list; decl != NULL; decl = decl->next) { cond_list_t *cond = decl->cond_list; while (cond) { if (cond_normalize_expr(p, cond) < 0) return -1; cond = cond->next; } } } return 0; } /* Allocate space for the various remapping arrays. */ static int prepare_module(link_state_t * state, policy_module_t * module) { int i; uint32_t items, num_decls = 0; avrule_block_t *cur; /* allocate the maps */ for (i = 0; i < SYM_NUM; i++) { items = module->policy->symtab[i].nprim; if ((module->map[i] = (uint32_t *) calloc(items, sizeof(*module->map[i]))) == NULL) { ERR(state->handle, "Out of memory!"); return -1; } } /* allocate the permissions remap here */ items = module->policy->p_classes.nprim; if ((module->perm_map_len = calloc(items, sizeof(*module->perm_map_len))) == NULL) { ERR(state->handle, "Out of memory!"); return -1; } if ((module->perm_map = calloc(items, sizeof(*module->perm_map))) == NULL) { ERR(state->handle, "Out of memory!"); return -1; } /* allocate a map for avrule_decls */ for (cur = module->policy->global; cur != NULL; cur = cur->next) { avrule_decl_t *decl; for (decl = cur->branch_list; decl != NULL; decl = decl->next) { if (decl->decl_id > num_decls) { num_decls = decl->decl_id; } } } num_decls++; if ((module->avdecl_map = calloc(num_decls, sizeof(uint32_t))) == NULL) { ERR(state->handle, "Out of memory!"); return -1; } module->num_decls = num_decls; /* normalize conditionals within */ if (cond_normalize(module->policy) < 0) { ERR(state->handle, "Error while normalizing conditionals within the module %s.", module->policy->name); return -1; } return 0; } static int prepare_base(link_state_t * state, uint32_t num_mod_decls) { avrule_block_t *cur = state->base->global; assert(cur != NULL); state->next_decl_id = 0; /* iterate through all of the declarations in the base, to determine what the next decl_id should be */ while (cur != NULL) { avrule_decl_t *decl; for (decl = cur->branch_list; decl != NULL; decl = decl->next) { if (decl->decl_id > state->next_decl_id) { state->next_decl_id = decl->decl_id; } } state->last_avrule_block = cur; cur = cur->next; } state->last_base_avrule_block = state->last_avrule_block; state->next_decl_id++; /* allocate the table mapping from base's decl_id to its * avrule_decls and set the initial mappings */ free(state->base->decl_val_to_struct); if ((state->base->decl_val_to_struct = calloc(state->next_decl_id + num_mod_decls, sizeof(*(state->base->decl_val_to_struct)))) == NULL) { ERR(state->handle, "Out of memory!"); return -1; } /* This allocates the decl block to module mapping used for error reporting */ if ((state->decl_to_mod = calloc(state->next_decl_id + num_mod_decls, sizeof(*(state->decl_to_mod)))) == NULL) { ERR(state->handle, "Out of memory!"); return -1; } cur = state->base->global; while (cur != NULL) { avrule_decl_t *decl = cur->branch_list; while (decl != NULL) { state->base->decl_val_to_struct[decl->decl_id - 1] = decl; state->decl_to_mod[decl->decl_id] = state->base; decl = decl->next; } cur = cur->next; } /* normalize conditionals within */ if (cond_normalize(state->base) < 0) { ERR(state->handle, "Error while normalizing conditionals within the base module."); return -1; } return 0; } static int expand_role_attributes(hashtab_key_t key, hashtab_datum_t datum, void * data) { char *id; role_datum_t *role, *sub_attr; link_state_t *state; unsigned int i; ebitmap_node_t *rnode; id = key; role = (role_datum_t *)datum; state = (link_state_t *)data; if (strcmp(id, OBJECT_R) == 0){ /* object_r is never a role attribute by far */ return 0; } if (role->flavor != ROLE_ATTRIB) return 0; if (state->verbose) INFO(state->handle, "expanding role attribute %s", id); restart: ebitmap_for_each_positive_bit(&role->roles, rnode, i) { sub_attr = state->base->role_val_to_struct[i]; if (sub_attr->flavor != ROLE_ATTRIB) continue; /* remove the sub role attribute from the parent * role attribute's roles ebitmap */ if (ebitmap_set_bit(&role->roles, i, 0)) return -1; /* loop dependency of role attributes */ if (sub_attr->s.value == role->s.value) continue; /* now go on to expand a sub role attribute * by escalating its roles ebitmap */ if (ebitmap_union(&role->roles, &sub_attr->roles)) { ERR(state->handle, "Out of memory!"); return -1; } /* sub_attr->roles may contain other role attributes, * re-scan the parent role attribute's roles ebitmap */ goto restart; } return 0; } /* For any role attribute in a declaration's local symtab[SYM_ROLES] table, * copy its roles ebitmap into its duplicate's in the base->p_roles.table. */ static int populate_decl_roleattributes(hashtab_key_t key, hashtab_datum_t datum, void *data) { char *id = key; role_datum_t *decl_role, *base_role; link_state_t *state = (link_state_t *)data; decl_role = (role_datum_t *)datum; if (strcmp(id, OBJECT_R) == 0) { /* object_r is never a role attribute by far */ return 0; } if (decl_role->flavor != ROLE_ATTRIB) return 0; base_role = (role_datum_t *)hashtab_search(state->base->p_roles.table, id); assert(base_role != NULL && base_role->flavor == ROLE_ATTRIB); if (ebitmap_union(&base_role->roles, &decl_role->roles)) { ERR(state->handle, "Out of memory!"); return -1; } return 0; } static int populate_roleattributes(link_state_t *state, policydb_t *pol) { avrule_block_t *block; avrule_decl_t *decl; if (state->verbose) INFO(state->handle, "Populating role-attribute relationship " "from enabled declarations' local symtab."); /* Iterate through all of the blocks skipping the first(which is the * global block, is required to be present and can't have an else). * If the block is disabled or not having an enabled decl, skip it. */ for (block = pol->global->next; block != NULL; block = block->next) { decl = block->enabled; if (decl == NULL || decl->enabled == 0) continue; if (hashtab_map(decl->symtab[SYM_ROLES].table, populate_decl_roleattributes, state)) return -1; } return 0; } /* Link a set of modules into a base module. This process is somewhat * similar to an actual compiler: it requires a set of order dependent * steps. The base and every module must have been indexed prior to * calling this function. */ int link_modules(sepol_handle_t * handle, policydb_t * b, policydb_t ** mods, int len, int verbose) { int i, ret, retval = -1; policy_module_t **modules = NULL; link_state_t state; uint32_t num_mod_decls = 0; memset(&state, 0, sizeof(state)); state.base = b; state.verbose = verbose; state.handle = handle; if (b->policy_type != POLICY_BASE) { ERR(state.handle, "Target of link was not a base policy."); return -1; } /* first allocate some space to hold the maps from module * symbol's value to the destination symbol value; then do * other preparation work */ if ((modules = (policy_module_t **) calloc(len, sizeof(*modules))) == NULL) { ERR(state.handle, "Out of memory!"); return -1; } for (i = 0; i < len; i++) { if (mods[i]->policy_type != POLICY_MOD) { ERR(state.handle, "Tried to link in a policy that was not a module."); goto cleanup; } if (mods[i]->mls != b->mls) { if (b->mls) ERR(state.handle, "Tried to link in a non-MLS module with an MLS base."); else ERR(state.handle, "Tried to link in an MLS module with a non-MLS base."); goto cleanup; } if (mods[i]->policyvers > b->policyvers) { WARN(state.handle, "Upgrading policy version from %u to %u", b->policyvers, mods[i]->policyvers); b->policyvers = mods[i]->policyvers; } if ((modules[i] = (policy_module_t *) calloc(1, sizeof(policy_module_t))) == NULL) { ERR(state.handle, "Out of memory!"); goto cleanup; } modules[i]->policy = mods[i]; if (prepare_module(&state, modules[i]) == -1) { goto cleanup; } num_mod_decls += modules[i]->num_decls; } if (prepare_base(&state, num_mod_decls) == -1) { goto cleanup; } /* copy and remap the module's data over to base */ for (i = 0; i < len; i++) { state.cur = modules[i]; ret = copy_module(&state, modules[i]); if (ret) { retval = ret; goto cleanup; } } /* re-index base, for symbols were added to symbol tables */ if (policydb_index_classes(state.base)) { ERR(state.handle, "Error while indexing classes"); goto cleanup; } if (policydb_index_others(state.handle, state.base, 0)) { ERR(state.handle, "Error while indexing others"); goto cleanup; } if (enable_avrules(&state, state.base)) { retval = SEPOL_EREQ; goto cleanup; } /* Now that all role attribute's roles ebitmap have been settled, * escalate sub role attribute's roles ebitmap into that of parent. * * First, since some role-attribute relationships could be recorded * in some decl's local symtab(see get_local_role()), we need to * populate them up to the base.p_roles table. */ if (populate_roleattributes(&state, state.base)) { retval = SEPOL_EREQ; goto cleanup; } /* Now do the escalation. */ if (hashtab_map(state.base->p_roles.table, expand_role_attributes, &state)) goto cleanup; retval = 0; cleanup: for (i = 0; modules != NULL && i < len; i++) { policy_module_destroy(modules[i]); } free(modules); free(state.decl_to_mod); return retval; } libsepol-3.8.1/src/mls.c000066400000000000000000000445161476211737200151060ustar00rootroot00000000000000/* Author : Stephen Smalley, */ /* * Updated: Trusted Computer Solutions, Inc. * * Support for enhanced MLS infrastructure. * * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* FLASK */ /* * Implementation of the multi-level security (MLS) policy. */ #include #include #include #include #include #include "handle.h" #include "debug.h" #include "private.h" #include "mls.h" int mls_to_string(sepol_handle_t * handle, const policydb_t * policydb, const context_struct_t * mls, char **str) { char *ptr = NULL, *ptr2 = NULL; /* Temporary buffer - length + NULL terminator */ int len = mls_compute_context_len(policydb, mls) + 1; ptr = (char *)malloc(len); if (ptr == NULL) goto omem; /* Final string w/ ':' cut off */ ptr2 = (char *)malloc(len - 1); if (ptr2 == NULL) goto omem; mls_sid_to_context(policydb, mls, &ptr); ptr -= len - 1; strcpy(ptr2, ptr + 1); free(ptr); *str = ptr2; return STATUS_SUCCESS; omem: ERR(handle, "out of memory, could not convert mls context to string"); free(ptr); free(ptr2); return STATUS_ERR; } int mls_from_string(sepol_handle_t * handle, const policydb_t * policydb, const char *str, context_struct_t * mls) { char *tmp = strdup(str); char *tmp_cp = tmp; if (!tmp) goto omem; if (mls_context_to_sid(policydb, '$', &tmp_cp, mls) < 0) { ERR(handle, "invalid MLS context %s", str); free(tmp); goto err; } free(tmp); return STATUS_SUCCESS; omem: ERR(handle, "out of memory"); err: ERR(handle, "could not construct mls context structure"); return STATUS_ERR; } /* * Return the length in bytes for the MLS fields of the * security context string representation of `context'. */ int mls_compute_context_len(const policydb_t * policydb, const context_struct_t * context) { unsigned int i, l, len, range; ebitmap_node_t *cnode; if (!policydb->mls) return 0; len = 1; /* for the beginning ":" */ for (l = 0; l < 2; l++) { range = 0; len += strlen(policydb-> p_sens_val_to_name[context->range.level[l].sens - 1]); ebitmap_for_each_bit(&context->range.level[l].cat, cnode, i) { if (ebitmap_node_get_bit(cnode, i)) { if (range) { range++; continue; } len += strlen(policydb->p_cat_val_to_name[i]) + 1; range++; } else { if (range > 1) len += strlen(policydb-> p_cat_val_to_name[i - 1]) + 1; range = 0; } } /* Handle case where last category is the end of range */ if (range > 1) len += strlen(policydb->p_cat_val_to_name[i - 1]) + 1; if (l == 0) { if (mls_level_eq(&context->range.level[0], &context->range.level[1])) break; else len++; } } return len; } /* * Write the security context string representation of * the MLS fields of `context' into the string `*scontext'. * Update `*scontext' to point to the end of the MLS fields. */ void mls_sid_to_context(const policydb_t * policydb, const context_struct_t * context, char **scontext) { char *scontextp; unsigned int i, l, range, wrote_sep; ebitmap_node_t *cnode; if (!policydb->mls) return; scontextp = *scontext; *scontextp = ':'; scontextp++; for (l = 0; l < 2; l++) { range = 0; wrote_sep = 0; strcpy(scontextp, policydb->p_sens_val_to_name[context->range.level[l]. sens - 1]); scontextp += strlen(policydb-> p_sens_val_to_name[context->range.level[l].sens - 1]); /* categories */ ebitmap_for_each_bit(&context->range.level[l].cat, cnode, i) { if (ebitmap_node_get_bit(cnode, i)) { if (range) { range++; continue; } if (!wrote_sep) { *scontextp++ = ':'; wrote_sep = 1; } else *scontextp++ = ','; strcpy(scontextp, policydb->p_cat_val_to_name[i]); scontextp += strlen(policydb->p_cat_val_to_name[i]); range++; } else { if (range > 1) { if (range > 2) *scontextp++ = '.'; else *scontextp++ = ','; strcpy(scontextp, policydb->p_cat_val_to_name[i - 1]); scontextp += strlen(policydb-> p_cat_val_to_name[i - 1]); } range = 0; } } /* Handle case where last category is the end of range */ if (range > 1) { if (range > 2) *scontextp++ = '.'; else *scontextp++ = ','; strcpy(scontextp, policydb->p_cat_val_to_name[i - 1]); scontextp += strlen(policydb->p_cat_val_to_name[i - 1]); } if (l == 0) { if (mls_level_eq(&context->range.level[0], &context->range.level[1])) break; else { *scontextp = '-'; scontextp++; } } } *scontext = scontextp; return; } /* * Return 1 if the MLS fields in the security context * structure `c' are valid. Return 0 otherwise. */ int mls_context_isvalid(const policydb_t * p, const context_struct_t * c) { level_datum_t *levdatum; user_datum_t *usrdatum; unsigned int i, l; ebitmap_node_t *cnode; hashtab_key_t key; if (!p->mls) return 1; /* * MLS range validity checks: high must dominate low, low level must * be valid (category set <-> sensitivity check), and high level must * be valid (category set <-> sensitivity check) */ if (!mls_level_dom(&c->range.level[1], &c->range.level[0])) /* High does not dominate low. */ return 0; for (l = 0; l < 2; l++) { if (!c->range.level[l].sens || c->range.level[l].sens > p->p_levels.nprim) return 0; key = p->p_sens_val_to_name[c->range.level[l].sens - 1]; if (!key) return 0; levdatum = (level_datum_t *) hashtab_search(p->p_levels.table, key); if (!levdatum) return 0; ebitmap_for_each_positive_bit(&c->range.level[l].cat, cnode, i) { if (i > p->p_cats.nprim) return 0; if (!ebitmap_get_bit(&levdatum->level->cat, i)) /* * Category may not be associated with * sensitivity in low level. */ return 0; } } if (c->role == OBJECT_R_VAL) return 1; /* * User must be authorized for the MLS range. */ if (!c->user || c->user > p->p_users.nprim) return 0; usrdatum = p->user_val_to_struct[c->user - 1]; if (!usrdatum || !mls_range_contains(usrdatum->exp_range, c->range)) return 0; /* user may not be associated with range */ return 1; } /* * Set the MLS fields in the security context structure * `context' based on the string representation in * the string `*scontext'. Update `*scontext' to * point to the end of the string representation of * the MLS fields. * * This function modifies the string in place, inserting * NULL characters to terminate the MLS fields. */ int mls_context_to_sid(const policydb_t * policydb, char oldc, char **scontext, context_struct_t * context) { char delim; char *scontextp, *p, *rngptr; level_datum_t *levdatum; cat_datum_t *catdatum, *rngdatum; unsigned int l; if (!policydb->mls) return 0; /* No MLS component to the security context */ if (!oldc) goto err; /* Extract low sensitivity. */ scontextp = p = *scontext; while (*p && *p != ':' && *p != '-') p++; delim = *p; if (delim != 0) *p++ = 0; for (l = 0; l < 2; l++) { levdatum = (level_datum_t *) hashtab_search(policydb->p_levels.table, (hashtab_key_t) scontextp); if (!levdatum) goto err; context->range.level[l].sens = levdatum->level->sens; if (delim == ':') { /* Extract category set. */ while (1) { scontextp = p; while (*p && *p != ',' && *p != '-') p++; delim = *p; if (delim != 0) *p++ = 0; /* Separate into range if exists */ if ((rngptr = strchr(scontextp, '.')) != NULL) { /* Remove '.' */ *rngptr++ = 0; } catdatum = (cat_datum_t *) hashtab_search(policydb-> p_cats.table, (hashtab_key_t) scontextp); if (!catdatum) goto err; if (ebitmap_set_bit (&context->range.level[l].cat, catdatum->s.value - 1, 1)) goto err; /* If range, set all categories in range */ if (rngptr) { unsigned int i; rngdatum = (cat_datum_t *) hashtab_search(policydb->p_cats. table, (hashtab_key_t) rngptr); if (!rngdatum) goto err; if (catdatum->s.value >= rngdatum->s.value) goto err; for (i = catdatum->s.value; i < rngdatum->s.value; i++) { if (ebitmap_set_bit (&context->range.level[l]. cat, i, 1)) goto err; } } if (delim != ',') break; } } if (delim == '-') { /* Extract high sensitivity. */ scontextp = p; while (*p && *p != ':') p++; delim = *p; if (delim != 0) *p++ = 0; } else break; } /* High level is missing, copy low level */ if (l == 0) { if (mls_level_cpy(&context->range.level[1], &context->range.level[0]) < 0) goto err; } *scontext = ++p; return STATUS_SUCCESS; err: return STATUS_ERR; } /* * Copies the MLS range from `src' into `dst'. */ static inline int mls_copy_context(context_struct_t * dst, const context_struct_t * src) { int l, rc = 0; /* Copy the MLS range from the source context */ for (l = 0; l < 2; l++) { dst->range.level[l].sens = src->range.level[l].sens; rc = ebitmap_cpy(&dst->range.level[l].cat, &src->range.level[l].cat); if (rc) break; } return rc; } /* * Copies the effective MLS range from `src' into `dst'. */ static inline int mls_scopy_context(context_struct_t * dst, const context_struct_t * src) { int l, rc = 0; /* Copy the MLS range from the source context */ for (l = 0; l < 2; l++) { dst->range.level[l].sens = src->range.level[0].sens; rc = ebitmap_cpy(&dst->range.level[l].cat, &src->range.level[0].cat); if (rc) break; } return rc; } /* * Copies the MLS range `range' into `context'. */ static inline int mls_range_set(context_struct_t * context, const mls_range_t * range) { int l, rc = 0; /* Copy the MLS range into the context */ for (l = 0; l < 2; l++) { context->range.level[l].sens = range->level[l].sens; rc = ebitmap_cpy(&context->range.level[l].cat, &range->level[l].cat); if (rc) break; } return rc; } int mls_setup_user_range(context_struct_t * fromcon, user_datum_t * user, context_struct_t * usercon, int mls) { if (mls) { mls_level_t *fromcon_sen = &(fromcon->range.level[0]); mls_level_t *fromcon_clr = &(fromcon->range.level[1]); mls_level_t *user_low = &(user->exp_range.level[0]); mls_level_t *user_clr = &(user->exp_range.level[1]); mls_level_t *user_def = &(user->exp_dfltlevel); mls_level_t *usercon_sen = &(usercon->range.level[0]); mls_level_t *usercon_clr = &(usercon->range.level[1]); /* Honor the user's default level if we can */ if (mls_level_between(user_def, fromcon_sen, fromcon_clr)) { *usercon_sen = *user_def; } else if (mls_level_between(fromcon_sen, user_def, user_clr)) { *usercon_sen = *fromcon_sen; } else if (mls_level_between(fromcon_clr, user_low, user_def)) { *usercon_sen = *user_low; } else return -EINVAL; /* Lower the clearance of available contexts if the clearance of "fromcon" is lower than that of the user's default clearance (but only if the "fromcon" clearance dominates the user's computed sensitivity level) */ if (mls_level_dom(user_clr, fromcon_clr)) { *usercon_clr = *fromcon_clr; } else if (mls_level_dom(fromcon_clr, user_clr)) { *usercon_clr = *user_clr; } else return -EINVAL; } return 0; } /* * Convert the MLS fields in the security context * structure `c' from the values specified in the * policy `oldp' to the values specified in the policy `newp'. */ int mls_convert_context(policydb_t * oldp, policydb_t * newp, context_struct_t * c) { level_datum_t *levdatum; cat_datum_t *catdatum; ebitmap_t bitmap; unsigned int l, i; ebitmap_node_t *cnode; if (!oldp->mls) return 0; for (l = 0; l < 2; l++) { levdatum = (level_datum_t *) hashtab_search(newp->p_levels.table, oldp-> p_sens_val_to_name[c-> range. level [l]. sens - 1]); if (!levdatum) return -EINVAL; c->range.level[l].sens = levdatum->level->sens; ebitmap_init(&bitmap); ebitmap_for_each_positive_bit(&c->range.level[l].cat, cnode, i) { int rc; catdatum = (cat_datum_t *) hashtab_search(newp->p_cats. table, oldp-> p_cat_val_to_name [i]); if (!catdatum) return -EINVAL; rc = ebitmap_set_bit(&bitmap, catdatum->s.value - 1, 1); if (rc) return rc; } ebitmap_destroy(&c->range.level[l].cat); c->range.level[l].cat = bitmap; } return 0; } int mls_compute_sid(policydb_t * policydb, const context_struct_t * scontext, const context_struct_t * tcontext, sepol_security_class_t tclass, uint32_t specified, context_struct_t * newcontext) { range_trans_t rtr; struct mls_range *r; struct class_datum *cladatum; int default_range = 0; if (!policydb->mls) return 0; switch (specified) { case AVTAB_TRANSITION: /* Look for a range transition rule. */ rtr.source_type = scontext->type; rtr.target_type = tcontext->type; rtr.target_class = tclass; r = hashtab_search(policydb->range_tr, (hashtab_key_t) &rtr); if (r) return mls_range_set(newcontext, r); if (tclass && tclass <= policydb->p_classes.nprim) { cladatum = policydb->class_val_to_struct[tclass - 1]; if (cladatum) default_range = cladatum->default_range; } switch (default_range) { case DEFAULT_SOURCE_LOW: return mls_context_cpy_low(newcontext, scontext); case DEFAULT_SOURCE_HIGH: return mls_context_cpy_high(newcontext, scontext); case DEFAULT_SOURCE_LOW_HIGH: return mls_context_cpy(newcontext, scontext); case DEFAULT_TARGET_LOW: return mls_context_cpy_low(newcontext, tcontext); case DEFAULT_TARGET_HIGH: return mls_context_cpy_high(newcontext, tcontext); case DEFAULT_TARGET_LOW_HIGH: return mls_context_cpy(newcontext, tcontext); case DEFAULT_GLBLUB: return mls_context_glblub(newcontext, scontext, tcontext); } /* Fallthrough */ case AVTAB_CHANGE: if (tclass == policydb->process_class) /* Use the process MLS attributes. */ return mls_copy_context(newcontext, scontext); else /* Use the process effective MLS attributes. */ return mls_scopy_context(newcontext, scontext); case AVTAB_MEMBER: /* Use the process effective MLS attributes. */ return mls_context_cpy_low(newcontext, scontext); default: return -EINVAL; } return -EINVAL; } int sepol_mls_contains(sepol_handle_t * handle, const sepol_policydb_t * policydb, const char *mls1, const char *mls2, int *response) { context_struct_t *ctx1 = NULL, *ctx2 = NULL; ctx1 = malloc(sizeof(context_struct_t)); ctx2 = malloc(sizeof(context_struct_t)); if (ctx1 == NULL || ctx2 == NULL){ ERR(handle, "out of memory"); goto omem; } context_init(ctx1); context_init(ctx2); if (mls_from_string(handle, &policydb->p, mls1, ctx1) < 0) goto err; if (mls_from_string(handle, &policydb->p, mls2, ctx2) < 0) goto err; *response = mls_range_contains(ctx1->range, ctx2->range); context_destroy(ctx1); context_destroy(ctx2); free(ctx1); free(ctx2); return STATUS_SUCCESS; err: context_destroy(ctx1); context_destroy(ctx2); omem: free(ctx1); free(ctx2); ERR(handle, "could not check if mls context %s contains %s", mls1, mls2); return STATUS_ERR; } int sepol_mls_check(sepol_handle_t * handle, const sepol_policydb_t * policydb, const char *mls) { int ret; context_struct_t *con = malloc(sizeof(context_struct_t)); if (!con) { ERR(handle, "out of memory, could not check if " "mls context %s is valid", mls); return STATUS_ERR; } context_init(con); ret = mls_from_string(handle, &policydb->p, mls, con); context_destroy(con); free(con); return ret; } void mls_semantic_cat_init(mls_semantic_cat_t * c) { memset(c, 0, sizeof(mls_semantic_cat_t)); } void mls_semantic_cat_destroy(mls_semantic_cat_t * c __attribute__ ((unused))) { /* it's currently a simple struct - really nothing to destroy */ return; } void mls_semantic_level_init(mls_semantic_level_t * l) { memset(l, 0, sizeof(mls_semantic_level_t)); } void mls_semantic_level_destroy(mls_semantic_level_t * l) { mls_semantic_cat_t *cur, *next; if (l == NULL) return; next = l->cat; while (next) { cur = next; next = cur->next; mls_semantic_cat_destroy(cur); free(cur); } } int mls_semantic_level_cpy(mls_semantic_level_t * dst, const mls_semantic_level_t * src) { const mls_semantic_cat_t *cat; mls_semantic_cat_t *newcat, *lnewcat = NULL; mls_semantic_level_init(dst); dst->sens = src->sens; cat = src->cat; while (cat) { newcat = (mls_semantic_cat_t *) malloc(sizeof(mls_semantic_cat_t)); if (!newcat) goto err; mls_semantic_cat_init(newcat); if (lnewcat) lnewcat->next = newcat; else dst->cat = newcat; newcat->low = cat->low; newcat->high = cat->high; lnewcat = newcat; cat = cat->next; } return 0; err: mls_semantic_level_destroy(dst); return -1; } void mls_semantic_range_init(mls_semantic_range_t * r) { mls_semantic_level_init(&r->level[0]); mls_semantic_level_init(&r->level[1]); } void mls_semantic_range_destroy(mls_semantic_range_t * r) { mls_semantic_level_destroy(&r->level[0]); mls_semantic_level_destroy(&r->level[1]); } int mls_semantic_range_cpy(mls_semantic_range_t * dst, const mls_semantic_range_t * src) { if (mls_semantic_level_cpy(&dst->level[0], &src->level[0]) < 0) return -1; if (mls_semantic_level_cpy(&dst->level[1], &src->level[1]) < 0) { mls_semantic_level_destroy(&dst->level[0]); return -1; } return 0; } libsepol-3.8.1/src/mls.h000066400000000000000000000046151476211737200151070ustar00rootroot00000000000000/* Author: Stephen Smalley, * Updated: Trusted Computer Solutions, Inc. * * Support for enhanced MLS infrastructure. * * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _SEPOL_MLS_INTERNAL_H_ #define _SEPOL_MLS_INTERNAL_H_ #include "policydb_internal.h" #include #include #include "handle.h" extern int mls_from_string(sepol_handle_t * handle, const policydb_t * policydb, const char *str, context_struct_t * mls); extern int mls_to_string(sepol_handle_t * handle, const policydb_t * policydb, const context_struct_t * mls, char **str); /* Deprecated */ extern int mls_compute_context_len(const policydb_t * policydb, const context_struct_t * context); /* Deprecated */ extern void mls_sid_to_context(const policydb_t * policydb, const context_struct_t * context, char **scontext); /* Deprecated */ extern int mls_context_to_sid(const policydb_t * policydb, char oldc, char **scontext, context_struct_t * context); extern int mls_context_isvalid(const policydb_t * p, const context_struct_t * c); extern int mls_convert_context(policydb_t * oldp, policydb_t * newp, context_struct_t * context); extern int mls_compute_sid(policydb_t * policydb, const context_struct_t * scontext, const context_struct_t * tcontext, sepol_security_class_t tclass, uint32_t specified, context_struct_t * newcontext); extern int mls_setup_user_range(context_struct_t * fromcon, user_datum_t * user, context_struct_t * usercon, int mls); #endif libsepol-3.8.1/src/module.c000066400000000000000000000566431476211737200156040ustar00rootroot00000000000000/* Author: Karl MacMillan * Jason Tang * Chris PeBenito * * Copyright (C) 2004-2005 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "policydb_internal.h" #include "module_internal.h" #include #include #include #include "debug.h" #include "private.h" #include #include #include #include #define SEPOL_PACKAGE_SECTION_FC 0xf97cff90 #define SEPOL_PACKAGE_SECTION_SEUSER 0x97cff91 #define SEPOL_PACKAGE_SECTION_USER_EXTRA 0x97cff92 #define SEPOL_PACKAGE_SECTION_NETFILTER 0x97cff93 static int policy_file_seek(struct policy_file *fp, size_t offset) { switch (fp->type) { case PF_USE_STDIO: if (offset > LONG_MAX) { errno = EFAULT; return -1; } return fseek(fp->fp, (long)offset, SEEK_SET); case PF_USE_MEMORY: if (offset > fp->size) { errno = EFAULT; return -1; } fp->data -= fp->size - fp->len; fp->data += offset; fp->len = fp->size - offset; return 0; default: return 0; } } static int policy_file_length(struct policy_file *fp, size_t *out) { long prev_offset, end_offset; int rc; switch (fp->type) { case PF_USE_STDIO: prev_offset = ftell(fp->fp); if (prev_offset < 0) return prev_offset; rc = fseek(fp->fp, 0L, SEEK_END); if (rc < 0) return rc; end_offset = ftell(fp->fp); if (end_offset < 0) return end_offset; rc = fseek(fp->fp, prev_offset, SEEK_SET); if (rc < 0) return rc; *out = end_offset; break; case PF_USE_MEMORY: *out = fp->size; break; default: *out = 0; break; } return 0; } static int module_package_init(sepol_module_package_t * p) { memset(p, 0, sizeof(sepol_module_package_t)); if (sepol_policydb_create(&p->policy)) return -1; p->version = 1; return 0; } static int set_char(char **field, char *data, size_t len) { if (*field) { free(*field); *field = NULL; } if (len) { *field = malloc(len); if (!*field) return -1; memcpy(*field, data, len); } return 0; } int sepol_module_package_create(sepol_module_package_t ** p) { int rc; *p = calloc(1, sizeof(sepol_module_package_t)); if (!(*p)) return -1; rc = module_package_init(*p); if (rc < 0) { free(*p); *p = NULL; } return rc; } /* Deallocates all memory associated with a module package, including * the pointer itself. Does nothing if p is NULL. */ void sepol_module_package_free(sepol_module_package_t * p) { if (p == NULL) return; sepol_policydb_free(p->policy); free(p->file_contexts); free(p->seusers); free(p->user_extra); free(p->netfilter_contexts); free(p); } char *sepol_module_package_get_file_contexts(sepol_module_package_t * p) { return p->file_contexts; } size_t sepol_module_package_get_file_contexts_len(sepol_module_package_t * p) { return p->file_contexts_len; } char *sepol_module_package_get_seusers(sepol_module_package_t * p) { return p->seusers; } size_t sepol_module_package_get_seusers_len(sepol_module_package_t * p) { return p->seusers_len; } char *sepol_module_package_get_user_extra(sepol_module_package_t * p) { return p->user_extra; } size_t sepol_module_package_get_user_extra_len(sepol_module_package_t * p) { return p->user_extra_len; } char *sepol_module_package_get_netfilter_contexts(sepol_module_package_t * p) { return p->netfilter_contexts; } size_t sepol_module_package_get_netfilter_contexts_len(sepol_module_package_t * p) { return p->netfilter_contexts_len; } int sepol_module_package_set_file_contexts(sepol_module_package_t * p, char *data, size_t len) { if (set_char(&p->file_contexts, data, len)) return -1; p->file_contexts_len = len; return 0; } int sepol_module_package_set_seusers(sepol_module_package_t * p, char *data, size_t len) { if (set_char(&p->seusers, data, len)) return -1; p->seusers_len = len; return 0; } int sepol_module_package_set_user_extra(sepol_module_package_t * p, char *data, size_t len) { if (set_char(&p->user_extra, data, len)) return -1; p->user_extra_len = len; return 0; } int sepol_module_package_set_netfilter_contexts(sepol_module_package_t * p, char *data, size_t len) { if (set_char(&p->netfilter_contexts, data, len)) return -1; p->netfilter_contexts_len = len; return 0; } sepol_policydb_t *sepol_module_package_get_policy(sepol_module_package_t * p) { return p->policy; } /* Append each of the file contexts from each module to the base * policy's file context. 'base_context' will be reallocated to a * larger size (and thus it is an in/out reference * variable). 'base_fc_len' is the length of base's file context; it * too is a reference variable. Return 0 on success, -1 if out of * memory. */ static int link_file_contexts(sepol_module_package_t * base, sepol_module_package_t ** modules, int num_modules) { size_t fc_len; int i; char *s; fc_len = base->file_contexts_len; for (i = 0; i < num_modules; i++) { fc_len += modules[i]->file_contexts_len; } if ((s = (char *)realloc(base->file_contexts, fc_len)) == NULL) { return -1; } base->file_contexts = s; for (i = 0; i < num_modules; i++) { memcpy(base->file_contexts + base->file_contexts_len, modules[i]->file_contexts, modules[i]->file_contexts_len); base->file_contexts_len += modules[i]->file_contexts_len; } return 0; } /* Append each of the netfilter contexts from each module to the base * policy's netfilter context. 'base_context' will be reallocated to a * larger size (and thus it is an in/out reference * variable). 'base_nc_len' is the length of base's netfilter contexts; it * too is a reference variable. Return 0 on success, -1 if out of * memory. */ static int link_netfilter_contexts(sepol_module_package_t * base, sepol_module_package_t ** modules, int num_modules) { size_t base_nc_len; int i; char *base_context; base_nc_len = base->netfilter_contexts_len; for (i = 0; i < num_modules; i++) { base_nc_len += modules[i]->netfilter_contexts_len; } if ((base_context = (char *)realloc(base->netfilter_contexts, base_nc_len)) == NULL) { return -1; } base->netfilter_contexts = base_context; for (i = 0; i < num_modules; i++) { if (modules[i]->netfilter_contexts_len > 0) { memcpy(base->netfilter_contexts + base->netfilter_contexts_len, modules[i]->netfilter_contexts, modules[i]->netfilter_contexts_len); base->netfilter_contexts_len += modules[i]->netfilter_contexts_len; } } return 0; } /* Links the module packages into the base. Returns 0 on success, -1 * if a requirement was not met, or -2 for all other errors. */ int sepol_link_packages(sepol_handle_t * handle, sepol_module_package_t * base, sepol_module_package_t ** modules, int num_modules, int verbose) { policydb_t **mod_pols = NULL; int i, retval; if ((mod_pols = calloc(num_modules, sizeof(*mod_pols))) == NULL) { ERR(handle, "Out of memory!"); return -2; } for (i = 0; i < num_modules; i++) { mod_pols[i] = &modules[i]->policy->p; } retval = link_modules(handle, &base->policy->p, mod_pols, num_modules, verbose); free(mod_pols); if (retval == -3) { return -1; } else if (retval < 0) { return -2; } if (link_file_contexts(base, modules, num_modules) == -1) { ERR(handle, "Out of memory!"); return -2; } if (link_netfilter_contexts(base, modules, num_modules) == -1) { ERR(handle, "Out of memory!"); return -2; } return 0; } /* buf must be large enough - no checks are performed */ #define _read_helper_bufsize BUFSIZ static int read_helper(char *buf, struct policy_file *file, uint32_t bytes) { uint32_t offset, nel, read_len; int rc; offset = 0; nel = bytes; while (nel) { if (nel < _read_helper_bufsize) read_len = nel; else read_len = _read_helper_bufsize; rc = next_entry(&buf[offset], file, read_len); if (rc < 0) return -1; offset += read_len; nel -= read_len; } return 0; } #define MAXSECTIONS 100 /* Get the section offsets from a package file, offsets will be malloc'd to * the appropriate size and the caller must free() them */ static int module_package_read_offsets(sepol_module_package_t * mod, struct policy_file *file, size_t ** offsets, uint32_t * sections) { uint32_t *buf = NULL, nsec; unsigned i; size_t *off = NULL; int rc; buf = malloc(sizeof(uint32_t)*3); if (!buf) { ERR(file->handle, "out of memory"); goto err; } rc = next_entry(buf, file, sizeof(uint32_t) * 3); if (rc < 0) { ERR(file->handle, "module package header truncated"); goto err; } if (le32_to_cpu(buf[0]) != SEPOL_MODULE_PACKAGE_MAGIC) { ERR(file->handle, "wrong magic number for module package: expected %#08x, got %#08x", SEPOL_MODULE_PACKAGE_MAGIC, le32_to_cpu(buf[0])); goto err; } mod->version = le32_to_cpu(buf[1]); nsec = *sections = le32_to_cpu(buf[2]); if (nsec > MAXSECTIONS) { ERR(file->handle, "too many sections (%u) in module package", nsec); goto err; } off = (size_t *) calloc(nsec + 1, sizeof(size_t)); if (!off) { ERR(file->handle, "out of memory"); goto err; } free(buf); buf = calloc(nsec, sizeof(uint32_t)); if (!buf) { ERR(file->handle, "out of memory"); goto err; } rc = next_entry(buf, file, sizeof(uint32_t) * nsec); if (rc < 0) { ERR(file->handle, "module package offset array truncated"); goto err; } for (i = 0; i < nsec; i++) { off[i] = le32_to_cpu(buf[i]); if (i && off[i] < off[i - 1]) { ERR(file->handle, "offsets are not increasing (at %u, " "offset %zu -> %zu", i, off[i - 1], off[i]); goto err; } } rc = policy_file_length(file, &off[nsec]); if (rc < 0) goto err; if (nsec && off[nsec] < off[nsec-1]) { ERR(file->handle, "offset greater than file size (at %u, " "offset %zu -> %zu", nsec, off[nsec - 1], off[nsec]); goto err; } *offsets = off; free(buf); return 0; err: free(buf); free(off); return -1; } /* Flags for which sections have been seen during parsing of module package. */ #define SEEN_MOD 1 #define SEEN_FC 2 #define SEEN_SEUSER 4 #define SEEN_USER_EXTRA 8 #define SEEN_NETFILTER 16 int sepol_module_package_read(sepol_module_package_t * mod, struct sepol_policy_file *spf, int verbose) { struct policy_file *file = &spf->pf; uint32_t buf[1], nsec; size_t *offsets, len; int rc; unsigned i, seen = 0; if (module_package_read_offsets(mod, file, &offsets, &nsec)) return -1; /* we know the section offsets, seek to them and read in the data */ for (i = 0; i < nsec; i++) { if (policy_file_seek(file, offsets[i])) { ERR(file->handle, "error seeking to offset %zu for " "module package section %u", offsets[i], i); goto cleanup; } len = offsets[i + 1] - offsets[i]; if (len < sizeof(uint32_t)) { ERR(file->handle, "module package section %u " "has too small length %zu", i, len); goto cleanup; } /* read the magic number, so that we know which function to call */ rc = next_entry(buf, file, sizeof(uint32_t)); if (rc < 0) { ERR(file->handle, "module package section %u truncated, lacks magic number", i); goto cleanup; } switch (le32_to_cpu(buf[0])) { case SEPOL_PACKAGE_SECTION_FC: if (seen & SEEN_FC) { ERR(file->handle, "found multiple file contexts sections in module package (at section %u)", i); goto cleanup; } mod->file_contexts_len = len - sizeof(uint32_t); mod->file_contexts = (char *)malloc(mod->file_contexts_len); if (!mod->file_contexts) { ERR(file->handle, "out of memory"); goto cleanup; } if (read_helper (mod->file_contexts, file, mod->file_contexts_len)) { ERR(file->handle, "invalid file contexts section at section %u", i); free(mod->file_contexts); mod->file_contexts = NULL; goto cleanup; } seen |= SEEN_FC; break; case SEPOL_PACKAGE_SECTION_SEUSER: if (seen & SEEN_SEUSER) { ERR(file->handle, "found multiple seuser sections in module package (at section %u)", i); goto cleanup; } mod->seusers_len = len - sizeof(uint32_t); mod->seusers = (char *)malloc(mod->seusers_len); if (!mod->seusers) { ERR(file->handle, "out of memory"); goto cleanup; } if (read_helper(mod->seusers, file, mod->seusers_len)) { ERR(file->handle, "invalid seuser section at section %u", i); free(mod->seusers); mod->seusers = NULL; goto cleanup; } seen |= SEEN_SEUSER; break; case SEPOL_PACKAGE_SECTION_USER_EXTRA: if (seen & SEEN_USER_EXTRA) { ERR(file->handle, "found multiple user_extra sections in module package (at section %u)", i); goto cleanup; } mod->user_extra_len = len - sizeof(uint32_t); mod->user_extra = (char *)malloc(mod->user_extra_len); if (!mod->user_extra) { ERR(file->handle, "out of memory"); goto cleanup; } if (read_helper (mod->user_extra, file, mod->user_extra_len)) { ERR(file->handle, "invalid user_extra section at section %u", i); free(mod->user_extra); mod->user_extra = NULL; goto cleanup; } seen |= SEEN_USER_EXTRA; break; case SEPOL_PACKAGE_SECTION_NETFILTER: if (seen & SEEN_NETFILTER) { ERR(file->handle, "found multiple netfilter contexts sections in module package (at section %u)", i); goto cleanup; } mod->netfilter_contexts_len = len - sizeof(uint32_t); mod->netfilter_contexts = (char *)malloc(mod->netfilter_contexts_len); if (!mod->netfilter_contexts) { ERR(file->handle, "out of memory"); goto cleanup; } if (read_helper (mod->netfilter_contexts, file, mod->netfilter_contexts_len)) { ERR(file->handle, "invalid netfilter contexts section at section %u", i); free(mod->netfilter_contexts); mod->netfilter_contexts = NULL; goto cleanup; } seen |= SEEN_NETFILTER; break; case POLICYDB_MOD_MAGIC: if (seen & SEEN_MOD) { ERR(file->handle, "found multiple module sections in module package (at section %u)", i); goto cleanup; } /* seek back to where the magic number was */ if (policy_file_seek(file, offsets[i])) goto cleanup; rc = policydb_read(&mod->policy->p, file, verbose); if (rc < 0) { ERR(file->handle, "invalid module in module package (at section %u)", i); goto cleanup; } seen |= SEEN_MOD; break; default: /* unknown section, ignore */ ERR(file->handle, "unknown magic number at section %u, offset: %zx, number: %x ", i, offsets[i], le32_to_cpu(buf[0])); break; } } if ((seen & SEEN_MOD) == 0) { ERR(file->handle, "missing module in module package"); goto cleanup; } free(offsets); return 0; cleanup: free(offsets); return -1; } int sepol_module_package_info(struct sepol_policy_file *spf, int *type, char **name, char **version) { struct policy_file *file = &spf->pf; sepol_module_package_t *mod = NULL; uint32_t buf[5], len, nsec; size_t *offsets = NULL; unsigned i, seen = 0; char *id; int rc; if (sepol_module_package_create(&mod)) return -1; if (module_package_read_offsets(mod, file, &offsets, &nsec)) { goto cleanup; } for (i = 0; i < nsec; i++) { if (policy_file_seek(file, offsets[i])) { ERR(file->handle, "error seeking to offset " "%zu for module package section %u", offsets[i], i); goto cleanup; } len = offsets[i + 1] - offsets[i]; if (len < sizeof(uint32_t)) { ERR(file->handle, "module package section %u has too small length %u", i, len); goto cleanup; } /* read the magic number, so that we know which function to call */ rc = next_entry(buf, file, sizeof(uint32_t) * 2); if (rc < 0) { ERR(file->handle, "module package section %u truncated, lacks magic number", i); goto cleanup; } switch (le32_to_cpu(buf[0])) { case SEPOL_PACKAGE_SECTION_FC: /* skip file contexts */ if (seen & SEEN_FC) { ERR(file->handle, "found multiple file contexts sections in module package (at section %u)", i); goto cleanup; } seen |= SEEN_FC; break; case SEPOL_PACKAGE_SECTION_SEUSER: /* skip seuser */ if (seen & SEEN_SEUSER) { ERR(file->handle, "found seuser sections in module package (at section %u)", i); goto cleanup; } seen |= SEEN_SEUSER; break; case SEPOL_PACKAGE_SECTION_USER_EXTRA: /* skip user_extra */ if (seen & SEEN_USER_EXTRA) { ERR(file->handle, "found user_extra sections in module package (at section %u)", i); goto cleanup; } seen |= SEEN_USER_EXTRA; break; case SEPOL_PACKAGE_SECTION_NETFILTER: /* skip netfilter contexts */ if (seen & SEEN_NETFILTER) { ERR(file->handle, "found multiple netfilter contexts sections in module package (at section %u)", i); goto cleanup; } seen |= SEEN_NETFILTER; break; case POLICYDB_MOD_MAGIC: if (seen & SEEN_MOD) { ERR(file->handle, "found multiple module sections in module package (at section %u)", i); goto cleanup; } len = le32_to_cpu(buf[1]); if (len != strlen(POLICYDB_MOD_STRING)) { ERR(file->handle, "module string length is wrong (at section %u)", i); goto cleanup; } /* skip id */ id = malloc(len + 1); if (!id) { ERR(file->handle, "out of memory (at section %u)", i); goto cleanup; } rc = next_entry(id, file, len); free(id); if (rc < 0) { ERR(file->handle, "cannot get module string (at section %u)", i); goto cleanup; } rc = next_entry(buf, file, sizeof(uint32_t) * 5); if (rc < 0) { ERR(file->handle, "cannot get module header (at section %u)", i); goto cleanup; } *type = le32_to_cpu(buf[0]); /* if base - we're done */ if (*type == POLICY_BASE) { *name = NULL; *version = NULL; seen |= SEEN_MOD; break; } else if (*type != POLICY_MOD) { ERR(file->handle, "module has invalid type %d (at section %u)", *type, i); goto cleanup; } /* read the name and version */ rc = next_entry(buf, file, sizeof(uint32_t)); if (rc < 0) { ERR(file->handle, "cannot get module name len (at section %u)", i); goto cleanup; } len = le32_to_cpu(buf[0]); if (str_read(name, file, len)) { ERR(file->handle, "cannot read module name (at section %u): %m", i); goto cleanup; } rc = next_entry(buf, file, sizeof(uint32_t)); if (rc < 0) { ERR(file->handle, "cannot get module version len (at section %u)", i); goto cleanup; } len = le32_to_cpu(buf[0]); if (str_read(version, file, len)) { ERR(file->handle, "cannot read module version (at section %u): %m", i); goto cleanup; } seen |= SEEN_MOD; break; default: break; } } if ((seen & SEEN_MOD) == 0) { ERR(file->handle, "missing module in module package"); goto cleanup; } sepol_module_package_free(mod); free(offsets); return 0; cleanup: sepol_module_package_free(mod); free(offsets); return -1; } static int write_helper(char *data, size_t len, struct policy_file *file) { int idx = 0; size_t len2; while (len) { if (len > BUFSIZ) len2 = BUFSIZ; else len2 = len; if (put_entry(&data[idx], 1, len2, file) != len2) { return -1; } len -= len2; idx += len2; } return 0; } int sepol_module_package_write(sepol_module_package_t * p, struct sepol_policy_file *spf) { struct policy_file *file = &spf->pf; policy_file_t polfile; uint32_t buf[5], offsets[5], len, nsec = 0; int i; if (p->policy) { /* compute policy length */ policy_file_init(&polfile); polfile.type = PF_LEN; polfile.handle = file->handle; if (policydb_write(&p->policy->p, &polfile)) return -1; len = polfile.len; if (!polfile.len) return -1; nsec++; } else { /* We don't support writing a package without a module at this point */ return -1; } /* seusers and user_extra only supported in base at the moment */ if ((p->seusers || p->user_extra) && (p->policy->p.policy_type != SEPOL_POLICY_BASE)) { ERR(file->handle, "seuser and user_extra sections only supported in base"); return -1; } if (p->file_contexts) nsec++; if (p->seusers) nsec++; if (p->user_extra) nsec++; if (p->netfilter_contexts) nsec++; buf[0] = cpu_to_le32(SEPOL_MODULE_PACKAGE_MAGIC); buf[1] = cpu_to_le32(p->version); buf[2] = cpu_to_le32(nsec); if (put_entry(buf, sizeof(uint32_t), 3, file) != 3) return -1; /* calculate offsets */ offsets[0] = (nsec + 3) * sizeof(uint32_t); buf[0] = cpu_to_le32(offsets[0]); i = 1; if (p->file_contexts) { offsets[i] = offsets[i - 1] + len; buf[i] = cpu_to_le32(offsets[i]); /* add a uint32_t to compensate for the magic number */ len = p->file_contexts_len + sizeof(uint32_t); i++; } if (p->seusers) { offsets[i] = offsets[i - 1] + len; buf[i] = cpu_to_le32(offsets[i]); len = p->seusers_len + sizeof(uint32_t); i++; } if (p->user_extra) { offsets[i] = offsets[i - 1] + len; buf[i] = cpu_to_le32(offsets[i]); len = p->user_extra_len + sizeof(uint32_t); i++; } if (p->netfilter_contexts) { offsets[i] = offsets[i - 1] + len; buf[i] = cpu_to_le32(offsets[i]); len = p->netfilter_contexts_len + sizeof(uint32_t); i++; } if (put_entry(buf, sizeof(uint32_t), nsec, file) != nsec) return -1; /* write sections */ if (policydb_write(&p->policy->p, file)) return -1; if (p->file_contexts) { buf[0] = cpu_to_le32(SEPOL_PACKAGE_SECTION_FC); if (put_entry(buf, sizeof(uint32_t), 1, file) != 1) return -1; if (write_helper(p->file_contexts, p->file_contexts_len, file)) return -1; } if (p->seusers) { buf[0] = cpu_to_le32(SEPOL_PACKAGE_SECTION_SEUSER); if (put_entry(buf, sizeof(uint32_t), 1, file) != 1) return -1; if (write_helper(p->seusers, p->seusers_len, file)) return -1; } if (p->user_extra) { buf[0] = cpu_to_le32(SEPOL_PACKAGE_SECTION_USER_EXTRA); if (put_entry(buf, sizeof(uint32_t), 1, file) != 1) return -1; if (write_helper(p->user_extra, p->user_extra_len, file)) return -1; } if (p->netfilter_contexts) { buf[0] = cpu_to_le32(SEPOL_PACKAGE_SECTION_NETFILTER); if (put_entry(buf, sizeof(uint32_t), 1, file) != 1) return -1; if (write_helper (p->netfilter_contexts, p->netfilter_contexts_len, file)) return -1; } return 0; } int sepol_link_modules(sepol_handle_t * handle, sepol_policydb_t * base, sepol_policydb_t ** modules, size_t len, int verbose) { return link_modules(handle, &base->p, (policydb_t **) modules, len, verbose); } int sepol_expand_module(sepol_handle_t * handle, sepol_policydb_t * base, sepol_policydb_t * out, int verbose, int check) { return expand_module(handle, &base->p, &out->p, verbose, check); } libsepol-3.8.1/src/module_internal.h000066400000000000000000000000331476211737200174630ustar00rootroot00000000000000#include libsepol-3.8.1/src/module_to_cil.c000066400000000000000000002652131476211737200171300ustar00rootroot00000000000000/* Authors: Steve Lawrence * * Functions to convert policy module to CIL * * Copyright (C) 2015 Tresys Technology, LLC * Copyright (C) 2017 Mellanox Technologies Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #ifndef IPPROTO_DCCP #define IPPROTO_DCCP 33 #endif #ifndef IPPROTO_SCTP #define IPPROTO_SCTP 132 #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "debug.h" #include "kernel_to_common.h" #include "private.h" #include "module_internal.h" #ifdef __GNUC__ # define UNUSED(x) UNUSED_ ## x __attribute__((__unused__)) #else # define UNUSED(x) UNUSED_ ## x #endif static FILE *out_file; #define STACK_SIZE 16 #define DEFAULT_LEVEL "systemlow" #define DEFAULT_OBJECT "object_r" #define GEN_REQUIRE_ATTR "cil_gen_require" /* Also in libsepol/cil/src/cil_post.c */ #define TYPEATTR_INFIX "_typeattr_" /* Also in libsepol/cil/src/cil_post.c */ #define ROLEATTR_INFIX "_roleattr_" static void cil_indent(int indent) { if (fprintf(out_file, "%*s", indent * 4, "") < 0) { ERR(NULL, "Failed to write to output"); _exit(EXIT_FAILURE); } } __attribute__ ((format(printf, 1, 2))) static void cil_printf(const char *fmt, ...) { va_list argptr; va_start(argptr, fmt); if (vfprintf(out_file, fmt, argptr) < 0) { ERR(NULL, "Failed to write to output"); _exit(EXIT_FAILURE); } va_end(argptr); } __attribute__ ((format(printf, 2, 3))) static void cil_println(int indent, const char *fmt, ...) { va_list argptr; cil_indent(indent); va_start(argptr, fmt); if (vfprintf(out_file, fmt, argptr) < 0) { ERR(NULL, "Failed to write to output"); _exit(EXIT_FAILURE); } va_end(argptr); if (fprintf(out_file, "\n") < 0) { ERR(NULL, "Failed to write to output"); _exit(EXIT_FAILURE); } } static int get_line(char **start, char *end, char **line) { int rc = 1; char *p = NULL; size_t len = 0; *line = NULL; for (p = *start; p < end && isspace(*p); p++); *start = p; for (len = 0; p < end && *p != '\n' && *p != '\0'; p++, len++); if (zero_or_saturated(len)) { rc = 0; goto exit; } *line = malloc(len+1); if (*line == NULL) { ERR(NULL, "Out of memory"); rc = -1; goto exit; } memcpy(*line, *start, len); (*line)[len] = '\0'; *start = p; return rc; exit: *start = NULL; return rc; } struct map_args { struct policydb *pdb; struct avrule_block *block; struct stack *decl_stack; int scope; int indent; int sym_index; }; struct stack { void **stack; int pos; int size; }; struct role_list_node { char *role_name; role_datum_t *role; }; struct attr_list_node { char *attr_name; int is_type; void *set; }; struct list_node { void *data; struct list_node *next; }; struct list { struct list_node *head; }; /* A linked list of all roles stored in the pdb * which is iterated to determine types associated * with each role when printing role_type statements */ static struct list *role_list; static void list_destroy(struct list **list) { struct list_node *curr = (*list)->head; struct list_node *tmp; while (curr != NULL) { tmp = curr->next; free(curr); curr = tmp; } free(*list); *list = NULL; } static void role_list_destroy(void) { struct list_node *curr; if (role_list == NULL) { return; } curr = role_list->head; while (curr != NULL) { free(curr->data); curr->data = NULL; curr = curr->next; } list_destroy(&role_list); } static void attr_list_destroy(struct list **attr_list) { struct list_node *curr; struct attr_list_node *attr; if (attr_list == NULL || *attr_list == NULL) { return; } curr = (*attr_list)->head; while (curr != NULL) { attr = curr->data; if (attr != NULL) { free(attr->attr_name); } free(curr->data); curr->data = NULL; curr = curr->next; } list_destroy(attr_list); } static int list_init(struct list **list) { struct list *l = calloc(1, sizeof(*l)); if (l == NULL) { return -1; } *list = l; return 0; } static int list_prepend(struct list *list, void *data) { int rc = -1; struct list_node *node = calloc(1, sizeof(*node)); if (node == NULL) { goto exit; } node->data = data; node->next = list->head; list->head = node; rc = 0; exit: return rc; } static int roles_gather_map(char *key, void *data, void *args) { struct role_list_node *role_node; role_datum_t *role = data; int rc = -1; role_node = calloc(1, sizeof(*role_node)); if (role_node == NULL) { return rc; } role_node->role_name = key; role_node->role = role; rc = list_prepend((struct list *)args, role_node); if (rc != 0) free(role_node); return rc; } static int role_list_create(hashtab_t roles_tab) { int rc = -1; rc = list_init(&role_list); if (rc != 0) { goto exit; } rc = hashtab_map(roles_tab, roles_gather_map, role_list); exit: return rc; } // array of lists, where each list contains all the aliases defined in the scope at index i static struct list **typealias_lists; static uint32_t typealias_lists_len; static int typealiases_gather_map(char *key, void *data, void *arg) { int rc = -1; struct type_datum *type = data; struct policydb *pdb = arg; struct scope_datum *scope; uint32_t len; uint32_t scope_id; if (type->primary != 1) { scope = hashtab_search(pdb->scope[SYM_TYPES].table, key); if (scope == NULL) { return -1; } len = scope->decl_ids_len; if (len > 0) { scope_id = scope->decl_ids[len-1]; if (typealias_lists[scope_id] == NULL) { rc = list_init(&typealias_lists[scope_id]); if (rc != 0) { goto exit; } } /* As typealias_lists[scope_id] does not hold the * ownership of its items (typealias_list_destroy does * not free the list items), "key" does not need to be * strdup'ed before it is inserted in the list. */ list_prepend(typealias_lists[scope_id], key); } } return 0; exit: return rc; } static void typealias_list_destroy(void) { uint32_t i; for (i = 0; i < typealias_lists_len; i++) { if (typealias_lists[i] != NULL) { list_destroy(&typealias_lists[i]); } } typealias_lists_len = 0; free(typealias_lists); typealias_lists = NULL; } static int typealias_list_create(struct policydb *pdb) { uint32_t max_decl_id = 0; struct avrule_decl *decl; struct avrule_block *block; uint32_t rc = -1; for (block = pdb->global; block != NULL; block = block->next) { decl = block->branch_list; if (decl != NULL && decl->decl_id > max_decl_id) { max_decl_id = decl->decl_id; } } typealias_lists = calloc(max_decl_id + 1, sizeof(*typealias_lists)); if (!typealias_lists) goto exit; typealias_lists_len = max_decl_id + 1; rc = hashtab_map(pdb->p_types.table, typealiases_gather_map, pdb); if (rc != 0) { goto exit; } return 0; exit: typealias_list_destroy(); return rc; } static int stack_destroy(struct stack **stack) { if (stack == NULL || *stack == NULL) { return 0; } free((*stack)->stack); free(*stack); *stack = NULL; return 0; } static int stack_init(struct stack **stack) { int rc = -1; struct stack *s = calloc(1, sizeof(*s)); if (s == NULL) { goto exit; } s->stack = calloc(STACK_SIZE, sizeof(*s->stack)); if (s->stack == NULL) { goto exit; } s->pos = -1; s->size = STACK_SIZE; *stack = s; return 0; exit: stack_destroy(&s); return rc; } static int stack_push(struct stack *stack, void *ptr) { int rc = -1; void *new_stack; if (stack->pos + 1 == stack->size) { new_stack = reallocarray(stack->stack, stack->size * 2, sizeof(*stack->stack)); if (new_stack == NULL) { goto exit; } stack->stack = new_stack; stack->size *= 2; } stack->pos++; stack->stack[stack->pos] = ptr; rc = 0; exit: return rc; } static void *stack_pop(struct stack *stack) { if (stack->pos == -1) { return NULL; } stack->pos--; return stack->stack[stack->pos + 1]; } static void *stack_peek(struct stack *stack) { if (stack->pos == -1) { return NULL; } return stack->stack[stack->pos]; } static int is_id_in_scope_with_start(struct policydb *pdb, struct stack *decl_stack, int start, uint32_t symbol_type, char *id) { int i; uint32_t j; struct avrule_decl *decl; struct scope_datum *scope; scope = hashtab_search(pdb->scope[symbol_type].table, id); if (scope == NULL) { return 0; } for (i = start; i >= 0; i--) { decl = decl_stack->stack[i]; for (j = 0; j < scope->decl_ids_len; j++) { if (scope->decl_ids[j] == decl->decl_id) { return 1; } } } return 0; } static int is_id_in_ancestor_scope(struct policydb *pdb, struct stack *decl_stack, char *type, uint32_t symbol_type) { int start = decl_stack->pos - 1; return is_id_in_scope_with_start(pdb, decl_stack, start, symbol_type, type); } static int is_id_in_scope(struct policydb *pdb, struct stack *decl_stack, char *type, uint32_t symbol_type) { int start = decl_stack->pos; return is_id_in_scope_with_start(pdb, decl_stack, start, symbol_type, type); } static int semantic_level_to_cil(struct policydb *pdb, int sens_offset, struct mls_semantic_level *level) { struct mls_semantic_cat *cat; cil_printf("(%s ", pdb->p_sens_val_to_name[level->sens - sens_offset]); if (level->cat != NULL) { cil_printf("("); } for (cat = level->cat; cat != NULL; cat = cat->next) { if (cat->low == cat->high) { cil_printf("%s", pdb->p_cat_val_to_name[cat->low - 1]); } else { cil_printf("range %s %s", pdb->p_cat_val_to_name[cat->low - 1], pdb->p_cat_val_to_name[cat->high - 1]); } if (cat->next != NULL) { cil_printf(" "); } } if (level->cat != NULL) { cil_printf(")"); } cil_printf(")"); return 0; } static int avrule_to_cil(int indent, struct policydb *pdb, uint32_t type, const char *src, const char *tgt, const struct class_perm_node *classperms) { int rc = -1; const char *rule; const struct class_perm_node *classperm; char *perms; switch (type) { case AVRULE_ALLOWED: rule = "allow"; break; case AVRULE_AUDITALLOW: rule = "auditallow"; break; case AVRULE_AUDITDENY: rule = "auditdeny"; break; case AVRULE_DONTAUDIT: rule = "dontaudit"; break; case AVRULE_NEVERALLOW: rule = "neverallow"; break; case AVRULE_TRANSITION: rule = "typetransition"; break; case AVRULE_MEMBER: rule = "typemember"; break; case AVRULE_CHANGE: rule = "typechange"; break; default: ERR(NULL, "Unknown avrule type: %i", type); rc = -1; goto exit; } for (classperm = classperms; classperm != NULL; classperm = classperm->next) { if (type & AVRULE_AV) { perms = sepol_av_to_string(pdb, classperm->tclass, classperm->data); if (perms == NULL) { ERR(NULL, "Failed to generate permission string"); rc = -1; goto exit; } if (*perms == '\0') { ERR(NULL, "No permissions in permission string"); free(perms); rc = -1; goto exit; } cil_println(indent, "(%s %s %s (%s (%s)))", rule, src, tgt, pdb->p_class_val_to_name[classperm->tclass - 1], perms + 1); free(perms); } else { cil_println(indent, "(%s %s %s %s %s)", rule, src, tgt, pdb->p_class_val_to_name[classperm->tclass - 1], pdb->p_type_val_to_name[classperm->data - 1]); } } return 0; exit: return rc; } #define next_bit_in_range(i, p) (((i) + 1 < sizeof(p)*8) && xperm_test(((i) + 1), p)) static int xperms_to_cil(const av_extended_perms_t *xperms) { uint16_t value; uint16_t low_bit; uint16_t low_value; unsigned int bit; unsigned int in_range = 0; int first = 1; if ((xperms->specified != AVTAB_XPERMS_IOCTLFUNCTION) && (xperms->specified != AVTAB_XPERMS_IOCTLDRIVER) && (xperms->specified != AVTAB_XPERMS_NLMSG)) return -1; for (bit = 0; bit < sizeof(xperms->perms)*8; bit++) { if (!xperm_test(bit, xperms->perms)) continue; if (in_range && next_bit_in_range(bit, xperms->perms)) { /* continue until high value found */ continue; } else if (next_bit_in_range(bit, xperms->perms)) { /* low value */ low_bit = bit; in_range = 1; continue; } if (!first) cil_printf(" "); else first = 0; if ((xperms->specified == AVTAB_XPERMS_IOCTLFUNCTION) || (xperms->specified == AVTAB_XPERMS_NLMSG)) { value = xperms->driver<<8 | bit; if (in_range) { low_value = xperms->driver<<8 | low_bit; cil_printf("(range 0x%hx 0x%hx)", low_value, value); in_range = 0; } else { cil_printf("0x%hx", value); } } else if (xperms->specified == AVTAB_XPERMS_IOCTLDRIVER) { value = bit << 8; if (in_range) { low_value = low_bit << 8; cil_printf("(range 0x%hx 0x%hx)", low_value, (uint16_t) (value|0xff)); in_range = 0; } else { cil_printf("(range 0x%hx 0x%hx)", value, (uint16_t) (value|0xff)); } } } return 0; } static int avrulex_to_cil(int indent, struct policydb *pdb, uint32_t type, const char *src, const char *tgt, const class_perm_node_t *classperms, const av_extended_perms_t *xperms) { int rc = -1; const char *rule; const char *xperm; const struct class_perm_node *classperm; switch (type) { case AVRULE_XPERMS_ALLOWED: rule = "allowx"; break; case AVRULE_XPERMS_AUDITALLOW: rule = "auditallowx"; break; case AVRULE_XPERMS_DONTAUDIT: rule = "dontauditx"; break; case AVRULE_XPERMS_NEVERALLOW: rule = "neverallowx"; break; default: ERR(NULL, "Unknown avrule xperm type: %i", type); rc = -1; goto exit; } if (xperms->specified == AVTAB_XPERMS_IOCTLFUNCTION || xperms->specified == AVTAB_XPERMS_IOCTLDRIVER) { xperm = "ioctl"; } else if (xperms->specified == AVTAB_XPERMS_NLMSG) { xperm = "nlmsg"; } else { ERR(NULL, "Unknown avrule xperms->specified: %i", xperms->specified); rc = -1; goto exit; } for (classperm = classperms; classperm != NULL; classperm = classperm->next) { cil_indent(indent); cil_printf("(%s %s %s (%s %s (", rule, src, tgt, xperm, pdb->p_class_val_to_name[classperm->tclass - 1]); xperms_to_cil(xperms); cil_printf(")))\n"); } return 0; exit: return rc; } static unsigned int num_digits(unsigned int n) { unsigned int num = 1; while (n >= 10) { n /= 10; num++; } return num; } static int ebitmap_to_cil(struct policydb *pdb, struct ebitmap *map, int type) { struct ebitmap_node *node; uint32_t i; char **val_to_name = pdb->sym_val_to_name[type]; ebitmap_for_each_positive_bit(map, node, i) { cil_printf("%s ", val_to_name[i]); } return 0; } static char *get_new_attr_name(struct policydb *pdb, int is_type) { static unsigned int num_attrs = 0; int len, rlen; const char *infix; char *attr_name = NULL; num_attrs++; if (is_type) { infix = TYPEATTR_INFIX; } else { infix = ROLEATTR_INFIX; } len = strlen(pdb->name) + strlen(infix) + num_digits(num_attrs) + 1; attr_name = malloc(len); if (!attr_name) { ERR(NULL, "Out of memory"); goto exit; } rlen = snprintf(attr_name, len, "%s%s%i", pdb->name, infix, num_attrs); if (rlen < 0 || rlen >= len) { ERR(NULL, "Failed to generate attribute name"); free(attr_name); attr_name = NULL; goto exit; } exit: return attr_name; } static int cil_add_attr_to_list(struct list *attr_list, char *attr_name, int is_type, void *set) { struct attr_list_node *attr_list_node = NULL; int rc = 0; attr_list_node = calloc(1, sizeof(*attr_list_node)); if (attr_list_node == NULL) { ERR(NULL, "Out of memory"); rc = -1; goto exit; } rc = list_prepend(attr_list, attr_list_node); if (rc != 0) { goto exit; } attr_list_node->attr_name = attr_name; attr_list_node->is_type = is_type; attr_list_node->set = set; return rc; exit: free(attr_list_node); return rc; } static int cil_print_attr_strs(int indent, struct policydb *pdb, int is_type, void *set, char *attr_name) { // CIL doesn't support anonymous positive/negative/complemented sets. So // instead we create a CIL type/roleattributeset that matches the set. If // the set has a negative set, then convert it to is (P & !N), where P is // the list of members in the positive set and N is the list of members // in the negative set. Additionally, if the set is complemented, then wrap // the whole thing with a negation. struct ebitmap_node *node; struct ebitmap *pos, *neg; uint32_t flags; unsigned i; struct type_set *ts; struct role_set *rs; int has_positive, has_negative; const char *kind; char **val_to_name; int rc = 0; if (is_type) { kind = "type"; val_to_name = pdb->p_type_val_to_name; ts = (struct type_set *)set; pos = &ts->types; neg = &ts->negset; flags = ts->flags; has_positive = pos && !ebitmap_is_empty(pos); has_negative = neg && !ebitmap_is_empty(neg); } else { kind = "role"; val_to_name = pdb->p_role_val_to_name; rs = (struct role_set *)set; pos = &rs->roles; neg = NULL; flags = rs->flags; has_positive = pos && !ebitmap_is_empty(pos); has_negative = 0; } cil_println(indent, "(%sattribute %s)", kind, attr_name); cil_indent(indent); cil_printf("(%sattributeset %s ", kind, attr_name); if (flags & TYPE_STAR) { cil_printf("(all)"); } if (flags & TYPE_COMP) { cil_printf("(not "); } if (has_positive && has_negative) { cil_printf("(and "); } if (has_positive) { cil_printf("("); ebitmap_for_each_positive_bit(pos, node, i) { cil_printf("%s ", val_to_name[i]); } cil_printf(") "); } if (has_negative) { cil_printf("(not ("); ebitmap_for_each_positive_bit(neg, node, i) { cil_printf("%s ", val_to_name[i]); } cil_printf("))"); } if (has_positive && has_negative) { cil_printf(")"); } if (flags & TYPE_COMP) { cil_printf(")"); } cil_printf(")\n"); return rc; } static int cil_print_attr_list(int indent, struct policydb *pdb, struct list *attr_list) { struct list_node *curr; struct attr_list_node *node; int rc = 0; for (curr = attr_list->head; curr != NULL; curr = curr->next) { node = curr->data; rc = cil_print_attr_strs(indent, pdb, node->is_type, node->set, node->attr_name); if (rc != 0) { return rc; } } return rc; } static char *search_attr_list(struct list *attr_list, int is_type, void *set) { struct list_node *curr; struct attr_list_node *node; struct role_set *rs1 = NULL, *rs2; struct type_set *ts1 = NULL, *ts2; if (is_type) { ts1 = (struct type_set *)set; } else { rs1 = (struct role_set *)set; } for (curr = attr_list->head; curr != NULL; curr = curr->next) { node = curr->data; if (node->is_type != is_type) continue; if (ts1) { ts2 = (struct type_set *)node->set; if (ts1->flags != ts2->flags) continue; if (ebitmap_cmp(&ts1->negset, &ts2->negset) == 0) continue; if (ebitmap_cmp(&ts1->types, &ts2->types) == 0) continue; return node->attr_name; } else { rs2 = (struct role_set *)node->set; if (rs1->flags != rs2->flags) continue; if (ebitmap_cmp(&rs1->roles, &rs2->roles) == 0) continue; return node->attr_name; } } return NULL; } static int set_to_names(struct policydb *pdb, int is_type, void *set, struct list *attr_list, char ***names, unsigned int *num_names) { char *attr_name = NULL; int rc = 0; *names = NULL; *num_names = 0; attr_name = search_attr_list(attr_list, is_type, set); if (!attr_name) { attr_name = get_new_attr_name(pdb, is_type); if (!attr_name) { rc = -1; goto exit; } rc = cil_add_attr_to_list(attr_list, attr_name, is_type, set); if (rc != 0) { free(attr_name); goto exit; } } *names = malloc(sizeof(char *)); if (!*names) { ERR(NULL, "Out of memory"); rc = -1; goto exit; } *names[0] = attr_name; *num_names = 1; exit: return rc; } static int ebitmap_to_names(struct ebitmap *map, char **vals_to_names, char ***names, unsigned int *num_names) { int rc = 0; struct ebitmap_node *node; uint32_t i; unsigned int num; char **name_arr; num = 0; ebitmap_for_each_positive_bit(map, node, i) { if (num >= UINT32_MAX / sizeof(*name_arr)) { ERR(NULL, "Overflow"); rc = -1; goto exit; } num++; } if (!num) { *names = NULL; *num_names = 0; goto exit; } name_arr = calloc(num, sizeof(*name_arr)); if (name_arr == NULL) { ERR(NULL, "Out of memory"); rc = -1; goto exit; } num = 0; ebitmap_for_each_positive_bit(map, node, i) { name_arr[num] = vals_to_names[i]; num++; } *names = name_arr; *num_names = num; exit: return rc; } static int process_roleset(struct policydb *pdb, struct role_set *rs, struct list *attr_list, char ***names, unsigned int *num_names) { int rc = 0; *names = NULL; *num_names = 0; if (rs->flags) { rc = set_to_names(pdb, 0, &rs->roles, attr_list, names, num_names); if (rc != 0) { goto exit; } } else { rc = ebitmap_to_names(&rs->roles, pdb->p_role_val_to_name, names, num_names); if (rc != 0) { goto exit; } } exit: return rc; } static int process_typeset(struct policydb *pdb, struct type_set *ts, struct list *attr_list, char ***names, unsigned int *num_names) { int rc = 0; *names = NULL; *num_names = 0; if (!ebitmap_is_empty(&ts->negset) || ts->flags != 0) { rc = set_to_names(pdb, 1, ts, attr_list, names, num_names); if (rc != 0) { goto exit; } } else { rc = ebitmap_to_names(&ts->types, pdb->p_type_val_to_name, names, num_names); if (rc != 0) { goto exit; } } exit: return rc; } static void names_destroy(char ***names, unsigned int *num_names) { free(*names); *names = NULL; *num_names = 0; } static int roletype_role_in_ancestor_to_cil(struct policydb *pdb, struct stack *decl_stack, char *type_name, int indent) { struct list_node *curr; char **tnames = NULL; unsigned int num_tnames, i; struct role_list_node *role_node = NULL; int rc; struct type_set *ts; struct list *attr_list = NULL; rc = list_init(&attr_list); if (rc != 0) { goto exit; } for (curr = role_list->head; curr != NULL; curr = curr->next) { role_node = curr->data; if (!is_id_in_ancestor_scope(pdb, decl_stack, role_node->role_name, SYM_ROLES)) { continue; } ts = &role_node->role->types; rc = process_typeset(pdb, ts, attr_list, &tnames, &num_tnames); if (rc != 0) { goto exit; } for (i = 0; i < num_tnames; i++) { if (!strcmp(type_name, tnames[i])) { cil_println(indent, "(roletype %s %s)", role_node->role_name, type_name); } } names_destroy(&tnames, &num_tnames); } rc = cil_print_attr_list(indent, pdb, attr_list); if (rc != 0) { goto exit; } exit: attr_list_destroy(&attr_list); return rc; } static int name_list_to_string(char **names, unsigned int num_names, char **string) { // create a space separated string of the names int rc = -1; size_t len = 0; unsigned int i; char *str; char *strpos; for (i = 0; i < num_names; i++) { if (__builtin_add_overflow(len, strlen(names[i]), &len)) { ERR(NULL, "Overflow"); return -1; } } // add spaces + null terminator if (__builtin_add_overflow(len, (size_t)num_names, &len)) { ERR(NULL, "Overflow"); return -1; } if (!len) { ERR(NULL, "Empty list"); return -1; } str = malloc(len); if (str == NULL) { ERR(NULL, "Out of memory"); rc = -1; goto exit; } str[0] = 0; strpos = str; for (i = 0; i < num_names; i++) { strpos = stpcpy(strpos, names[i]); if (i < num_names - 1) { *strpos++ = ' '; } } *string = str; return 0; exit: free(str); return rc; } static int avrule_list_to_cil(int indent, struct policydb *pdb, struct avrule *avrule_list, struct list *attr_list) { int rc = -1; struct avrule *avrule; char **snames = NULL; char **tnames = NULL; unsigned int s, t, num_snames, num_tnames; struct type_set *ts; for (avrule = avrule_list; avrule != NULL; avrule = avrule->next) { if ((avrule->specified & (AVRULE_NEVERALLOW|AVRULE_XPERMS_NEVERALLOW)) && avrule->source_filename) { cil_println(0, ";;* lmx %lu %s\n",avrule->source_line, avrule->source_filename); } ts = &avrule->stypes; rc = process_typeset(pdb, ts, attr_list, &snames, &num_snames); if (rc != 0) { goto exit; } if (avrule->flags & RULE_NOTSELF) { if (!ebitmap_is_empty(&avrule->ttypes.types) || !ebitmap_is_empty(&avrule->ttypes.negset)) { if (avrule->source_filename) { ERR(NULL, "%s:%lu: Non-trivial neverallow rules with targets containing not or minus self not yet supported", avrule->source_filename, avrule->source_line); } else { ERR(NULL, "Non-trivial neverallow rules with targets containing not or minus self not yet supported"); } rc = -1; goto exit; } num_tnames = 0; } else { ts = &avrule->ttypes; rc = process_typeset(pdb, ts, attr_list, &tnames, &num_tnames); if (rc != 0) { goto exit; } } for (s = 0; s < num_snames; s++) { for (t = 0; t < num_tnames; t++) { if (avrule->specified & AVRULE_XPERMS) { rc = avrulex_to_cil(indent, pdb, avrule->specified, snames[s], tnames[t], avrule->perms, avrule->xperms); } else { rc = avrule_to_cil(indent, pdb, avrule->specified, snames[s], tnames[t], avrule->perms); } if (rc != 0) { goto exit; } } if (avrule->flags & RULE_SELF) { if (avrule->specified & AVRULE_XPERMS) { rc = avrulex_to_cil(indent, pdb, avrule->specified, snames[s], "self", avrule->perms, avrule->xperms); } else { rc = avrule_to_cil(indent, pdb, avrule->specified, snames[s], "self", avrule->perms); } if (rc != 0) { goto exit; } } else if (avrule->flags & RULE_NOTSELF) { if (avrule->specified & AVRULE_XPERMS) { rc = avrulex_to_cil(indent, pdb, avrule->specified, snames[s], "notself", avrule->perms, avrule->xperms); } else { rc = avrule_to_cil(indent, pdb, avrule->specified, snames[s], "notself", avrule->perms); } if (rc != 0) { goto exit; } } } names_destroy(&snames, &num_snames); names_destroy(&tnames, &num_tnames); if ((avrule->specified & (AVRULE_NEVERALLOW|AVRULE_XPERMS_NEVERALLOW)) && avrule->source_filename) { cil_println(0, ";;* lme\n"); } } return 0; exit: names_destroy(&snames, &num_snames); names_destroy(&tnames, &num_tnames); return rc; } static int cond_expr_to_cil(int indent, struct policydb *pdb, struct cond_expr *cond_expr, uint32_t flags) { int rc = 0; struct cond_expr *curr; struct stack *stack = NULL; int len = 0; int rlen; char *new_val = NULL; char *val1 = NULL; char *val2 = NULL; unsigned int num_params; const char *op; const char *sep; const char *type; rc = stack_init(&stack); if (rc != 0) { ERR(NULL, "Out of memory"); goto exit; } for (curr = cond_expr; curr != NULL; curr = curr->next) { if (curr->expr_type == COND_BOOL) { val1 = pdb->p_bool_val_to_name[curr->boolean - 1]; // length of boolean + 2 parens + null terminator len = strlen(val1) + 2 + 1; new_val = malloc(len); if (new_val == NULL) { ERR(NULL, "Out of memory"); rc = -1; goto exit; } rlen = snprintf(new_val, len, "(%s)", val1); if (rlen < 0 || rlen >= len) { ERR(NULL, "Failed to generate conditional expression"); rc = -1; goto exit; } } else { switch(curr->expr_type) { case COND_NOT: op = "not"; break; case COND_OR: op = "or"; break; case COND_AND: op = "and"; break; case COND_XOR: op = "xor"; break; case COND_EQ: op = "eq"; break; case COND_NEQ: op = "neq"; break; default: rc = -1; goto exit; } num_params = curr->expr_type == COND_NOT ? 1 : 2; if (num_params == 1) { val1 = stack_pop(stack); val2 = strdup(""); if (val2 == NULL) { ERR(NULL, "Out of memory"); rc = -1; goto exit; } sep = ""; } else { val2 = stack_pop(stack); val1 = stack_pop(stack); sep = " "; } if (val1 == NULL || val2 == NULL) { ERR(NULL, "Invalid conditional expression"); rc = -1; goto exit; } // length = length of parameters + // length of operator + // 1 space preceding each parameter + // 2 parens around the whole expression // + null terminator len = strlen(val1) + strlen(val2) + strlen(op) + (num_params * 1) + 2 + 1; new_val = malloc(len); if (new_val == NULL) { ERR(NULL, "Out of memory"); rc = -1; goto exit; } rlen = snprintf(new_val, len, "(%s %s%s%s)", op, val1, sep, val2); if (rlen < 0 || rlen >= len) { ERR(NULL, "Failed to generate conditional expression"); rc = -1; goto exit; } free(val1); free(val2); val1 = NULL; val2 = NULL; } rc = stack_push(stack, new_val); if (rc != 0) { ERR(NULL, "Out of memory"); goto exit; } new_val = NULL; } if (flags & COND_NODE_FLAGS_TUNABLE) { type = "tunableif"; } else { type = "booleanif"; } val1 = stack_pop(stack); if (val1 == NULL || stack_peek(stack) != NULL) { ERR(NULL, "Invalid conditional expression"); rc = -1; goto exit; } cil_println(indent, "(%s %s", type, val1); free(val1); val1 = NULL; rc = 0; exit: free(new_val); free(val1); free(val2); if (stack != NULL) { while ((val1 = stack_pop(stack)) != NULL) { free(val1); } stack_destroy(&stack); } return rc; } static int cond_list_to_cil(int indent, struct policydb *pdb, struct cond_node *cond_list, struct list *attr_list) { int rc = 0; struct cond_node *cond; for (cond = cond_list; cond != NULL; cond = cond->next) { rc = cond_expr_to_cil(indent, pdb, cond->expr, cond->flags); if (rc != 0) { goto exit; } if (cond->avtrue_list != NULL) { cil_println(indent + 1, "(true"); rc = avrule_list_to_cil(indent + 2, pdb, cond->avtrue_list, attr_list); if (rc != 0) { goto exit; } cil_println(indent + 1, ")"); } if (cond->avfalse_list != NULL) { cil_println(indent + 1, "(false"); rc = avrule_list_to_cil(indent + 2, pdb, cond->avfalse_list, attr_list); if (rc != 0) { goto exit; } cil_println(indent + 1, ")"); } cil_println(indent, ")"); } exit: return rc; } static int role_trans_to_cil(int indent, struct policydb *pdb, struct role_trans_rule *rules, struct list *role_attr_list, struct list *type_attr_list) { int rc = 0; struct role_trans_rule *rule; char **role_names = NULL; unsigned int num_role_names = 0; unsigned int role; char **type_names = NULL; unsigned int num_type_names = 0; unsigned int type; uint32_t i; struct ebitmap_node *node; struct type_set *ts; struct role_set *rs; for (rule = rules; rule != NULL; rule = rule->next) { rs = &rule->roles; rc = process_roleset(pdb, rs, role_attr_list, &role_names, &num_role_names); if (rc != 0) { goto exit; } ts = &rule->types; rc = process_typeset(pdb, ts, type_attr_list, &type_names, &num_type_names); if (rc != 0) { goto exit; } for (role = 0; role < num_role_names; role++) { for (type = 0; type < num_type_names; type++) { ebitmap_for_each_positive_bit(&rule->classes, node, i) { cil_println(indent, "(roletransition %s %s %s %s)", role_names[role], type_names[type], pdb->p_class_val_to_name[i], pdb->p_role_val_to_name[rule->new_role - 1]); } } } names_destroy(&role_names, &num_role_names); names_destroy(&type_names, &num_type_names); } exit: names_destroy(&role_names, &num_role_names); names_destroy(&type_names, &num_type_names); return rc; } static int role_allows_to_cil(int indent, struct policydb *pdb, struct role_allow_rule *rules, struct list *attr_list) { int rc = -1; struct role_allow_rule *rule; char **roles = NULL; unsigned int num_roles = 0; char **new_roles = NULL; unsigned int num_new_roles = 0; unsigned int i, j; struct role_set *rs; for (rule = rules; rule != NULL; rule = rule->next) { rs = &rule->roles; rc = process_roleset(pdb, rs, attr_list, &roles, &num_roles); if (rc != 0) { goto exit; } rs = &rule->new_roles; rc = process_roleset(pdb, rs, attr_list, &new_roles, &num_new_roles); if (rc != 0) { goto exit; } for (i = 0; i < num_roles; i++) { for (j = 0; j < num_new_roles; j++) { cil_println(indent, "(roleallow %s %s)", roles[i], new_roles[j]); } } names_destroy(&roles, &num_roles); names_destroy(&new_roles, &num_new_roles); } rc = 0; exit: names_destroy(&roles, &num_roles); names_destroy(&new_roles, &num_new_roles); return rc; } static int range_trans_to_cil(int indent, struct policydb *pdb, struct range_trans_rule *rules, struct list *attr_list) { int rc = -1; struct range_trans_rule *rule; char **stypes = NULL; unsigned int num_stypes = 0; unsigned int stype; char **ttypes = NULL; unsigned int num_ttypes = 0; unsigned int ttype; struct ebitmap_node *node; uint32_t i; struct type_set *ts; if (!pdb->mls) { return 0; } for (rule = rules; rule != NULL; rule = rule->next) { ts = &rule->stypes; rc = process_typeset(pdb, ts, attr_list, &stypes, &num_stypes); if (rc != 0) { goto exit; } ts = &rule->ttypes; rc = process_typeset(pdb, ts, attr_list, &ttypes, &num_ttypes); if (rc != 0) { goto exit; } for (stype = 0; stype < num_stypes; stype++) { for (ttype = 0; ttype < num_ttypes; ttype++) { ebitmap_for_each_positive_bit(&rule->tclasses, node, i) { cil_indent(indent); cil_printf("(rangetransition %s %s %s ", stypes[stype], ttypes[ttype], pdb->p_class_val_to_name[i]); cil_printf("("); rc = semantic_level_to_cil(pdb, 1, &rule->trange.level[0]); if (rc != 0) { goto exit; } cil_printf(" "); rc = semantic_level_to_cil(pdb, 1, &rule->trange.level[1]); if (rc != 0) { goto exit; } cil_printf("))\n"); } } } names_destroy(&stypes, &num_stypes); names_destroy(&ttypes, &num_ttypes); } rc = 0; exit: names_destroy(&stypes, &num_stypes); names_destroy(&ttypes, &num_ttypes); return rc; } static int filename_trans_to_cil(int indent, struct policydb *pdb, struct filename_trans_rule *rules, struct list *attr_list) { int rc = -1; char **stypes = NULL; unsigned int num_stypes = 0; unsigned int stype; char **ttypes = NULL; unsigned int num_ttypes = 0; unsigned int ttype; struct type_set *ts; struct filename_trans_rule *rule; for (rule = rules; rule != NULL; rule = rule->next) { ts = &rule->stypes; rc = process_typeset(pdb, ts, attr_list, &stypes, &num_stypes); if (rc != 0) { goto exit; } ts = &rule->ttypes; rc = process_typeset(pdb, ts, attr_list, &ttypes, &num_ttypes); if (rc != 0) { goto exit; } for (stype = 0; stype < num_stypes; stype++) { for (ttype = 0; ttype < num_ttypes; ttype++) { cil_println(indent, "(typetransition %s %s %s \"%s\" %s)", stypes[stype], ttypes[ttype], pdb->p_class_val_to_name[rule->tclass - 1], rule->name, pdb->p_type_val_to_name[rule->otype - 1]); } if (rule->flags & RULE_SELF) { cil_println(indent, "(typetransition %s self %s \"%s\" %s)", stypes[stype], pdb->p_class_val_to_name[rule->tclass - 1], rule->name, pdb->p_type_val_to_name[rule->otype - 1]); } } names_destroy(&stypes, &num_stypes); names_destroy(&ttypes, &num_ttypes); } rc = 0; exit: names_destroy(&stypes, &num_stypes); names_destroy(&ttypes, &num_ttypes); return rc; } struct class_perm_datum { char *name; uint32_t val; }; struct class_perm_array { struct class_perm_datum *perms; uint32_t count; }; static int class_perm_to_array(char *key, void *data, void *args) { struct class_perm_array *arr = args; struct perm_datum *datum = data; arr->perms[arr->count].name = key; arr->perms[arr->count].val = datum->s.value; arr->count++; return 0; } static int class_perm_cmp(const void *a, const void *b) { const struct class_perm_datum *aa = a; const struct class_perm_datum *bb = b; return spaceship_cmp(aa->val, bb->val); } static int common_to_cil(char *key, void *data, void *UNUSED(arg)) { int rc = -1; struct common_datum *common = data; struct class_perm_array arr; uint32_t i; arr.count = 0; arr.perms = calloc(common->permissions.nprim, sizeof(*arr.perms)); if (arr.perms == NULL) { goto exit; } rc = hashtab_map(common->permissions.table, class_perm_to_array, &arr); if (rc != 0) { goto exit; } qsort(arr.perms, arr.count, sizeof(*arr.perms), class_perm_cmp); cil_printf("(common %s (", key); for (i = 0; i < arr.count; i++) { cil_printf("%s ", arr.perms[i].name); } cil_printf("))\n"); rc = 0; exit: free(arr.perms); return rc; } static int constraint_expr_to_string(struct policydb *pdb, struct constraint_expr *exprs, char **expr_string) { int rc = -1; struct constraint_expr *expr; struct stack *stack = NULL; int len = 0; int rlen; char *new_val = NULL; char *val1 = NULL; char *val2 = NULL; uint32_t num_params; const char *op; const char *sep; const char *attr1; const char *attr2; char *names = NULL; char **name_list = NULL; unsigned int num_names = 0; struct type_set *ts; rc = stack_init(&stack); if (rc != 0) { goto exit; } for (expr = exprs; expr != NULL; expr = expr->next) { if (expr->expr_type == CEXPR_ATTR || expr->expr_type == CEXPR_NAMES) { switch (expr->op) { case CEXPR_EQ: op = "eq"; break; case CEXPR_NEQ: op = "neq"; break; case CEXPR_DOM: op = "dom"; break; case CEXPR_DOMBY: op = "domby"; break; case CEXPR_INCOMP: op = "incomp"; break; default: ERR(NULL, "Unknown constraint operator type: %i", expr->op); rc = -1; goto exit; } switch (expr->attr) { case CEXPR_USER: attr1 = "u1"; attr2 = "u2"; break; case CEXPR_USER | CEXPR_TARGET: attr1 = "u2"; attr2 = ""; break; case CEXPR_USER | CEXPR_XTARGET: attr1 = "u3"; attr2 = ""; break; case CEXPR_ROLE: attr1 = "r1"; attr2 = "r2"; break; case CEXPR_ROLE | CEXPR_TARGET: attr1 = "r2"; attr2 = ""; break; case CEXPR_ROLE | CEXPR_XTARGET: attr1 = "r3"; attr2 = ""; break; case CEXPR_TYPE: attr1 = "t1"; attr2 = "t2"; break; case CEXPR_TYPE | CEXPR_TARGET: attr1 = "t2"; attr2 = ""; break; case CEXPR_TYPE | CEXPR_XTARGET: attr1 = "t3"; attr2 = ""; break; case CEXPR_L1L2: attr1 = "l1"; attr2 = "l2"; break; case CEXPR_L1H2: attr1 = "l1"; attr2 = "h2"; break; case CEXPR_H1L2: attr1 = "h1"; attr2 = "l2"; break; case CEXPR_H1H2: attr1 = "h1"; attr2 = "h2"; break; case CEXPR_L1H1: attr1 = "l1"; attr2 = "h1"; break; case CEXPR_L2H2: attr1 = "l2"; attr2 = "h2"; break; default: ERR(NULL, "Unknown expression attribute type: %i", expr->attr); rc = -1; goto exit; } if (expr->expr_type == CEXPR_ATTR) { // length of values/attrs + 2 separating spaces + 2 parens + null terminator len = strlen(op) + strlen(attr1) + strlen(attr2) + 2 + 2 + 1; new_val = malloc(len); if (new_val == NULL) { ERR(NULL, "Out of memory"); rc = -1; goto exit; } rlen = snprintf(new_val, len, "(%s %s %s)", op, attr1, attr2); if (rlen < 0 || rlen >= len) { ERR(NULL, "Failed to generate constraint expression"); rc = -1; goto exit; } } else { if (expr->attr & CEXPR_TYPE) { ts = expr->type_names; rc = ebitmap_to_names(&ts->types, pdb->p_type_val_to_name, &name_list, &num_names); if (rc != 0) { goto exit; } } else if (expr->attr & CEXPR_USER) { rc = ebitmap_to_names(&expr->names, pdb->p_user_val_to_name, &name_list, &num_names); if (rc != 0) { goto exit; } } else if (expr->attr & CEXPR_ROLE) { rc = ebitmap_to_names(&expr->names, pdb->p_role_val_to_name, &name_list, &num_names); if (rc != 0) { goto exit; } } if (num_names == 0) { names = strdup("NO_IDENTIFIER"); if (!names) { rc = -1; goto exit; } } else { rc = name_list_to_string(name_list, num_names, &names); if (rc != 0) { goto exit; } } // length of values/oper + 2 spaces + 2 parens + null terminator len = strlen(op) + strlen(attr1) + strlen(names) + 2 + 2 + 1; if (num_names > 1) { len += 2; // 2 more parens } new_val = malloc(len); if (new_val == NULL) { ERR(NULL, "Out of memory"); rc = -1; goto exit; } if (num_names > 1) { rlen = snprintf(new_val, len, "(%s %s (%s))", op, attr1, names); } else { rlen = snprintf(new_val, len, "(%s %s %s)", op, attr1, names); } if (rlen < 0 || rlen >= len) { ERR(NULL, "Failed to generate constraint expression"); rc = -1; goto exit; } names_destroy(&name_list, &num_names); free(names); names = NULL; } } else { switch (expr->expr_type) { case CEXPR_NOT: op = "not"; break; case CEXPR_AND: op = "and"; break; case CEXPR_OR: op = "or"; break; default: ERR(NULL, "Unknown constraint expression type: %i", expr->expr_type); rc = -1; goto exit; } num_params = expr->expr_type == CEXPR_NOT ? 1 : 2; if (num_params == 1) { val1 = stack_pop(stack); val2 = strdup(""); if (val2 == NULL) { ERR(NULL, "Out of memory"); rc = -1; goto exit; } sep = ""; } else { val2 = stack_pop(stack); val1 = stack_pop(stack); sep = " "; } if (val1 == NULL || val2 == NULL) { ERR(NULL, "Invalid constraint expression"); rc = -1; goto exit; } // length = length of parameters + // length of operator + // 1 space preceding each parameter + // 2 parens around the whole expression // + null terminator len = strlen(val1) + strlen(val2) + strlen(op) + (num_params * 1) + 2 + 1; new_val = malloc(len); if (new_val == NULL) { ERR(NULL, "Out of memory"); rc = -1; goto exit; } rlen = snprintf(new_val, len, "(%s %s%s%s)", op, val1, sep, val2); if (rlen < 0 || rlen >= len) { ERR(NULL, "Failed to generate constraint expression"); rc = -1; goto exit; } free(val1); free(val2); val1 = NULL; val2 = NULL; } rc = stack_push(stack, new_val); if (rc != 0) { ERR(NULL, "Out of memory"); goto exit; } new_val = NULL; } new_val = stack_pop(stack); if (new_val == NULL || stack_peek(stack) != NULL) { ERR(NULL, "Invalid constraint expression"); rc = -1; goto exit; } *expr_string = new_val; new_val = NULL; rc = 0; exit: names_destroy(&name_list, &num_names); free(names); free(new_val); free(val1); free(val2); if (stack != NULL) { while ((val1 = stack_pop(stack)) != NULL) { free(val1); } stack_destroy(&stack); } return rc; } static int constraints_to_cil(int indent, struct policydb *pdb, char *classkey, struct class_datum *class, struct constraint_node *constraints, int is_constraint) { int rc = -1; struct constraint_node *node; char *expr = NULL; const char *mls; char *perms; mls = pdb->mls ? "mls" : ""; for (node = constraints; node != NULL; node = node->next) { rc = constraint_expr_to_string(pdb, node->expr, &expr); if (rc != 0) { goto exit; } if (is_constraint) { perms = sepol_av_to_string(pdb, class->s.value, node->permissions); if (perms == NULL) { ERR(NULL, "Failed to generate permission string"); rc = -1; goto exit; } if (*perms == '\0') { ERR(NULL, "No permissions in permission string"); free(perms); rc = -1; goto exit; } cil_println(indent, "(%sconstrain (%s (%s)) %s)", mls, classkey, perms + 1, expr); free(perms); } else { cil_println(indent, "(%svalidatetrans %s %s)", mls, classkey, expr); } free(expr); expr = NULL; } rc = 0; exit: free(expr); return rc; } static int class_to_cil(int indent, struct policydb *pdb, struct avrule_block *UNUSED(block), struct stack *UNUSED(decl_stack), char *key, void *datum, int scope) { int rc = -1; struct class_datum *class = datum; const char *dflt; struct class_perm_array arr; uint32_t i; if (scope == SCOPE_REQ) { return 0; } arr.count = 0; arr.perms = calloc(class->permissions.nprim, sizeof(*arr.perms)); if (arr.perms == NULL) { goto exit; } rc = hashtab_map(class->permissions.table, class_perm_to_array, &arr); if (rc != 0) { goto exit; } qsort(arr.perms, arr.count, sizeof(*arr.perms), class_perm_cmp); cil_indent(indent); cil_printf("(class %s (", key); for (i = 0; i < arr.count; i++) { cil_printf("%s ", arr.perms[i].name); } cil_printf("))\n"); if (class->comkey != NULL) { cil_println(indent, "(classcommon %s %s)", key, class->comkey); } if (class->default_user != 0) { switch (class->default_user) { case DEFAULT_SOURCE: dflt = "source"; break; case DEFAULT_TARGET: dflt = "target"; break; default: ERR(NULL, "Unknown default user value: %i", class->default_user); rc = -1; goto exit; } cil_println(indent, "(defaultuser %s %s)", key, dflt); } if (class->default_role != 0) { switch (class->default_role) { case DEFAULT_SOURCE: dflt = "source"; break; case DEFAULT_TARGET: dflt = "target"; break; default: ERR(NULL, "Unknown default role value: %i", class->default_role); rc = -1; goto exit; } cil_println(indent, "(defaultrole %s %s)", key, dflt); } if (class->default_type != 0) { switch (class->default_type) { case DEFAULT_SOURCE: dflt = "source"; break; case DEFAULT_TARGET: dflt = "target"; break; default: ERR(NULL, "Unknown default type value: %i", class->default_type); rc = -1; goto exit; } cil_println(indent, "(defaulttype %s %s)", key, dflt); } if (class->default_range != 0) { switch (class->default_range) { case DEFAULT_SOURCE_LOW: dflt = "source low"; break; case DEFAULT_SOURCE_HIGH: dflt = "source high"; break; case DEFAULT_SOURCE_LOW_HIGH: dflt = "source low-high"; break; case DEFAULT_TARGET_LOW: dflt = "target low"; break; case DEFAULT_TARGET_HIGH: dflt = "target high"; break; case DEFAULT_TARGET_LOW_HIGH: dflt = "target low-high"; break; case DEFAULT_GLBLUB: dflt = "glblub"; break; default: ERR(NULL, "Unknown default range value: %i", class->default_range); rc = -1; goto exit; } cil_println(indent, "(defaultrange %s %s)", key, dflt); } if (class->constraints != NULL) { rc = constraints_to_cil(indent, pdb, key, class, class->constraints, 1); if (rc != 0) { goto exit; } } if (class->validatetrans != NULL) { rc = constraints_to_cil(indent, pdb, key, class, class->validatetrans, 0); if (rc != 0) { goto exit; } } rc = 0; exit: free(arr.perms); return rc; } static int class_order_to_cil(int indent, struct policydb *pdb, struct ebitmap order) { struct ebitmap_node *node; uint32_t i; if (ebitmap_is_empty(&order)) { return 0; } cil_indent(indent); cil_printf("(classorder ("); ebitmap_for_each_positive_bit(&order, node, i) { cil_printf("%s ", pdb->sym_val_to_name[SYM_CLASSES][i]); } cil_printf("))\n"); return 0; } static int role_to_cil(int indent, struct policydb *pdb, struct avrule_block *UNUSED(block), struct stack *decl_stack, char *key, void *datum, int scope) { int rc = -1; struct ebitmap_node *node; uint32_t i; unsigned int j; char **types = NULL; unsigned int num_types = 0; struct role_datum *role = datum; struct type_set *ts; struct list *attr_list = NULL; rc = list_init(&attr_list); if (rc != 0) { goto exit; } if (scope == SCOPE_REQ) { // if a role/roleattr is in the REQ scope, then it could cause an // optional block to fail, even if it is never used. However in CIL, // symbols must be used in order to cause an optional block to fail. So // for symbols in the REQ scope, add them to a roleattribute as a way // to 'use' them in the optional without affecting the resulting policy. cil_println(indent, "(roleattributeset " GEN_REQUIRE_ATTR " %s)", key); } switch (role->flavor) { case ROLE_ROLE: if (scope == SCOPE_DECL) { cil_println(indent, "(role %s)", key); } if (ebitmap_cardinality(&role->dominates) > 1) { ERR(NULL, "Warning: role 'dominance' statement unsupported in CIL. Dropping from output."); } ts = &role->types; rc = process_typeset(pdb, ts, attr_list, &types, &num_types); if (rc != 0) { goto exit; } for (j = 0; j < num_types; j++) { if (is_id_in_scope(pdb, decl_stack, types[j], SYM_TYPES)) { cil_println(indent, "(roletype %s %s)", key, types[j]); } } if (role->bounds > 0) { cil_println(indent, "(rolebounds %s %s)", key, pdb->p_role_val_to_name[role->bounds - 1]); } break; case ROLE_ATTRIB: if (scope == SCOPE_DECL) { cil_println(indent, "(roleattribute %s)", key); } if (!ebitmap_is_empty(&role->roles)) { cil_indent(indent); cil_printf("(roleattributeset %s (", key); ebitmap_for_each_positive_bit(&role->roles, node, i) { cil_printf("%s ", pdb->p_role_val_to_name[i]); } cil_printf("))\n"); } ts = &role->types; rc = process_typeset(pdb, ts, attr_list, &types, &num_types); if (rc != 0) { goto exit; } for (j = 0; j < num_types; j++) { if (is_id_in_scope(pdb, decl_stack, types[j], SYM_TYPES)) { cil_println(indent, "(roletype %s %s)", key, types[j]); } } break; default: ERR(NULL, "Unknown role type: %i", role->flavor); rc = -1; goto exit; } rc = cil_print_attr_list(indent, pdb, attr_list); if (rc != 0) { goto exit; } exit: attr_list_destroy(&attr_list); names_destroy(&types, &num_types); return rc; } static int type_to_cil(int indent, struct policydb *pdb, struct avrule_block *UNUSED(block), struct stack *decl_stack, char *key, void *datum, int scope) { int rc = -1; struct type_datum *type = datum; if (scope == SCOPE_REQ) { // if a type/typeattr is in the REQ scope, then it could cause an // optional block to fail, even if it is never used. However in CIL, // symbols must be used in order to cause an optional block to fail. So // for symbols in the REQ scope, add them to a typeattribute as a way // to 'use' them in the optional without affecting the resulting policy. cil_println(indent, "(typeattributeset " GEN_REQUIRE_ATTR " %s)", key); } rc = roletype_role_in_ancestor_to_cil(pdb, decl_stack, key, indent); if (rc != 0) { goto exit; } switch(type->flavor) { case TYPE_TYPE: if (scope == SCOPE_DECL) { cil_println(indent, "(type %s)", key); // object_r is implicit in checkmodule, but not with CIL, // create it as part of base cil_println(indent, "(roletype " DEFAULT_OBJECT " %s)", key); } if (type->flags & TYPE_FLAGS_PERMISSIVE) { cil_println(indent, "(typepermissive %s)", key); } if (type->bounds > 0) { cil_println(indent, "(typebounds %s %s)", pdb->p_type_val_to_name[type->bounds - 1], key); } break; case TYPE_ATTRIB: if (scope == SCOPE_DECL) { cil_println(indent, "(typeattribute %s)", key); } if (type->flags & TYPE_FLAGS_EXPAND_ATTR) { cil_indent(indent); cil_printf("(expandtypeattribute (%s) ", key); if (type->flags & TYPE_FLAGS_EXPAND_ATTR_TRUE) { cil_printf("true"); } else if (type->flags & TYPE_FLAGS_EXPAND_ATTR_FALSE) { cil_printf("false"); } cil_printf(")\n"); } if (!ebitmap_is_empty(&type->types)) { cil_indent(indent); cil_printf("(typeattributeset %s (", key); ebitmap_to_cil(pdb, &type->types, SYM_TYPES); cil_printf("))\n"); } break; case TYPE_ALIAS: break; default: ERR(NULL, "Unknown flavor (%i) of type %s", type->flavor, key); rc = -1; goto exit; } rc = 0; exit: return rc; } static int user_to_cil(int indent, struct policydb *pdb, struct avrule_block *block, struct stack *UNUSED(decl_stack), char *key, void *datum, int scope) { struct user_datum *user = datum; struct ebitmap roles = user->roles.roles; struct mls_semantic_level level = user->dfltlevel; struct mls_semantic_range range = user->range; struct ebitmap_node *node; uint32_t i; int sens_offset = 1; if (scope == SCOPE_DECL) { cil_println(indent, "(user %s)", key); // object_r is implicit in checkmodule, but not with CIL, create it // as part of base cil_println(indent, "(userrole %s " DEFAULT_OBJECT ")", key); } ebitmap_for_each_positive_bit(&roles, node, i) { cil_println(indent, "(userrole %s %s)", key, pdb->p_role_val_to_name[i]); } if (block->flags & AVRULE_OPTIONAL) { // sensitivities in user statements in optionals do not have the // standard -1 offset sens_offset = 0; } cil_indent(indent); cil_printf("(userlevel %s ", key); if (pdb->mls) { semantic_level_to_cil(pdb, sens_offset, &level); } else { cil_printf(DEFAULT_LEVEL); } cil_printf(")\n"); cil_indent(indent); cil_printf("(userrange %s (", key); if (pdb->mls) { semantic_level_to_cil(pdb, sens_offset, &range.level[0]); cil_printf(" "); semantic_level_to_cil(pdb, sens_offset, &range.level[1]); } else { cil_printf(DEFAULT_LEVEL " " DEFAULT_LEVEL); } cil_printf("))\n"); return 0; } static int boolean_to_cil(int indent, struct policydb *UNUSED(pdb), struct avrule_block *UNUSED(block), struct stack *UNUSED(decl_stack), char *key, void *datum, int scope) { struct cond_bool_datum *boolean = datum; const char *type; if (scope == SCOPE_DECL) { if (boolean->flags & COND_BOOL_FLAGS_TUNABLE) { type = "tunable"; } else { type = "boolean"; } cil_println(indent, "(%s %s %s)", type, key, boolean->state ? "true" : "false"); } return 0; } static int sens_to_cil(int indent, struct policydb *pdb, struct avrule_block *UNUSED(block), struct stack *UNUSED(decl_stack), char *key, void *datum, int scope) { level_datum_t *level = datum; if (scope == SCOPE_DECL) { if (!level->isalias) { cil_println(indent, "(sensitivity %s)", key); } else { cil_println(indent, "(sensitivityalias %s)", key); cil_println(indent, "(sensitivityaliasactual %s %s)", key, pdb->p_sens_val_to_name[level->level->sens - 1]); } } if (!ebitmap_is_empty(&level->level->cat)) { cil_indent(indent); cil_printf("(sensitivitycategory %s (", key); ebitmap_to_cil(pdb, &level->level->cat, SYM_CATS); cil_printf("))\n"); } return 0; } static int sens_order_to_cil(int indent, struct policydb *pdb, struct ebitmap order) { struct ebitmap_node *node; uint32_t i; if (ebitmap_is_empty(&order)) { return 0; } cil_indent(indent); cil_printf("(sensitivityorder ("); ebitmap_for_each_positive_bit(&order, node, i) { cil_printf("%s ", pdb->p_sens_val_to_name[i]); } cil_printf("))\n"); return 0; } static int cat_to_cil(int indent, struct policydb *pdb, struct avrule_block *UNUSED(block), struct stack *UNUSED(decl_stack), char *key, void *datum, int scope) { struct cat_datum *cat = datum; if (scope == SCOPE_REQ) { return 0; } if (!cat->isalias) { cil_println(indent, "(category %s)", key); } else { cil_println(indent, "(categoryalias %s)", key); cil_println(indent, "(categoryaliasactual %s %s)", key, pdb->p_cat_val_to_name[cat->s.value - 1]); } return 0; } static int cat_order_to_cil(int indent, struct policydb *pdb, struct ebitmap order) { int rc = -1; struct ebitmap_node *node; uint32_t i; if (ebitmap_is_empty(&order)) { rc = 0; goto exit; } cil_indent(indent); cil_printf("(categoryorder ("); ebitmap_for_each_positive_bit(&order, node, i) { cil_printf("%s ", pdb->p_cat_val_to_name[i]); } cil_printf("))\n"); return 0; exit: return rc; } static int polcaps_to_cil(struct policydb *pdb) { int rc = -1; struct ebitmap *map; struct ebitmap_node *node; uint32_t i; const char *name; map = &pdb->policycaps; ebitmap_for_each_positive_bit(map, node, i) { name = sepol_polcap_getname(i); if (name == NULL) { ERR(NULL, "Unknown policy capability id: %i", i); rc = -1; goto exit; } cil_println(0, "(policycap %s)", name); } return 0; exit: return rc; } static int level_to_cil(struct policydb *pdb, struct mls_level *level) { struct ebitmap *map = &level->cat; cil_printf("(%s", pdb->p_sens_val_to_name[level->sens - 1]); if (!ebitmap_is_empty(map)) { cil_printf("("); ebitmap_to_cil(pdb, map, SYM_CATS); cil_printf(")"); } cil_printf(")"); return 0; } static int context_to_cil(struct policydb *pdb, struct context_struct *con) { cil_printf("(%s %s %s (", pdb->p_user_val_to_name[con->user - 1], pdb->p_role_val_to_name[con->role - 1], pdb->p_type_val_to_name[con->type - 1]); if (pdb->mls) { level_to_cil(pdb, &con->range.level[0]); cil_printf(" "); level_to_cil(pdb, &con->range.level[1]); } else { cil_printf(DEFAULT_LEVEL); cil_printf(" "); cil_printf(DEFAULT_LEVEL); } cil_printf("))"); return 0; } static int ocontext_isid_to_cil(struct policydb *pdb, const char *const *sid_to_string, unsigned num_sids, struct ocontext *isids) { int rc = -1; struct ocontext *isid; struct sid_item { char *sid_key; struct sid_item *next; }; struct sid_item *head = NULL; struct sid_item *item = NULL; char *sid; char unknown[18]; unsigned i; for (isid = isids; isid != NULL; isid = isid->next) { i = isid->sid[0]; if (i < num_sids && sid_to_string[i]) { sid = (char*)sid_to_string[i]; } else { snprintf(unknown, 18, "%s%u", "UNKNOWN", i); sid = unknown; } cil_println(0, "(sid %s)", sid); cil_printf("(sidcontext %s ", sid); context_to_cil(pdb, &isid->context[0]); cil_printf(")\n"); // get the sid names in the correct order (reverse from the isids // ocontext) for sidorder statement item = malloc(sizeof(*item)); if (item == NULL) { ERR(NULL, "Out of memory"); rc = -1; goto exit; } item->sid_key = strdup(sid); if (!item->sid_key) { ERR(NULL, "Out of memory"); free(item); rc = -1; goto exit; } item->next = head; head = item; } if (head != NULL) { cil_printf("(sidorder ("); for (item = head; item != NULL; item = item->next) { cil_printf("%s ", item->sid_key); } cil_printf("))\n"); } rc = 0; exit: while(head) { item = head; head = item->next; free(item->sid_key); free(item); } return rc; } static int ocontext_selinux_isid_to_cil(struct policydb *pdb, struct ocontext *isids) { int rc = -1; rc = ocontext_isid_to_cil(pdb, selinux_sid_to_str, SELINUX_SID_SZ, isids); if (rc != 0) { goto exit; } return 0; exit: return rc; } static int ocontext_selinux_fs_to_cil(struct policydb *UNUSED(pdb), struct ocontext *fss) { if (fss != NULL) { ERR(NULL, "Warning: 'fscon' statement unsupported in CIL. Dropping from output."); } return 0; } static int ocontext_selinux_port_to_cil(struct policydb *pdb, struct ocontext *portcons) { int rc = -1; struct ocontext *portcon; const char *protocol; uint16_t high; uint16_t low; for (portcon = portcons; portcon != NULL; portcon = portcon->next) { switch (portcon->u.port.protocol) { case IPPROTO_TCP: protocol = "tcp"; break; case IPPROTO_UDP: protocol = "udp"; break; case IPPROTO_DCCP: protocol = "dccp"; break; case IPPROTO_SCTP: protocol = "sctp"; break; default: ERR(NULL, "Unknown portcon protocol: %i", portcon->u.port.protocol); rc = -1; goto exit; } low = portcon->u.port.low_port; high = portcon->u.port.high_port; if (low == high) { cil_printf("(portcon %s %i ", protocol, low); } else { cil_printf("(portcon %s (%i %i) ", protocol, low, high); } context_to_cil(pdb, &portcon->context[0]); cil_printf(")\n"); } return 0; exit: return rc; } static int ocontext_selinux_ibpkey_to_cil(struct policydb *pdb, struct ocontext *ibpkeycons) { int rc = -1; struct ocontext *ibpkeycon; char subnet_prefix_str[INET6_ADDRSTRLEN]; struct in6_addr subnet_prefix = IN6ADDR_ANY_INIT; uint16_t high; uint16_t low; for (ibpkeycon = ibpkeycons; ibpkeycon; ibpkeycon = ibpkeycon->next) { low = ibpkeycon->u.ibpkey.low_pkey; high = ibpkeycon->u.ibpkey.high_pkey; memcpy(&subnet_prefix.s6_addr, &ibpkeycon->u.ibpkey.subnet_prefix, sizeof(ibpkeycon->u.ibpkey.subnet_prefix)); if (inet_ntop(AF_INET6, &subnet_prefix.s6_addr, subnet_prefix_str, INET6_ADDRSTRLEN) == NULL) { ERR(NULL, "ibpkeycon subnet_prefix is invalid: %m"); rc = -1; goto exit; } if (low == high) cil_printf("(ibpkeycon %s %i ", subnet_prefix_str, low); else cil_printf("(ibpkeycon %s (%i %i) ", subnet_prefix_str, low, high); context_to_cil(pdb, &ibpkeycon->context[0]); cil_printf(")\n"); } return 0; exit: return rc; } static int ocontext_selinux_netif_to_cil(struct policydb *pdb, struct ocontext *netifs) { struct ocontext *netif; for (netif = netifs; netif != NULL; netif = netif->next) { cil_printf("(netifcon %s ", netif->u.name); context_to_cil(pdb, &netif->context[0]); cil_printf(" "); context_to_cil(pdb, &netif->context[1]); cil_printf(")\n"); } return 0; } static int ocontext_selinux_node_to_cil(struct policydb *pdb, struct ocontext *nodes) { int rc = -1; struct ocontext *node; char addr[INET_ADDRSTRLEN]; char mask[INET_ADDRSTRLEN]; for (node = nodes; node != NULL; node = node->next) { if (inet_ntop(AF_INET, &node->u.node.addr, addr, INET_ADDRSTRLEN) == NULL) { ERR(NULL, "Nodecon address is invalid: %m"); rc = -1; goto exit; } if (inet_ntop(AF_INET, &node->u.node.mask, mask, INET_ADDRSTRLEN) == NULL) { ERR(NULL, "Nodecon mask is invalid: %m"); rc = -1; goto exit; } cil_printf("(nodecon (%s) (%s) ", addr, mask); context_to_cil(pdb, &node->context[0]); cil_printf(")\n"); } return 0; exit: return rc; } static int ocontext_selinux_node6_to_cil(struct policydb *pdb, struct ocontext *nodes) { int rc = -1; struct ocontext *node; char addr[INET6_ADDRSTRLEN]; char mask[INET6_ADDRSTRLEN]; for (node = nodes; node != NULL; node = node->next) { if (inet_ntop(AF_INET6, &node->u.node6.addr, addr, INET6_ADDRSTRLEN) == NULL) { ERR(NULL, "Nodecon address is invalid: %m"); rc = -1; goto exit; } if (inet_ntop(AF_INET6, &node->u.node6.mask, mask, INET6_ADDRSTRLEN) == NULL) { ERR(NULL, "Nodecon mask is invalid: %m"); rc = -1; goto exit; } cil_printf("(nodecon (%s) (%s) ", addr, mask); context_to_cil(pdb, &node->context[0]); cil_printf(")\n"); } return 0; exit: return rc; } static int ocontext_selinux_ibendport_to_cil(struct policydb *pdb, struct ocontext *ibendports) { struct ocontext *ibendport; for (ibendport = ibendports; ibendport; ibendport = ibendport->next) { cil_printf("(ibendportcon %s %u ", ibendport->u.ibendport.dev_name, ibendport->u.ibendport.port); context_to_cil(pdb, &ibendport->context[0]); cil_printf(")\n"); } return 0; } static int ocontext_selinux_fsuse_to_cil(struct policydb *pdb, struct ocontext *fsuses) { int rc = -1; struct ocontext *fsuse; const char *behavior; for (fsuse = fsuses; fsuse != NULL; fsuse = fsuse->next) { switch (fsuse->v.behavior) { case SECURITY_FS_USE_XATTR: behavior = "xattr"; break; case SECURITY_FS_USE_TRANS: behavior = "trans"; break; case SECURITY_FS_USE_TASK: behavior = "task"; break; default: ERR(NULL, "Unknown fsuse behavior: %i", fsuse->v.behavior); rc = -1; goto exit; } cil_printf("(fsuse %s %s ", behavior, fsuse->u.name); context_to_cil(pdb, &fsuse->context[0]); cil_printf(")\n"); } return 0; exit: return rc; } static int ocontext_xen_isid_to_cil(struct policydb *pdb, struct ocontext *isids) { int rc = -1; rc = ocontext_isid_to_cil(pdb, xen_sid_to_str, XEN_SID_SZ, isids); if (rc != 0) { goto exit; } return 0; exit: return rc; } static int ocontext_xen_pirq_to_cil(struct policydb *pdb, struct ocontext *pirqs) { struct ocontext *pirq; for (pirq = pirqs; pirq != NULL; pirq = pirq->next) { cil_printf("(pirqcon %i ", pirq->u.pirq); context_to_cil(pdb, &pirq->context[0]); cil_printf(")\n"); } return 0; } static int ocontext_xen_ioport_to_cil(struct policydb *pdb, struct ocontext *ioports) { struct ocontext *ioport; uint32_t low; uint32_t high; for (ioport = ioports; ioport != NULL; ioport = ioport->next) { low = ioport->u.ioport.low_ioport; high = ioport->u.ioport.high_ioport; if (low == high) { cil_printf("(ioportcon 0x%x ", low); } else { cil_printf("(ioportcon (0x%x 0x%x) ", low, high); } context_to_cil(pdb, &ioport->context[0]); cil_printf(")\n"); } return 0; } static int ocontext_xen_iomem_to_cil(struct policydb *pdb, struct ocontext *iomems) { struct ocontext *iomem; uint64_t low; uint64_t high; for (iomem = iomems; iomem != NULL; iomem = iomem->next) { low = iomem->u.iomem.low_iomem; high = iomem->u.iomem.high_iomem; if (low == high) { cil_printf("(iomemcon 0x%"PRIx64" ", low); } else { cil_printf("(iomemcon (0x%"PRIx64" 0x%"PRIx64") ", low, high); } context_to_cil(pdb, &iomem->context[0]); cil_printf(")\n"); } return 0; } static int ocontext_xen_pcidevice_to_cil(struct policydb *pdb, struct ocontext *pcids) { struct ocontext *pcid; for (pcid = pcids; pcid != NULL; pcid = pcid->next) { cil_printf("(pcidevicecon 0x%lx ", (unsigned long)pcid->u.device); context_to_cil(pdb, &pcid->context[0]); cil_printf(")\n"); } return 0; } static int ocontexts_to_cil(struct policydb *pdb) { int rc = -1; int ocon; static int (*const *ocon_funcs)(struct policydb *pdb, struct ocontext *ocon); static int (*const ocon_selinux_funcs[OCON_NUM])(struct policydb *pdb, struct ocontext *ocon) = { ocontext_selinux_isid_to_cil, ocontext_selinux_fs_to_cil, ocontext_selinux_port_to_cil, ocontext_selinux_netif_to_cil, ocontext_selinux_node_to_cil, ocontext_selinux_fsuse_to_cil, ocontext_selinux_node6_to_cil, ocontext_selinux_ibpkey_to_cil, ocontext_selinux_ibendport_to_cil, }; static int (*const ocon_xen_funcs[OCON_NUM])(struct policydb *pdb, struct ocontext *ocon) = { ocontext_xen_isid_to_cil, ocontext_xen_pirq_to_cil, ocontext_xen_ioport_to_cil, ocontext_xen_iomem_to_cil, ocontext_xen_pcidevice_to_cil, NULL, NULL, }; switch (pdb->target_platform) { case SEPOL_TARGET_SELINUX: ocon_funcs = ocon_selinux_funcs; break; case SEPOL_TARGET_XEN: ocon_funcs = ocon_xen_funcs; break; default: ERR(NULL, "Unknown target platform: %i", pdb->target_platform); rc = -1; goto exit; } for (ocon = 0; ocon < OCON_NUM; ocon++) { if (ocon_funcs[ocon] != NULL) { rc = ocon_funcs[ocon](pdb, pdb->ocontexts[ocon]); if (rc != 0) { goto exit; } } } return 0; exit: return rc; } static int genfscon_to_cil(struct policydb *pdb) { struct genfs *genfs; struct ocontext *ocon; uint32_t sclass; for (genfs = pdb->genfs; genfs != NULL; genfs = genfs->next) { for (ocon = genfs->head; ocon != NULL; ocon = ocon->next) { sclass = ocon->v.sclass; if (sclass) { const char *file_type; const char *class_name = pdb->p_class_val_to_name[sclass-1]; if (strcmp(class_name, "file") == 0) { file_type = "file"; } else if (strcmp(class_name, "dir") == 0) { file_type = "dir"; } else if (strcmp(class_name, "chr_file") == 0) { file_type = "char"; } else if (strcmp(class_name, "blk_file") == 0) { file_type = "block"; } else if (strcmp(class_name, "sock_file") == 0) { file_type = "socket"; } else if (strcmp(class_name, "fifo_file") == 0) { file_type = "pipe"; } else if (strcmp(class_name, "lnk_file") == 0) { file_type = "symlink"; } else { return -1; } cil_printf("(genfscon %s \"%s\" %s ", genfs->fstype, ocon->u.name, file_type); } else { cil_printf("(genfscon %s \"%s\" ", genfs->fstype, ocon->u.name); } context_to_cil(pdb, &ocon->context[0]); cil_printf(")\n"); } } return 0; } static int level_string_to_cil(char *levelstr) { int rc = -1; char *sens = NULL; char *cats = NULL; int matched; char *saveptr = NULL; char *token = NULL; char *ranged = NULL; matched = tokenize(levelstr, ':', 2, &sens, &cats); if (matched < 1 || matched > 2) { ERR(NULL, "Invalid level: %s", levelstr); rc = -1; goto exit; } cil_printf("(%s", sens); if (matched == 2) { cil_printf("("); token = strtok_r(cats, ",", &saveptr); while (token != NULL) { ranged = strchr(token, '.'); if (ranged == NULL) { cil_printf("%s ", token); } else { *ranged = '\0'; cil_printf("(range %s %s) ", token, ranged + 1); } token = strtok_r(NULL, ",", &saveptr); } cil_printf(")"); } cil_printf(")"); rc = 0; exit: free(sens); free(cats); return rc; } static int level_range_string_to_cil(char *levelrangestr) { char *ranged = NULL; char *low; char *high; ranged = strchr(levelrangestr, '-'); if (ranged == NULL) { low = high = levelrangestr; } else { *ranged = '\0'; low = levelrangestr; high = ranged + 1; } level_string_to_cil(low); cil_printf(" "); level_string_to_cil(high); return 0; } static int context_string_to_cil(char *contextstr) { int rc = -1; int matched; char *user = NULL; char *role = NULL; char *type = NULL; char *level = NULL; matched = tokenize(contextstr, ':', 4, &user, &role, &type, &level); if (matched < 3 || matched > 4) { ERR(NULL, "Invalid context: %s", contextstr); rc = -1; goto exit; } cil_printf("(%s %s %s (", user, role, type); if (matched == 3) { cil_printf(DEFAULT_LEVEL); cil_printf(" "); cil_printf(DEFAULT_LEVEL); } else { level_range_string_to_cil(level); } cil_printf("))"); rc = 0; exit: free(user); free(role); free(type); free(level); return rc; } static int seusers_to_cil(struct sepol_module_package *mod_pkg) { int rc = -1; char *seusers = sepol_module_package_get_seusers(mod_pkg); size_t seusers_len = sepol_module_package_get_seusers_len(mod_pkg); char *cur = seusers; char *end = seusers + seusers_len; char *line = NULL; char *user = NULL; char *seuser = NULL; char *level = NULL; char *tmp = NULL; int matched; if (seusers_len == 0) { return 0; } while ((rc = get_line(&cur, end, &line)) > 0) { tmp = line; while (isspace(*tmp)) { tmp++; } if (tmp[0] == '#' || tmp[0] == '\0') { free(line); line = NULL; continue; } matched = tokenize(tmp, ':', 3, &user, &seuser, &level); if (matched < 2 || matched > 3) { ERR(NULL, "Invalid seuser line: %s", line); rc = -1; goto exit; } if (!strcmp(user, "__default__")) { cil_printf("(selinuxuserdefault %s (", seuser); } else { cil_printf("(selinuxuser %s %s (", user, seuser); } switch (matched) { case 2: cil_printf("systemlow systemlow"); break; case 3: level_range_string_to_cil(level); break; } cil_printf("))\n"); free(user); free(seuser); free(level); free(line); user = seuser = level = NULL; } if (rc == -1) { cil_printf("Failed to read seusers\n"); goto exit; } rc = 0; exit: free(line); free(user); free(seuser); free(level); return rc; } static int netfilter_contexts_to_cil(struct sepol_module_package *mod_pkg) { size_t netcons_len = sepol_module_package_get_netfilter_contexts_len(mod_pkg); if (netcons_len > 0) { ERR(NULL, "Warning: netfilter_contexts are unsupported in CIL. Dropping from output."); } return 0; } static int user_extra_to_cil(struct sepol_module_package *mod_pkg) { int rc = -1; char *userx = sepol_module_package_get_user_extra(mod_pkg); size_t userx_len = sepol_module_package_get_user_extra_len(mod_pkg); char *cur = userx; char *end = userx + userx_len; char *line; int matched; char *user = NULL; char *prefix = NULL; int prefix_len = 0; char *user_str = NULL; char *prefix_str = NULL; char *eol = NULL; char *tmp = NULL; if (userx_len == 0) { return 0; } while ((rc = get_line(&cur, end, &line)) > 0) { tmp = line; while (isspace(*tmp)) { tmp++; } if (tmp[0] == '#' || tmp[0] == '\0') { free(line); line = NULL; continue; } matched = tokenize(tmp, ' ', 4, &user_str, &user, &prefix_str, &prefix); if (matched != 4) { rc = -1; ERR(NULL, "Invalid user extra line: %s", line); goto exit; } prefix_len = strlen(prefix); eol = prefix + prefix_len - 1; if (*eol != ';' || strcmp(user_str, "user") || strcmp(prefix_str, "prefix")) { rc = -1; ERR(NULL, "Invalid user extra line: %s", line); goto exit; } *eol = '\0'; cil_println(0, "(userprefix %s %s)", user, prefix); free(user); free(prefix); free(line); free(user_str); free(prefix_str); user = prefix = line = user_str = prefix_str = NULL; } if (rc == -1) { cil_printf("Failed to read user_extra\n"); goto exit; } rc = 0; exit: free(line); free(user); free(prefix); return rc; } static int file_contexts_to_cil(struct sepol_module_package *mod_pkg) { int rc = -1; char *fc = sepol_module_package_get_file_contexts(mod_pkg); size_t fc_len = sepol_module_package_get_file_contexts_len(mod_pkg); char *cur = fc; char *end = fc + fc_len; char *line = NULL; int matched; char *regex = NULL; char *mode = NULL; char *context = NULL; const char *cilmode; char *tmp = NULL; if (fc_len == 0) { return 0; } while ((rc = get_line(&cur, end, &line)) > 0) { tmp = line; while (isspace(*tmp)) { tmp++; } if (tmp[0] == '#' || tmp[0] == '\0') { free(line); line = NULL; continue; } matched = tokenize(tmp, ' ', 3, ®ex, &mode, &context); if (matched < 2 || matched > 3) { rc = -1; ERR(NULL, "Invalid file context line: %s", line); goto exit; } if (matched == 2) { context = mode; mode = NULL; } if (mode == NULL) { cilmode = "any"; } else if (!strcmp(mode, "--")) { cilmode = "file"; } else if (!strcmp(mode, "-d")) { cilmode = "dir"; } else if (!strcmp(mode, "-c")) { cilmode = "char"; } else if (!strcmp(mode, "-b")) { cilmode = "block"; } else if (!strcmp(mode, "-s")) { cilmode = "socket"; } else if (!strcmp(mode, "-p")) { cilmode = "pipe"; } else if (!strcmp(mode, "-l")) { cilmode = "symlink"; } else { rc = -1; ERR(NULL, "Invalid mode in file context line: %s", line); goto exit; } cil_printf("(filecon \"%s\" %s ", regex, cilmode); if (!strcmp(context, "<>")) { cil_printf("()"); } else { context_string_to_cil(context); } cil_printf(")\n"); free(regex); free(mode); free(context); free(line); regex = mode = context = line = NULL; } if (rc == -1) { cil_printf("Failed to read file_contexts_to_cil\n"); goto exit; } rc = 0; exit: free(line); free(regex); free(mode); free(context); return rc; } static int (*const func_to_cil[SYM_NUM])(int indent, struct policydb *pdb, struct avrule_block *block, struct stack *decl_stack, char *key, void *datum, int scope) = { NULL, // commons, only stored in the global symtab, handled elsewhere class_to_cil, role_to_cil, type_to_cil, user_to_cil, boolean_to_cil, sens_to_cil, cat_to_cil }; static int typealiases_to_cil(int indent, struct policydb *pdb, struct avrule_block *UNUSED(block), struct stack *decl_stack) { struct type_datum *alias_datum; char *alias_name; char *type_name; struct list_node *curr; struct avrule_decl *decl = stack_peek(decl_stack); struct list *alias_list; int rc = -1; if (decl == NULL) { return -1; } alias_list = typealias_lists[decl->decl_id]; if (alias_list == NULL) { return 0; } for (curr = alias_list->head; curr != NULL; curr = curr->next) { alias_name = curr->data; alias_datum = hashtab_search(pdb->p_types.table, alias_name); if (alias_datum == NULL) { rc = -1; goto exit; } if (alias_datum->flavor == TYPE_ALIAS) { type_name = pdb->p_type_val_to_name[alias_datum->primary - 1]; } else { type_name = pdb->p_type_val_to_name[alias_datum->s.value - 1]; } cil_println(indent, "(typealias %s)", alias_name); cil_println(indent, "(typealiasactual %s %s)", alias_name, type_name); } return 0; exit: return rc; } static int declared_scopes_to_cil(int indent, struct policydb *pdb, struct avrule_block *block, struct stack *decl_stack) { int rc = -1; struct ebitmap map; struct ebitmap_node *node; unsigned int i; char * key; struct scope_datum *scope; int sym; void *datum; struct avrule_decl *decl = stack_peek(decl_stack); for (sym = 0; sym < SYM_NUM; sym++) { if (func_to_cil[sym] == NULL) { continue; } map = decl->declared.scope[sym]; ebitmap_for_each_positive_bit(&map, node, i) { key = pdb->sym_val_to_name[sym][i]; datum = hashtab_search(pdb->symtab[sym].table, key); if (datum == NULL) { rc = -1; goto exit; } scope = hashtab_search(pdb->scope[sym].table, key); if (scope == NULL) { rc = -1; goto exit; } rc = func_to_cil[sym](indent, pdb, block, decl_stack, key, datum, scope->scope); if (rc != 0) { goto exit; } } if (sym == SYM_CATS) { rc = cat_order_to_cil(indent, pdb, map); if (rc != 0) { goto exit; } } if (sym == SYM_LEVELS) { rc = sens_order_to_cil(indent, pdb, map); if (rc != 0) { goto exit; } } if (sym == SYM_CLASSES) { rc = class_order_to_cil(indent, pdb, map); if (rc != 0) { goto exit; } } } return 0; exit: return rc; } static int required_scopes_to_cil(int indent, struct policydb *pdb, struct avrule_block *block, struct stack *decl_stack) { int rc = -1; struct ebitmap map; struct ebitmap_node *node; unsigned int i; unsigned int j; char * key; int sym; void *datum; struct avrule_decl *decl = stack_peek(decl_stack); struct scope_datum *scope_datum; for (sym = 0; sym < SYM_NUM; sym++) { if (func_to_cil[sym] == NULL) { continue; } map = decl->required.scope[sym]; ebitmap_for_each_positive_bit(&map, node, i) { key = pdb->sym_val_to_name[sym][i]; scope_datum = hashtab_search(pdb->scope[sym].table, key); if (scope_datum == NULL) { rc = -1; goto exit; } for (j = 0; j < scope_datum->decl_ids_len; j++) { if (scope_datum->decl_ids[j] == decl->decl_id) { break; } } if (j >= scope_datum->decl_ids_len) { // Symbols required in the global scope are also in the // required scope ebitmap of all avrule decls (i.e. required // in all optionals). So we need to look at the scopes of each // symbol in this avrule_decl to determine if it actually is // required in this decl, or if it's just required in the // global scope. If we got here, then this symbol is not // actually required in this scope, so skip it. continue; } datum = hashtab_search(pdb->symtab[sym].table, key); if (datum == NULL) { rc = -1; goto exit; } rc = func_to_cil[sym](indent, pdb, block, decl_stack, key, datum, SCOPE_REQ); if (rc != 0) { goto exit; } } } return 0; exit: return rc; } static int additive_scopes_to_cil_map(char *key, void *data, void *arg) { int rc = -1; struct map_args *args = arg; rc = func_to_cil[args->sym_index](args->indent, args->pdb, args->block, args->decl_stack, key, data, SCOPE_REQ); if (rc != 0) { goto exit; } return 0; exit: return rc; } static int additive_scopes_to_cil(int indent, struct policydb *pdb, struct avrule_block *block, struct stack *decl_stack) { int rc = -1; struct avrule_decl *decl = stack_peek(decl_stack); struct map_args args; args.pdb = pdb; args.block = block; args.decl_stack = decl_stack; args.indent = indent; for (args.sym_index = 0; args.sym_index < SYM_NUM; args.sym_index++) { if (func_to_cil[args.sym_index] == NULL) { continue; } rc = hashtab_map(decl->symtab[args.sym_index].table, additive_scopes_to_cil_map, &args); if (rc != 0) { goto exit; } } return 0; exit: return rc; } static int is_scope_superset(struct scope_index *sup, struct scope_index *sub) { // returns 1 if sup is a superset of sub, returns 0 otherwise int rc = 0; uint32_t i; struct ebitmap sup_map; struct ebitmap sub_map; struct ebitmap res; ebitmap_init(&res); for (i = 0; i < SYM_NUM; i++) { sup_map = sup->scope[i]; sub_map = sub->scope[i]; ebitmap_and(&res, &sup_map, &sub_map); if (!ebitmap_cmp(&res, &sub_map)) { goto exit; } ebitmap_destroy(&res); } if (sup->class_perms_len < sub->class_perms_len) { goto exit; } for (i = 0; i < sub->class_perms_len; i++) { sup_map = sup->class_perms_map[i]; sub_map = sub->class_perms_map[i]; ebitmap_and(&res, &sup_map, &sub_map); if (!ebitmap_cmp(&res, &sub_map)) { goto exit; } ebitmap_destroy(&res); } rc = 1; exit: ebitmap_destroy(&res); return rc; } static int block_to_cil(struct policydb *pdb, struct avrule_block *block, struct stack *stack, int indent) { int rc = -1; struct avrule_decl *decl; struct list *type_attr_list = NULL; struct list *role_attr_list = NULL; decl = block->branch_list; rc = list_init(&type_attr_list); if (rc != 0) { goto exit; } rc = list_init(&role_attr_list); if (rc != 0) { goto exit; } rc = typealiases_to_cil(indent, pdb, block, stack); if (rc != 0) { goto exit; } rc = declared_scopes_to_cil(indent, pdb, block, stack); if (rc != 0) { goto exit; } rc = required_scopes_to_cil(indent, pdb, block, stack); if (rc != 0) { goto exit; } rc = additive_scopes_to_cil(indent, pdb, block, stack); if (rc != 0) { goto exit; } rc = avrule_list_to_cil(indent, pdb, decl->avrules, type_attr_list); if (rc != 0) { goto exit; } rc = role_trans_to_cil(indent, pdb, decl->role_tr_rules, role_attr_list, type_attr_list); if (rc != 0) { goto exit; } rc = role_allows_to_cil(indent, pdb, decl->role_allow_rules, role_attr_list); if (rc != 0) { goto exit; } rc = range_trans_to_cil(indent, pdb, decl->range_tr_rules, type_attr_list); if (rc != 0) { goto exit; } rc = filename_trans_to_cil(indent, pdb, decl->filename_trans_rules, type_attr_list); if (rc != 0) { goto exit; } rc = cond_list_to_cil(indent, pdb, decl->cond_list, type_attr_list); if (rc != 0) { goto exit; } rc = cil_print_attr_list(indent, pdb, type_attr_list); if (rc != 0) { goto exit; } rc = cil_print_attr_list(indent, pdb, role_attr_list); if (rc != 0) { goto exit; } exit: attr_list_destroy(&type_attr_list); attr_list_destroy(&role_attr_list); return rc; } static int module_block_to_cil(struct policydb *pdb, struct avrule_block *block, struct stack *stack, int *indent) { int rc = 0; struct avrule_decl *decl; struct avrule_decl *decl_tmp; decl = block->branch_list; if (decl == NULL) { goto exit; } if (decl->next != NULL) { ERR(NULL, "Warning: 'else' blocks in optional statements are unsupported in CIL. Dropping from output."); } if (block->flags & AVRULE_OPTIONAL) { while (stack->pos > 0) { decl_tmp = stack_peek(stack); if (is_scope_superset(&decl->required, &decl_tmp->required)) { break; } stack_pop(stack); (*indent)--; cil_println(*indent, ")"); } cil_println(*indent, "(optional %s_optional_%i", pdb->name, decl->decl_id); (*indent)++; } stack_push(stack, decl); rc = block_to_cil(pdb, block, stack, *indent); if (rc != 0) { goto exit; } exit: return rc; } static int global_block_to_cil(struct policydb *pdb, struct avrule_block *block, struct stack *stack) { int rc = 0; struct avrule_decl *decl; decl = block->branch_list; if (decl == NULL) { goto exit; } if (decl->next != NULL) { ERR(NULL, "Warning: 'else' not allowed in global block. Dropping from output."); } stack_push(stack, decl); // type aliases and commons are only stored in the global symtab. // However, to get scoping correct, we assume they are in the // global block rc = hashtab_map(pdb->p_commons.table, common_to_cil, NULL); if (rc != 0) { goto exit; } rc = block_to_cil(pdb, block, stack, 0); if (rc != 0) { goto exit; } exit: return rc; } static int blocks_to_cil(struct policydb *pdb) { int rc = -1; struct avrule_block *block; int indent = 0; struct stack *stack = NULL; rc = stack_init(&stack); if (rc != 0) { goto exit; } block = pdb->global; rc = global_block_to_cil(pdb, block, stack); if (rc != 0) { goto exit; } for (block = block->next; block != NULL; block = block->next) { rc = module_block_to_cil(pdb, block, stack, &indent); if (rc != 0) { goto exit; } } while (indent > 0) { indent--; cil_println(indent, ")"); } exit: stack_destroy(&stack); return rc; } static int linked_block_to_cil(struct policydb *pdb, struct avrule_block *block, struct stack *stack) { int rc = 0; struct avrule_decl *decl; decl = block->branch_list; if (decl == NULL) { goto exit; } if (!decl->enabled) { if (decl->next != NULL) { decl = decl->next; } else { goto exit; } } stack_push(stack, decl); rc = block_to_cil(pdb, block, stack, 0); if (rc != 0) { goto exit; } stack_pop(stack); exit: return rc; } static int linked_blocks_to_cil(struct policydb *pdb) { // Convert base module that has been linked to CIL // Since it is linked, all optional blocks have been resolved int rc = -1; struct avrule_block *block; struct stack *stack = NULL; rc = stack_init(&stack); if (rc != 0) { goto exit; } block = pdb->global; rc = global_block_to_cil(pdb, block, stack); if (rc != 0) { goto exit; } for (block = block->next; block != NULL; block = block->next) { rc = linked_block_to_cil(pdb, block, stack); if (rc != 0) { goto exit; } } exit: stack_destroy(&stack); return rc; } static int handle_unknown_to_cil(struct policydb *pdb) { int rc = -1; const char *hu; switch (pdb->handle_unknown) { case SEPOL_DENY_UNKNOWN: hu = "deny"; break; case SEPOL_REJECT_UNKNOWN: hu = "reject"; break; case SEPOL_ALLOW_UNKNOWN: hu = "allow"; break; default: ERR(NULL, "Unknown value for handle-unknown: %i", pdb->handle_unknown); rc = -1; goto exit; } cil_println(0, "(handleunknown %s)", hu); return 0; exit: return rc; } static int generate_mls(struct policydb *pdb) { const char *mls_str = pdb->mls ? "true" : "false"; cil_println(0, "(mls %s)", mls_str); return 0; } static int generate_default_level(void) { cil_println(0, "(sensitivity s0)"); cil_println(0, "(sensitivityorder (s0))"); cil_println(0, "(level " DEFAULT_LEVEL " (s0))"); return 0; } static int generate_default_object(void) { cil_println(0, "(role " DEFAULT_OBJECT ")"); return 0; } static int generate_gen_require_attribute(void) { cil_println(0, "(typeattribute " GEN_REQUIRE_ATTR ")"); cil_println(0, "(roleattribute " GEN_REQUIRE_ATTR ")"); return 0; } static int fix_module_name(struct policydb *pdb) { char *letter; int rc = -1; // The base module doesn't have its name set, but we use that for some // autogenerated names, like optionals and attributes, to prevent naming // collisions. However, they sometimes need to be fixed up. // the base module isn't given a name, so just call it "base" if (pdb->policy_type == POLICY_BASE) { pdb->name = strdup("base"); if (pdb->name == NULL) { ERR(NULL, "Out of memory"); rc = -1; goto exit; } } // CIL is more restrictive in module names than checkmodule. Convert bad // characters to underscores for (letter = pdb->name; *letter != '\0'; letter++) { if (isalnum(*letter)) { continue; } *letter = '_'; } return 0; exit: return rc; } int sepol_module_policydb_to_cil(FILE *fp, struct policydb *pdb, int linked) { int rc = -1; out_file = fp; if (pdb == NULL) { rc = 0; goto exit; } if (pdb->policy_type != SEPOL_POLICY_BASE && pdb->policy_type != SEPOL_POLICY_MOD) { ERR(NULL, "Policy package is not a base or module"); rc = -1; goto exit; } rc = fix_module_name(pdb); if (rc != 0) { goto exit; } if (pdb->policy_type == SEPOL_POLICY_BASE && !pdb->mls) { // If this is a base non-mls policy, we need to define a default level // range that can be used for contexts by other non-mls modules, since // CIL requires that all contexts have a range, even if they are // ignored as in non-mls policies rc = generate_default_level(); if (rc != 0) { goto exit; } } if (pdb->policy_type == SEPOL_POLICY_BASE) { // object_r is implicit in checkmodule, but not with CIL, create it // as part of base rc = generate_default_object(); if (rc != 0) { goto exit; } // default attribute to be used to mimic gen_require in CIL rc = generate_gen_require_attribute(); if (rc != 0) { goto exit; } // handle_unknown is used from only the base module rc = handle_unknown_to_cil(pdb); if (rc != 0) { goto exit; } // mls is used from only the base module rc = generate_mls(pdb); if (rc != 0) { goto exit; } } rc = role_list_create(pdb->p_roles.table); if (rc != 0) { goto exit; } rc = typealias_list_create(pdb); if (rc != 0) { goto exit; } rc = polcaps_to_cil(pdb); if (rc != 0) { goto exit; } rc = ocontexts_to_cil(pdb); if (rc != 0) { goto exit; } rc = genfscon_to_cil(pdb); if (rc != 0) { goto exit; } // now print everything that is scoped if (linked) { rc = linked_blocks_to_cil(pdb); } else { rc = blocks_to_cil(pdb); } if (rc != 0) { goto exit; } rc = 0; exit: role_list_destroy(); typealias_list_destroy(); return rc; } int sepol_module_package_to_cil(FILE *fp, struct sepol_module_package *mod_pkg) { int rc = -1; struct sepol_policydb *pdb; out_file = fp; pdb = sepol_module_package_get_policy(mod_pkg); if (pdb == NULL) { ERR(NULL, "Failed to get policydb"); rc = -1; goto exit; } rc = sepol_module_policydb_to_cil(fp, &pdb->p, 0); if (rc != 0) { goto exit; } rc = seusers_to_cil(mod_pkg); if (rc != 0) { goto exit; } rc = netfilter_contexts_to_cil(mod_pkg); if (rc != 0) { goto exit; } rc = user_extra_to_cil(mod_pkg); if (rc != 0) { goto exit; } rc = file_contexts_to_cil(mod_pkg); if (rc != 0) { goto exit; } rc = 0; exit: return rc; } static int fp_to_buffer(FILE *fp, char **data, size_t *data_len) { int rc = -1; char *d = NULL, *d_tmp; size_t d_len = 0; size_t read_len = 0; size_t max_len = 1 << 17; // start at 128KB, this is enough to hold about half of all the existing pp files d = malloc(max_len); if (d == NULL) { ERR(NULL, "Out of memory"); rc = -1; goto exit; } while ((read_len = fread(d + d_len, 1, max_len - d_len, fp)) > 0) { d_len += read_len; if (d_len == max_len) { max_len *= 2; d_tmp = realloc(d, max_len); if (d_tmp == NULL) { ERR(NULL, "Out of memory"); rc = -1; goto exit; } d = d_tmp; } } if (ferror(fp) != 0) { ERR(NULL, "Failed to read pp file"); rc = -1; goto exit; } *data = d; *data_len = d_len; return 0; exit: free(d); return rc; } int sepol_ppfile_to_module_package(FILE *fp, struct sepol_module_package **mod_pkg) { int rc = -1; struct sepol_policy_file *pf = NULL; struct sepol_module_package *pkg = NULL; char *data = NULL; size_t data_len; int fd; struct stat sb; rc = sepol_policy_file_create(&pf); if (rc != 0) { ERR(NULL, "Failed to create policy file"); goto exit; } fd = fileno(fp); if (fstat(fd, &sb) == -1) { rc = -1; goto exit; } if (S_ISFIFO(sb.st_mode) || S_ISSOCK(sb.st_mode)) { // libsepol fails when trying to read a policy package from a pipe or a // socket due its use of lseek. In this case, read the data into a // buffer and provide that to libsepol rc = fp_to_buffer(fp, &data, &data_len); if (rc != 0) { goto exit; } sepol_policy_file_set_mem(pf, data, data_len); } else { sepol_policy_file_set_fp(pf, fp); } rc = sepol_module_package_create(&pkg); if (rc != 0) { ERR(NULL, "Failed to create module package"); goto exit; } rc = sepol_module_package_read(pkg, pf, 0); if (rc != 0) { ERR(NULL, "Failed to read policy package"); goto exit; } *mod_pkg = pkg; exit: free(data); sepol_policy_file_free(pf); if (rc != 0) { sepol_module_package_free(pkg); } return rc; } libsepol-3.8.1/src/node_internal.h000066400000000000000000000002011476211737200171200ustar00rootroot00000000000000#ifndef _SEPOL_NODE_INTERNAL_H_ #define _SEPOL_NODE_INTERNAL_H_ #include #include #endif libsepol-3.8.1/src/node_record.c000066400000000000000000000307541476211737200165750ustar00rootroot00000000000000#include #include #include #include #include #include #include "node_internal.h" #include "context_internal.h" #include "debug.h" struct sepol_node { /* Network address and mask */ char *addr; size_t addr_sz; char *mask; size_t mask_sz; /* Protocol */ int proto; /* Context */ sepol_context_t *con; }; struct sepol_node_key { /* Network address and mask */ char *addr; size_t addr_sz; char *mask; size_t mask_sz; /* Protocol */ int proto; }; /* Converts a string represtation (addr_str) * to a numeric representation (addr_bytes) */ static int node_parse_addr(sepol_handle_t * handle, const char *addr_str, int proto, char *addr_bytes) { switch (proto) { case SEPOL_PROTO_IP4: { struct in_addr in_addr; if (inet_pton(AF_INET, addr_str, &in_addr) <= 0) { ERR(handle, "could not parse IPv4 address " "%s: %m", addr_str); return STATUS_ERR; } memcpy(addr_bytes, &in_addr.s_addr, 4); break; } case SEPOL_PROTO_IP6: { struct in6_addr in_addr; if (inet_pton(AF_INET6, addr_str, &in_addr) <= 0) { ERR(handle, "could not parse IPv6 address " "%s: %m", addr_str); return STATUS_ERR; } memcpy(addr_bytes, in_addr.s6_addr, 16); break; } default: ERR(handle, "unsupported protocol %u, could not " "parse address", proto); return STATUS_ERR; } return STATUS_SUCCESS; } /* Allocates a sufficiently large buffer (addr, addr_sz) * according to the protocol */ static int node_alloc_addr(sepol_handle_t * handle, int proto, char **addr, size_t * addr_sz) { char *tmp_addr = NULL; size_t tmp_addr_sz; switch (proto) { case SEPOL_PROTO_IP4: tmp_addr_sz = 4; tmp_addr = malloc(4); if (!tmp_addr) goto omem; break; case SEPOL_PROTO_IP6: tmp_addr_sz = 16; tmp_addr = malloc(16); if (!tmp_addr) goto omem; break; default: ERR(handle, "unsupported protocol %u", proto); goto err; } *addr = tmp_addr; *addr_sz = tmp_addr_sz; return STATUS_SUCCESS; omem: ERR(handle, "out of memory"); err: free(tmp_addr); ERR(handle, "could not allocate address of protocol %s", sepol_node_get_proto_str(proto)); return STATUS_ERR; } /* Converts a numeric representation (addr_bytes) * to a string representation (addr_str), according to * the protocol */ static int node_expand_addr(sepol_handle_t * handle, char *addr_bytes, int proto, char *addr_str) { switch (proto) { case SEPOL_PROTO_IP4: { struct in_addr addr; memset(&addr, 0, sizeof(struct in_addr)); memcpy(&addr.s_addr, addr_bytes, 4); if (inet_ntop(AF_INET, &addr, addr_str, INET_ADDRSTRLEN) == NULL) { ERR(handle, "could not expand IPv4 address to string: %m"); return STATUS_ERR; } break; } case SEPOL_PROTO_IP6: { struct in6_addr addr; memset(&addr, 0, sizeof(struct in6_addr)); memcpy(&addr.s6_addr[0], addr_bytes, 16); if (inet_ntop(AF_INET6, &addr, addr_str, INET6_ADDRSTRLEN) == NULL) { ERR(handle, "could not expand IPv6 address to string: %m"); return STATUS_ERR; } break; } default: ERR(handle, "unsupported protocol %u, could not" " expand address to string", proto); return STATUS_ERR; } return STATUS_SUCCESS; } /* Allocates a sufficiently large address string (addr) * according to the protocol */ static int node_alloc_addr_string(sepol_handle_t * handle, int proto, char **addr) { char *tmp_addr = NULL; switch (proto) { case SEPOL_PROTO_IP4: tmp_addr = malloc(INET_ADDRSTRLEN); if (!tmp_addr) goto omem; break; case SEPOL_PROTO_IP6: tmp_addr = malloc(INET6_ADDRSTRLEN); if (!tmp_addr) goto omem; break; default: ERR(handle, "unsupported protocol %u", proto); goto err; } *addr = tmp_addr; return STATUS_SUCCESS; omem: ERR(handle, "out of memory"); err: free(tmp_addr); ERR(handle, "could not allocate string buffer for " "address of protocol %s", sepol_node_get_proto_str(proto)); return STATUS_ERR; } /* Key */ int sepol_node_key_create(sepol_handle_t * handle, const char *addr, const char *mask, int proto, sepol_node_key_t ** key_ptr) { sepol_node_key_t *tmp_key = (sepol_node_key_t *) calloc(1, sizeof(sepol_node_key_t)); if (!tmp_key) goto omem; if (node_alloc_addr(handle, proto, &tmp_key->addr, &tmp_key->addr_sz) < 0) goto err; if (node_parse_addr(handle, addr, proto, tmp_key->addr) < 0) goto err; if (node_alloc_addr(handle, proto, &tmp_key->mask, &tmp_key->mask_sz) < 0) goto err; if (node_parse_addr(handle, mask, proto, tmp_key->mask) < 0) goto err; tmp_key->proto = proto; *key_ptr = tmp_key; return STATUS_SUCCESS; omem: ERR(handle, "out of memory"); err: sepol_node_key_free(tmp_key); ERR(handle, "could not create node key for (%s, %s, %s)", addr, mask, sepol_node_get_proto_str(proto)); return STATUS_ERR; } void sepol_node_key_unpack(const sepol_node_key_t * key, const char **addr, const char **mask, int *proto) { *addr = key->addr; *mask = key->mask; *proto = key->proto; } int sepol_node_key_extract(sepol_handle_t * handle, const sepol_node_t * node, sepol_node_key_t ** key_ptr) { sepol_node_key_t *tmp_key = (sepol_node_key_t *) calloc(1, sizeof(sepol_node_key_t)); if (!tmp_key) goto omem; tmp_key->addr = malloc(node->addr_sz); tmp_key->mask = malloc(node->mask_sz); if (!tmp_key->addr || !tmp_key->mask) goto omem; memcpy(tmp_key->addr, node->addr, node->addr_sz); memcpy(tmp_key->mask, node->mask, node->mask_sz); tmp_key->addr_sz = node->addr_sz; tmp_key->mask_sz = node->mask_sz; tmp_key->proto = node->proto; *key_ptr = tmp_key; return STATUS_SUCCESS; omem: sepol_node_key_free(tmp_key); ERR(handle, "out of memory, could not extract node key"); return STATUS_ERR; } void sepol_node_key_free(sepol_node_key_t * key) { if (!key) return; free(key->addr); free(key->mask); free(key); } int sepol_node_compare(const sepol_node_t * node, const sepol_node_key_t * key) { int rc1, rc2; if ((node->addr_sz < key->addr_sz) || (node->mask_sz < key->mask_sz)) return -1; else if ((node->addr_sz > key->addr_sz) || (node->mask_sz > key->mask_sz)) return 1; rc1 = memcmp(node->addr, key->addr, node->addr_sz); rc2 = memcmp(node->mask, key->mask, node->mask_sz); return (rc2 != 0) ? rc2 : rc1; } int sepol_node_compare2(const sepol_node_t * node, const sepol_node_t * node2) { int rc1, rc2; if ((node->addr_sz < node2->addr_sz) || (node->mask_sz < node2->mask_sz)) return -1; else if ((node->addr_sz > node2->addr_sz) || (node->mask_sz > node2->mask_sz)) return 1; rc1 = memcmp(node->addr, node2->addr, node->addr_sz); rc2 = memcmp(node->mask, node2->mask, node->mask_sz); return (rc2 != 0) ? rc2 : rc1; } /* Addr */ int sepol_node_get_addr(sepol_handle_t * handle, const sepol_node_t * node, char **addr) { char *tmp_addr = NULL; if (node_alloc_addr_string(handle, node->proto, &tmp_addr) < 0) goto err; if (node_expand_addr(handle, node->addr, node->proto, tmp_addr) < 0) goto err; *addr = tmp_addr; return STATUS_SUCCESS; err: free(tmp_addr); ERR(handle, "could not get node address"); return STATUS_ERR; } int sepol_node_get_addr_bytes(sepol_handle_t * handle, const sepol_node_t * node, char **buffer, size_t * bsize) { char *tmp_buf = malloc(node->addr_sz); if (!tmp_buf) { ERR(handle, "out of memory, could not get address bytes"); return STATUS_ERR; } memcpy(tmp_buf, node->addr, node->addr_sz); *buffer = tmp_buf; *bsize = node->addr_sz; return STATUS_SUCCESS; } int sepol_node_set_addr(sepol_handle_t * handle, sepol_node_t * node, int proto, const char *addr) { char *tmp_addr = NULL; size_t tmp_addr_sz; if (node_alloc_addr(handle, proto, &tmp_addr, &tmp_addr_sz) < 0) goto err; if (node_parse_addr(handle, addr, proto, tmp_addr) < 0) goto err; free(node->addr); node->addr = tmp_addr; node->addr_sz = tmp_addr_sz; return STATUS_SUCCESS; err: free(tmp_addr); ERR(handle, "could not set node address to %s", addr); return STATUS_ERR; } int sepol_node_set_addr_bytes(sepol_handle_t * handle, sepol_node_t * node, const char *addr, size_t addr_sz) { char *tmp_addr = malloc(addr_sz); if (!tmp_addr) { ERR(handle, "out of memory, could not " "set node address"); return STATUS_ERR; } memcpy(tmp_addr, addr, addr_sz); free(node->addr); node->addr = tmp_addr; node->addr_sz = addr_sz; return STATUS_SUCCESS; } /* Mask */ int sepol_node_get_mask(sepol_handle_t * handle, const sepol_node_t * node, char **mask) { char *tmp_mask = NULL; if (node_alloc_addr_string(handle, node->proto, &tmp_mask) < 0) goto err; if (node_expand_addr(handle, node->mask, node->proto, tmp_mask) < 0) goto err; *mask = tmp_mask; return STATUS_SUCCESS; err: free(tmp_mask); ERR(handle, "could not get node netmask"); return STATUS_ERR; } int sepol_node_get_mask_bytes(sepol_handle_t * handle, const sepol_node_t * node, char **buffer, size_t * bsize) { char *tmp_buf = malloc(node->mask_sz); if (!tmp_buf) { ERR(handle, "out of memory, could not get netmask bytes"); return STATUS_ERR; } memcpy(tmp_buf, node->mask, node->mask_sz); *buffer = tmp_buf; *bsize = node->mask_sz; return STATUS_SUCCESS; } int sepol_node_set_mask(sepol_handle_t * handle, sepol_node_t * node, int proto, const char *mask) { char *tmp_mask = NULL; size_t tmp_mask_sz; if (node_alloc_addr(handle, proto, &tmp_mask, &tmp_mask_sz) < 0) goto err; if (node_parse_addr(handle, mask, proto, tmp_mask) < 0) goto err; free(node->mask); node->mask = tmp_mask; node->mask_sz = tmp_mask_sz; return STATUS_SUCCESS; err: free(tmp_mask); ERR(handle, "could not set node netmask to %s", mask); return STATUS_ERR; } int sepol_node_set_mask_bytes(sepol_handle_t * handle, sepol_node_t * node, const char *mask, size_t mask_sz) { char *tmp_mask = malloc(mask_sz); if (!tmp_mask) { ERR(handle, "out of memory, could not " "set node netmask"); return STATUS_ERR; } memcpy(tmp_mask, mask, mask_sz); free(node->mask); node->mask = tmp_mask; node->mask_sz = mask_sz; return STATUS_SUCCESS; } /* Protocol */ int sepol_node_get_proto(const sepol_node_t * node) { return node->proto; } void sepol_node_set_proto(sepol_node_t * node, int proto) { node->proto = proto; } const char *sepol_node_get_proto_str(int proto) { switch (proto) { case SEPOL_PROTO_IP4: return "ipv4"; case SEPOL_PROTO_IP6: return "ipv6"; default: return "???"; } } /* Create */ int sepol_node_create(sepol_handle_t * handle, sepol_node_t ** node) { sepol_node_t *tmp_node = (sepol_node_t *) malloc(sizeof(sepol_node_t)); if (!tmp_node) { ERR(handle, "out of memory, could not create " "node record"); return STATUS_ERR; } tmp_node->addr = NULL; tmp_node->addr_sz = 0; tmp_node->mask = NULL; tmp_node->mask_sz = 0; tmp_node->proto = SEPOL_PROTO_IP4; tmp_node->con = NULL; *node = tmp_node; return STATUS_SUCCESS; } /* Deep copy clone */ int sepol_node_clone(sepol_handle_t * handle, const sepol_node_t * node, sepol_node_t ** node_ptr) { sepol_node_t *new_node = NULL; if (sepol_node_create(handle, &new_node) < 0) goto err; /* Copy address, mask, protocol */ new_node->addr = malloc(node->addr_sz); new_node->mask = malloc(node->mask_sz); if (!new_node->addr || !new_node->mask) goto omem; memcpy(new_node->addr, node->addr, node->addr_sz); memcpy(new_node->mask, node->mask, node->mask_sz); new_node->addr_sz = node->addr_sz; new_node->mask_sz = node->mask_sz; new_node->proto = node->proto; /* Copy context */ if (node->con && (sepol_context_clone(handle, node->con, &new_node->con) < 0)) goto err; *node_ptr = new_node; return STATUS_SUCCESS; omem: ERR(handle, "out of memory"); err: ERR(handle, "could not clone node record"); sepol_node_free(new_node); return STATUS_ERR; } /* Destroy */ void sepol_node_free(sepol_node_t * node) { if (!node) return; sepol_context_free(node->con); free(node->addr); free(node->mask); free(node); } /* Context */ sepol_context_t *sepol_node_get_con(const sepol_node_t * node) { return node->con; } int sepol_node_set_con(sepol_handle_t * handle, sepol_node_t * node, sepol_context_t * con) { sepol_context_t *newcon; if (sepol_context_clone(handle, con, &newcon) < 0) { ERR(handle, "out of memory, could not set node context"); return STATUS_ERR; } sepol_context_free(node->con); node->con = newcon; return STATUS_SUCCESS; } libsepol-3.8.1/src/nodes.c000066400000000000000000000207461476211737200154220ustar00rootroot00000000000000#include #include #include #include "debug.h" #include "context.h" #include "handle.h" #include #include "node_internal.h" /* Create a low level node structure from * a high level representation */ static int node_from_record(sepol_handle_t * handle, const policydb_t * policydb, ocontext_t ** node, const sepol_node_t * data) { ocontext_t *tmp_node = NULL; context_struct_t *tmp_con = NULL; char *addr_buf = NULL, *mask_buf = NULL; size_t addr_bsize, mask_bsize; int proto; tmp_node = (ocontext_t *) calloc(1, sizeof(ocontext_t)); if (!tmp_node) goto omem; /* Address and netmask */ if (sepol_node_get_addr_bytes(handle, data, &addr_buf, &addr_bsize) < 0) goto err; if (sepol_node_get_mask_bytes(handle, data, &mask_buf, &mask_bsize) < 0) goto err; proto = sepol_node_get_proto(data); switch (proto) { case SEPOL_PROTO_IP4: memcpy(&tmp_node->u.node.addr, addr_buf, addr_bsize); memcpy(&tmp_node->u.node.mask, mask_buf, mask_bsize); break; case SEPOL_PROTO_IP6: memcpy(tmp_node->u.node6.addr, addr_buf, addr_bsize); memcpy(tmp_node->u.node6.mask, mask_buf, mask_bsize); break; default: ERR(handle, "unsupported protocol %u", proto); goto err; } free(addr_buf); free(mask_buf); addr_buf = NULL; mask_buf = NULL; /* Context */ if (context_from_record(handle, policydb, &tmp_con, sepol_node_get_con(data)) < 0) goto err; context_cpy(&tmp_node->context[0], tmp_con); context_destroy(tmp_con); free(tmp_con); tmp_con = NULL; *node = tmp_node; return STATUS_SUCCESS; omem: ERR(handle, "out of memory"); err: if (tmp_node != NULL) { context_destroy(&tmp_node->context[0]); free(tmp_node); } context_destroy(tmp_con); free(tmp_con); free(addr_buf); free(mask_buf); ERR(handle, "could not create node structure"); return STATUS_ERR; } static int node_to_record(sepol_handle_t * handle, const policydb_t * policydb, ocontext_t * node, int proto, sepol_node_t ** record) { context_struct_t *con = &node->context[0]; sepol_context_t *tmp_con = NULL; sepol_node_t *tmp_record = NULL; if (sepol_node_create(handle, &tmp_record) < 0) goto err; sepol_node_set_proto(tmp_record, proto); switch (proto) { case SEPOL_PROTO_IP4: if (sepol_node_set_addr_bytes(handle, tmp_record, (const char *)&node->u.node.addr, 4) < 0) goto err; if (sepol_node_set_mask_bytes(handle, tmp_record, (const char *)&node->u.node.mask, 4) < 0) goto err; break; case SEPOL_PROTO_IP6: if (sepol_node_set_addr_bytes(handle, tmp_record, (const char *)&node->u.node6.addr, 16) < 0) goto err; if (sepol_node_set_mask_bytes(handle, tmp_record, (const char *)&node->u.node6.mask, 16) < 0) goto err; break; default: ERR(handle, "unsupported protocol %u", proto); goto err; } if (context_to_record(handle, policydb, con, &tmp_con) < 0) goto err; if (sepol_node_set_con(handle, tmp_record, tmp_con) < 0) goto err; sepol_context_free(tmp_con); *record = tmp_record; return STATUS_SUCCESS; err: ERR(handle, "could not convert node to record"); sepol_context_free(tmp_con); sepol_node_free(tmp_record); return STATUS_ERR; } /* Return the number of nodes */ extern int sepol_node_count(sepol_handle_t * handle __attribute__ ((unused)), const sepol_policydb_t * p, unsigned int *response) { unsigned int count = 0; ocontext_t *c, *head; const policydb_t *policydb = &p->p; head = policydb->ocontexts[OCON_NODE]; for (c = head; c != NULL; c = c->next) count++; head = policydb->ocontexts[OCON_NODE6]; for (c = head; c != NULL; c = c->next) count++; *response = count; return STATUS_SUCCESS; } /* Check if a node exists */ int sepol_node_exists(sepol_handle_t * handle, const sepol_policydb_t * p, const sepol_node_key_t * key, int *response) { const policydb_t *policydb = &p->p; ocontext_t *c, *head; int proto; const char *addr, *mask; sepol_node_key_unpack(key, &addr, &mask, &proto); switch (proto) { case SEPOL_PROTO_IP4: { head = policydb->ocontexts[OCON_NODE]; for (c = head; c; c = c->next) { unsigned int *addr2 = &c->u.node.addr; unsigned int *mask2 = &c->u.node.mask; if (!memcmp(addr, addr2, 4) && !memcmp(mask, mask2, 4)) { *response = 1; return STATUS_SUCCESS; } } break; } case SEPOL_PROTO_IP6: { head = policydb->ocontexts[OCON_NODE6]; for (c = head; c; c = c->next) { unsigned int *addr2 = c->u.node6.addr; unsigned int *mask2 = c->u.node6.mask; if (!memcmp(addr, addr2, 16) && !memcmp(mask, mask2, 16)) { *response = 1; return STATUS_SUCCESS; } } break; } default: ERR(handle, "unsupported protocol %u", proto); goto err; } *response = 0; return STATUS_SUCCESS; err: ERR(handle, "could not check if node %s/%s (%s) exists", addr, mask, sepol_node_get_proto_str(proto)); return STATUS_ERR; } /* Query a node */ int sepol_node_query(sepol_handle_t * handle, const sepol_policydb_t * p, const sepol_node_key_t * key, sepol_node_t ** response) { const policydb_t *policydb = &p->p; ocontext_t *c, *head; int proto; const char *addr, *mask; sepol_node_key_unpack(key, &addr, &mask, &proto); switch (proto) { case SEPOL_PROTO_IP4: { head = policydb->ocontexts[OCON_NODE]; for (c = head; c; c = c->next) { unsigned int *addr2 = &c->u.node.addr; unsigned int *mask2 = &c->u.node.mask; if (!memcmp(addr, addr2, 4) && !memcmp(mask, mask2, 4)) { if (node_to_record(handle, policydb, c, SEPOL_PROTO_IP4, response) < 0) goto err; return STATUS_SUCCESS; } } break; } case SEPOL_PROTO_IP6: { head = policydb->ocontexts[OCON_NODE6]; for (c = head; c; c = c->next) { unsigned int *addr2 = c->u.node6.addr; unsigned int *mask2 = c->u.node6.mask; if (!memcmp(addr, addr2, 16) && !memcmp(mask, mask2, 16)) { if (node_to_record(handle, policydb, c, SEPOL_PROTO_IP6, response) < 0) goto err; return STATUS_SUCCESS; } } break; } default: ERR(handle, "unsupported protocol %u", proto); goto err; } *response = NULL; return STATUS_SUCCESS; err: ERR(handle, "could not query node %s/%s (%s)", addr, mask, sepol_node_get_proto_str(proto)); return STATUS_ERR; } /* Load a node into policy */ int sepol_node_modify(sepol_handle_t * handle, sepol_policydb_t * p, const sepol_node_key_t * key, const sepol_node_t * data) { policydb_t *policydb = &p->p; ocontext_t *node = NULL; int proto; const char *addr, *mask; sepol_node_key_unpack(key, &addr, &mask, &proto); if (node_from_record(handle, policydb, &node, data) < 0) goto err; switch (proto) { case SEPOL_PROTO_IP4: { /* Attach to context list */ node->next = policydb->ocontexts[OCON_NODE]; policydb->ocontexts[OCON_NODE] = node; break; } case SEPOL_PROTO_IP6: { /* Attach to context list */ node->next = policydb->ocontexts[OCON_NODE6]; policydb->ocontexts[OCON_NODE6] = node; break; } default: ERR(handle, "unsupported protocol %u", proto); goto err; } return STATUS_SUCCESS; err: ERR(handle, "could not load node %s/%s (%s)", addr, mask, sepol_node_get_proto_str(proto)); if (node != NULL) { context_destroy(&node->context[0]); free(node); } return STATUS_ERR; } int sepol_node_iterate(sepol_handle_t * handle, const sepol_policydb_t * p, int (*fn) (const sepol_node_t * node, void *fn_arg), void *arg) { const policydb_t *policydb = &p->p; ocontext_t *c, *head; sepol_node_t *node = NULL; int status; head = policydb->ocontexts[OCON_NODE]; for (c = head; c; c = c->next) { if (node_to_record(handle, policydb, c, SEPOL_PROTO_IP4, &node) < 0) goto err; /* Invoke handler */ status = fn(node, arg); if (status < 0) goto err; sepol_node_free(node); node = NULL; /* Handler requested exit */ if (status > 0) break; } head = policydb->ocontexts[OCON_NODE6]; for (c = head; c; c = c->next) { if (node_to_record(handle, policydb, c, SEPOL_PROTO_IP6, &node) < 0) goto err; /* Invoke handler */ status = fn(node, arg); if (status < 0) goto err; sepol_node_free(node); node = NULL; /* Handler requested exit */ if (status > 0) break; } return STATUS_SUCCESS; err: ERR(handle, "could not iterate over nodes"); sepol_node_free(node); return STATUS_ERR; } libsepol-3.8.1/src/optimize.c000066400000000000000000000264361476211737200161540ustar00rootroot00000000000000/* * Author: Ondrej Mosnacek * * Copyright (C) 2019 Red Hat Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* * Binary policy optimization. * * Defines the policydb_optimize() function, which finds and removes * redundant rules from the binary policy to reduce its size and potentially * improve rule matching times. Only rules that are already covered by a * more general rule are removed. The resulting policy is functionally * equivalent to the original one. */ #include #include #include "debug.h" #include "private.h" #define TYPE_VEC_INIT_SIZE 16 struct type_vec { uint32_t *types; unsigned int count, capacity; }; static int type_vec_init(struct type_vec *v) { v->capacity = TYPE_VEC_INIT_SIZE; v->count = 0; v->types = calloc(v->capacity, sizeof(*v->types)); if (!v->types) return -1; return 0; } static void type_vec_destroy(struct type_vec *v) { free(v->types); } static int type_vec_append(struct type_vec *v, uint32_t type) { if (v->capacity == v->count) { unsigned int new_capacity = v->capacity * 2; uint32_t *new_types = reallocarray(v->types, new_capacity, sizeof(*v->types)); if (!new_types) return -1; v->types = new_types; v->capacity = new_capacity; } v->types[v->count++] = type; return 0; } static int type_vec_contains(const struct type_vec *v, uint32_t type) { unsigned int s = 0, e = v->count; while (s != e) { unsigned int mid = (s + e) / 2; if (v->types[mid] == type) return 1; if (v->types[mid] < type) s = mid + 1; else e = mid; } return 0; } /* builds map: type/attribute -> {all attributes that are a superset of it} */ static struct type_vec *build_type_map(const policydb_t *p) { unsigned int i, k; ebitmap_node_t *n; struct type_vec *map = calloc(p->p_types.nprim, sizeof(*map)); if (!map) return NULL; for (i = 0; i < p->p_types.nprim; i++) { if (type_vec_init(&map[i])) goto err; if (!p->type_val_to_struct[i]) continue; if (p->type_val_to_struct[i]->flavor != TYPE_ATTRIB) { ebitmap_for_each_positive_bit(&p->type_attr_map[i], n, k) { if (type_vec_append(&map[i], k)) goto err; } } else { ebitmap_t *types_i = &p->attr_type_map[i]; for (k = 0; k < p->p_types.nprim; k++) { const ebitmap_t *types_k; if (!p->type_val_to_struct[k] || p->type_val_to_struct[k]->flavor != TYPE_ATTRIB) continue; types_k = &p->attr_type_map[k]; if (ebitmap_contains(types_k, types_i)) { if (type_vec_append(&map[i], k)) goto err; } } } } return map; err: for (k = 0; k <= i; k++) type_vec_destroy(&map[k]); free(map); return NULL; } static void destroy_type_map(const policydb_t *p, struct type_vec *type_map) { unsigned int i; for (i = 0; i < p->p_types.nprim; i++) type_vec_destroy(&type_map[i]); free(type_map); } static int process_xperms(uint32_t *p1, const uint32_t *p2) { size_t i; int ret = 1; for (i = 0; i < EXTENDED_PERMS_LEN; i++) { p1[i] &= ~p2[i]; if (p1[i] != 0) ret = 0; } return ret; } static int process_avtab_datum(uint16_t specified, avtab_datum_t *d1, const avtab_datum_t *d2) { /* inverse logic needed for AUDITDENY rules */ if (specified & AVTAB_AUDITDENY) return (d1->data |= ~d2->data) == UINT32_C(0xFFFFFFFF); if (specified & AVTAB_AV) return (d1->data &= ~d2->data) == 0; if (specified & AVTAB_XPERMS) { avtab_extended_perms_t *x1 = d1->xperms; const avtab_extended_perms_t *x2 = d2->xperms; if (x1->specified == AVTAB_XPERMS_IOCTLFUNCTION) { if (x2->specified == AVTAB_XPERMS_IOCTLFUNCTION) { if (x1->driver != x2->driver) return 0; return process_xperms(x1->perms, x2->perms); } if (x2->specified == AVTAB_XPERMS_IOCTLDRIVER) return xperm_test(x1->driver, x2->perms); } else if (x1->specified == AVTAB_XPERMS_IOCTLDRIVER) { if (x2->specified == AVTAB_XPERMS_IOCTLFUNCTION) return 0; if (x2->specified == AVTAB_XPERMS_IOCTLDRIVER) return process_xperms(x1->perms, x2->perms); } else if (x1->specified == AVTAB_XPERMS_NLMSG && x2->specified == AVTAB_XPERMS_NLMSG) { if (x1->driver != x2->driver) return 0; return process_xperms(x1->perms, x2->perms); } return 0; } return 0; } /* checks if avtab contains a rule that covers the given rule */ static int is_avrule_redundant(avtab_ptr_t entry, avtab_t *tab, const struct type_vec *type_map, unsigned char not_cond) { unsigned int i, k, s_idx, t_idx; uint32_t st, tt; avtab_datum_t *d1, *d2; avtab_key_t key; /* we only care about AV rules */ if (!(entry->key.specified & (AVTAB_AV|AVTAB_XPERMS))) return 0; s_idx = entry->key.source_type - 1; t_idx = entry->key.target_type - 1; key.target_class = entry->key.target_class; key.specified = entry->key.specified; d1 = &entry->datum; for (i = 0; i < type_map[s_idx].count; i++) { st = type_map[s_idx].types[i]; key.source_type = st + 1; for (k = 0; k < type_map[t_idx].count; k++) { tt = type_map[t_idx].types[k]; if (not_cond && s_idx == st && t_idx == tt) continue; key.target_type = tt + 1; d2 = avtab_search(tab, &key); if (!d2) continue; if (process_avtab_datum(key.specified, d1, d2)) return 1; } } return 0; } static int is_type_attr(policydb_t *p, unsigned int id) { return p->type_val_to_struct[id]->flavor == TYPE_ATTRIB; } static int is_avrule_with_attr(avtab_ptr_t entry, policydb_t *p) { unsigned int s_idx = entry->key.source_type - 1; unsigned int t_idx = entry->key.target_type - 1; return is_type_attr(p, s_idx) || is_type_attr(p, t_idx); } /* checks if conditional list contains a rule that covers the given rule */ static int is_cond_rule_redundant(avtab_ptr_t e1, cond_av_list_t *list, const struct type_vec *type_map) { unsigned int s1, t1, c1, k1, s2, t2, c2, k2; /* we only care about AV rules */ if (!(e1->key.specified & (AVTAB_AV|AVTAB_XPERMS))) return 0; s1 = e1->key.source_type - 1; t1 = e1->key.target_type - 1; c1 = e1->key.target_class; k1 = e1->key.specified; for (; list; list = list->next) { avtab_ptr_t e2 = list->node; s2 = e2->key.source_type - 1; t2 = e2->key.target_type - 1; c2 = e2->key.target_class; k2 = e2->key.specified; if (k1 != k2 || c1 != c2) continue; if (s1 == s2 && t1 == t2) continue; if (!type_vec_contains(&type_map[s1], s2)) continue; if (!type_vec_contains(&type_map[t1], t2)) continue; if (process_avtab_datum(k1, &e1->datum, &e2->datum)) return 1; } return 0; } static void optimize_avtab(policydb_t *p, const struct type_vec *type_map) { avtab_t *tab = &p->te_avtab; unsigned int i; avtab_ptr_t *cur; for (i = 0; i < tab->nslot; i++) { cur = &tab->htable[i]; while (*cur) { if (is_avrule_redundant(*cur, tab, type_map, 1)) { /* redundant rule -> remove it */ avtab_ptr_t tmp = *cur; *cur = tmp->next; if (tmp->key.specified & AVTAB_XPERMS) free(tmp->datum.xperms); free(tmp); tab->nel--; } else { /* rule not redundant -> move to next rule */ cur = &(*cur)->next; } } } } /* find redundant rules in (*cond) and put them into (*del) */ static void optimize_cond_av_list(cond_av_list_t **cond, cond_av_list_t **del, policydb_t *p, const struct type_vec *type_map) { cond_av_list_t **listp = cond; cond_av_list_t *pcov = NULL; cond_av_list_t **pcov_cur; /* * Separate out all "potentially covering" rules (src or tgt is an attr) * and move them to the end of the list. This is needed to avoid * polynomial complexity when almost all rules are expanded. */ while (*cond) { if (is_avrule_with_attr((*cond)->node, p)) { cond_av_list_t *tmp = *cond; *cond = tmp->next; tmp->next = pcov; pcov = tmp; } else { cond = &(*cond)->next; } } /* link the "potentially covering" rules to the end of the list */ *cond = pcov; /* now go through the list and find the redundant rules */ cond = listp; pcov_cur = &pcov; while (*cond) { /* needed because pcov itself may get deleted */ if (*cond == pcov) pcov_cur = cond; /* * First check if covered by an unconditional rule, then also * check if covered by another rule in the same list. */ if (is_avrule_redundant((*cond)->node, &p->te_avtab, type_map, 0) || is_cond_rule_redundant((*cond)->node, *pcov_cur, type_map)) { cond_av_list_t *tmp = *cond; *cond = tmp->next; tmp->next = *del; *del = tmp; } else { cond = &(*cond)->next; } } } static void optimize_cond_avtab(policydb_t *p, const struct type_vec *type_map) { avtab_t *tab = &p->te_cond_avtab; unsigned int i; avtab_ptr_t *cur; cond_node_t **cond; cond_av_list_t **avcond, *del = NULL; /* First go through all conditionals and collect redundant rules. */ cond = &p->cond_list; while (*cond) { optimize_cond_av_list(&(*cond)->true_list, &del, p, type_map); optimize_cond_av_list(&(*cond)->false_list, &del, p, type_map); /* TODO: maybe also check for rules present in both lists */ /* nothing left in both lists -> remove the whole conditional */ if (!(*cond)->true_list && !(*cond)->false_list) { cond_node_t *cond_tmp = *cond; *cond = cond_tmp->next; cond_node_destroy(cond_tmp); free(cond_tmp); } else { cond = &(*cond)->next; } } if (!del) return; /* * Now go through the whole cond_avtab and remove all rules that are * found in the 'del' list. */ for (i = 0; i < tab->nslot; i++) { cur = &tab->htable[i]; while (*cur) { int redundant = 0; avcond = &del; while (*avcond) { if ((*avcond)->node == *cur) { cond_av_list_t *cond_tmp = *avcond; *avcond = cond_tmp->next; free(cond_tmp); redundant = 1; break; } else { avcond = &(*avcond)->next; } } if (redundant) { avtab_ptr_t tmp = *cur; *cur = tmp->next; if (tmp->key.specified & AVTAB_XPERMS) free(tmp->datum.xperms); free(tmp); tab->nel--; } else { cur = &(*cur)->next; } } } } int policydb_optimize(policydb_t *p) { struct type_vec *type_map; if (p->policy_type != POLICY_KERN) return -1; if (p->policyvers >= POLICYDB_VERSION_AVTAB && p->policyvers <= POLICYDB_VERSION_PERMISSIVE) { /* * For policy versions between 20 and 23, attributes exist in the policy, * but only in the type_attr_map. This means that there are gaps in both * the type_val_to_struct and p_type_val_to_name arrays and policy rules * can refer to those gaps. */ ERR(NULL, "Optimizing policy versions between 20 and 23 is not supported"); return -1; } type_map = build_type_map(p); if (!type_map) return -1; optimize_avtab(p, type_map); optimize_cond_avtab(p, type_map); destroy_type_map(p, type_map); return 0; } libsepol-3.8.1/src/polcaps.c000066400000000000000000000021751476211737200157470ustar00rootroot00000000000000/* * Policy capability support functions */ #include #include static const char * const polcap_names[POLICYDB_CAP_MAX + 1] = { [POLICYDB_CAP_NETPEER] = "network_peer_controls", [POLICYDB_CAP_OPENPERM] = "open_perms", [POLICYDB_CAP_EXTSOCKCLASS] = "extended_socket_class", [POLICYDB_CAP_ALWAYSNETWORK] = "always_check_network", [POLICYDB_CAP_CGROUPSECLABEL] = "cgroup_seclabel", [POLICYDB_CAP_NNP_NOSUID_TRANSITION] = "nnp_nosuid_transition", [POLICYDB_CAP_GENFS_SECLABEL_SYMLINKS] = "genfs_seclabel_symlinks", [POLICYDB_CAP_IOCTL_SKIP_CLOEXEC] = "ioctl_skip_cloexec", [POLICYDB_CAP_USERSPACE_INITIAL_CONTEXT] = "userspace_initial_context", [POLICYDB_CAP_NETLINK_XPERM] = "netlink_xperm", }; int sepol_polcap_getnum(const char *name) { int capnum; for (capnum = 0; capnum <= POLICYDB_CAP_MAX; capnum++) { if (polcap_names[capnum] == NULL) continue; if (strcasecmp(polcap_names[capnum], name) == 0) return capnum; } return -1; } const char *sepol_polcap_getname(unsigned int capnum) { if (capnum > POLICYDB_CAP_MAX) return NULL; return polcap_names[capnum]; } libsepol-3.8.1/src/policydb.c000066400000000000000000003121341476211737200161120ustar00rootroot00000000000000 /* Author : Stephen Smalley, */ /* * Updated: Trusted Computer Solutions, Inc. * * Support for enhanced MLS infrastructure. * * Updated: Frank Mayer and Karl MacMillan * * Added conditional policy language extensions * * Updated: Red Hat, Inc. James Morris * Fine-grained netlink support * IPv6 support * Code cleanup * * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. * Copyright (C) 2003 - 2005 Tresys Technology, LLC * Copyright (C) 2003 - 2007 Red Hat, Inc. * Copyright (C) 2017 Mellanox Technologies Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* FLASK */ /* * Implementation of the policy database. */ #include #include #include #include #include #include #include #include "kernel_to_common.h" #include "private.h" #include "debug.h" #include "mls.h" #include "policydb_validate.h" #define POLICYDB_TARGET_SZ ARRAY_SIZE(policydb_target_strings) const char * const policydb_target_strings[] = { POLICYDB_STRING, POLICYDB_XEN_STRING }; /* These need to be updated if SYM_NUM or OCON_NUM changes */ static const struct policydb_compat_info policydb_compat[] = { { .type = POLICY_KERN, .version = POLICYDB_VERSION_BOUNDARY, .sym_num = SYM_NUM, .ocon_num = OCON_XEN_PCIDEVICE + 1, .target_platform = SEPOL_TARGET_XEN, }, { .type = POLICY_KERN, .version = POLICYDB_VERSION_XEN_DEVICETREE, .sym_num = SYM_NUM, .ocon_num = OCON_XEN_DEVICETREE + 1, .target_platform = SEPOL_TARGET_XEN, }, { .type = POLICY_KERN, .version = POLICYDB_VERSION_BASE, .sym_num = SYM_NUM - 3, .ocon_num = OCON_FSUSE + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_KERN, .version = POLICYDB_VERSION_BOOL, .sym_num = SYM_NUM - 2, .ocon_num = OCON_FSUSE + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_KERN, .version = POLICYDB_VERSION_IPV6, .sym_num = SYM_NUM - 2, .ocon_num = OCON_NODE6 + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_KERN, .version = POLICYDB_VERSION_NLCLASS, .sym_num = SYM_NUM - 2, .ocon_num = OCON_NODE6 + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_KERN, .version = POLICYDB_VERSION_MLS, .sym_num = SYM_NUM, .ocon_num = OCON_NODE6 + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_KERN, .version = POLICYDB_VERSION_AVTAB, .sym_num = SYM_NUM, .ocon_num = OCON_NODE6 + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_KERN, .version = POLICYDB_VERSION_RANGETRANS, .sym_num = SYM_NUM, .ocon_num = OCON_NODE6 + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_KERN, .version = POLICYDB_VERSION_POLCAP, .sym_num = SYM_NUM, .ocon_num = OCON_NODE6 + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_KERN, .version = POLICYDB_VERSION_PERMISSIVE, .sym_num = SYM_NUM, .ocon_num = OCON_NODE6 + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_KERN, .version = POLICYDB_VERSION_BOUNDARY, .sym_num = SYM_NUM, .ocon_num = OCON_NODE6 + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_KERN, .version = POLICYDB_VERSION_FILENAME_TRANS, .sym_num = SYM_NUM, .ocon_num = OCON_NODE6 + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_KERN, .version = POLICYDB_VERSION_ROLETRANS, .sym_num = SYM_NUM, .ocon_num = OCON_NODE6 + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_KERN, .version = POLICYDB_VERSION_NEW_OBJECT_DEFAULTS, .sym_num = SYM_NUM, .ocon_num = OCON_NODE6 + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_KERN, .version = POLICYDB_VERSION_DEFAULT_TYPE, .sym_num = SYM_NUM, .ocon_num = OCON_NODE6 + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_KERN, .version = POLICYDB_VERSION_CONSTRAINT_NAMES, .sym_num = SYM_NUM, .ocon_num = OCON_NODE6 + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_KERN, .version = POLICYDB_VERSION_XPERMS_IOCTL, .sym_num = SYM_NUM, .ocon_num = OCON_NODE6 + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_KERN, .version = POLICYDB_VERSION_INFINIBAND, .sym_num = SYM_NUM, .ocon_num = OCON_IBENDPORT + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_KERN, .version = POLICYDB_VERSION_GLBLUB, .sym_num = SYM_NUM, .ocon_num = OCON_IBENDPORT + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_KERN, .version = POLICYDB_VERSION_COMP_FTRANS, .sym_num = SYM_NUM, .ocon_num = OCON_IBENDPORT + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_KERN, .version = POLICYDB_VERSION_COND_XPERMS, .sym_num = SYM_NUM, .ocon_num = OCON_IBENDPORT + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_BASE, .version = MOD_POLICYDB_VERSION_BASE, .sym_num = SYM_NUM, .ocon_num = OCON_NODE6 + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_BASE, .version = MOD_POLICYDB_VERSION_MLS, .sym_num = SYM_NUM, .ocon_num = OCON_NODE6 + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_BASE, .version = MOD_POLICYDB_VERSION_MLS_USERS, .sym_num = SYM_NUM, .ocon_num = OCON_NODE6 + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_BASE, .version = MOD_POLICYDB_VERSION_POLCAP, .sym_num = SYM_NUM, .ocon_num = OCON_NODE6 + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_BASE, .version = MOD_POLICYDB_VERSION_PERMISSIVE, .sym_num = SYM_NUM, .ocon_num = OCON_NODE6 + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_BASE, .version = MOD_POLICYDB_VERSION_BOUNDARY, .sym_num = SYM_NUM, .ocon_num = OCON_NODE6 + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_BASE, .version = MOD_POLICYDB_VERSION_BOUNDARY_ALIAS, .sym_num = SYM_NUM, .ocon_num = OCON_NODE6 + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_BASE, .version = MOD_POLICYDB_VERSION_FILENAME_TRANS, .sym_num = SYM_NUM, .ocon_num = OCON_NODE6 + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_BASE, .version = MOD_POLICYDB_VERSION_ROLETRANS, .sym_num = SYM_NUM, .ocon_num = OCON_NODE6 + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_BASE, .version = MOD_POLICYDB_VERSION_ROLEATTRIB, .sym_num = SYM_NUM, .ocon_num = OCON_NODE6 + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_BASE, .version = MOD_POLICYDB_VERSION_TUNABLE_SEP, .sym_num = SYM_NUM, .ocon_num = OCON_NODE6 + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_BASE, .version = MOD_POLICYDB_VERSION_NEW_OBJECT_DEFAULTS, .sym_num = SYM_NUM, .ocon_num = OCON_NODE6 + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_BASE, .version = MOD_POLICYDB_VERSION_DEFAULT_TYPE, .sym_num = SYM_NUM, .ocon_num = OCON_NODE6 + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_BASE, .version = MOD_POLICYDB_VERSION_CONSTRAINT_NAMES, .sym_num = SYM_NUM, .ocon_num = OCON_NODE6 + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_BASE, .version = MOD_POLICYDB_VERSION_XPERMS_IOCTL, .sym_num = SYM_NUM, .ocon_num = OCON_NODE6 + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_BASE, .version = MOD_POLICYDB_VERSION_INFINIBAND, .sym_num = SYM_NUM, .ocon_num = OCON_IBENDPORT + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_BASE, .version = MOD_POLICYDB_VERSION_GLBLUB, .sym_num = SYM_NUM, .ocon_num = OCON_IBENDPORT + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_BASE, .version = MOD_POLICYDB_VERSION_SELF_TYPETRANS, .sym_num = SYM_NUM, .ocon_num = OCON_IBENDPORT + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_BASE, .version = MOD_POLICYDB_VERSION_COND_XPERMS, .sym_num = SYM_NUM, .ocon_num = OCON_IBENDPORT + 1, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_MOD, .version = MOD_POLICYDB_VERSION_BASE, .sym_num = SYM_NUM, .ocon_num = 0, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_MOD, .version = MOD_POLICYDB_VERSION_MLS, .sym_num = SYM_NUM, .ocon_num = 0, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_MOD, .version = MOD_POLICYDB_VERSION_MLS_USERS, .sym_num = SYM_NUM, .ocon_num = 0, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_MOD, .version = MOD_POLICYDB_VERSION_POLCAP, .sym_num = SYM_NUM, .ocon_num = 0, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_MOD, .version = MOD_POLICYDB_VERSION_PERMISSIVE, .sym_num = SYM_NUM, .ocon_num = 0, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_MOD, .version = MOD_POLICYDB_VERSION_BOUNDARY, .sym_num = SYM_NUM, .ocon_num = 0, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_MOD, .version = MOD_POLICYDB_VERSION_BOUNDARY_ALIAS, .sym_num = SYM_NUM, .ocon_num = 0, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_MOD, .version = MOD_POLICYDB_VERSION_FILENAME_TRANS, .sym_num = SYM_NUM, .ocon_num = 0, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_MOD, .version = MOD_POLICYDB_VERSION_ROLETRANS, .sym_num = SYM_NUM, .ocon_num = 0, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_MOD, .version = MOD_POLICYDB_VERSION_ROLEATTRIB, .sym_num = SYM_NUM, .ocon_num = 0, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_MOD, .version = MOD_POLICYDB_VERSION_TUNABLE_SEP, .sym_num = SYM_NUM, .ocon_num = 0, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_MOD, .version = MOD_POLICYDB_VERSION_NEW_OBJECT_DEFAULTS, .sym_num = SYM_NUM, .ocon_num = 0, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_MOD, .version = MOD_POLICYDB_VERSION_DEFAULT_TYPE, .sym_num = SYM_NUM, .ocon_num = 0, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_MOD, .version = MOD_POLICYDB_VERSION_CONSTRAINT_NAMES, .sym_num = SYM_NUM, .ocon_num = 0, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_MOD, .version = MOD_POLICYDB_VERSION_XPERMS_IOCTL, .sym_num = SYM_NUM, .ocon_num = 0, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_MOD, .version = MOD_POLICYDB_VERSION_INFINIBAND, .sym_num = SYM_NUM, .ocon_num = 0, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_MOD, .version = MOD_POLICYDB_VERSION_GLBLUB, .sym_num = SYM_NUM, .ocon_num = 0, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_MOD, .version = MOD_POLICYDB_VERSION_SELF_TYPETRANS, .sym_num = SYM_NUM, .ocon_num = 0, .target_platform = SEPOL_TARGET_SELINUX, }, { .type = POLICY_MOD, .version = MOD_POLICYDB_VERSION_COND_XPERMS, .sym_num = SYM_NUM, .ocon_num = 0, .target_platform = SEPOL_TARGET_SELINUX, }, }; #if 0 static char *symtab_name[SYM_NUM] = { "common prefixes", "classes", "roles", "types", "users", "bools" mls_symtab_names cond_symtab_names }; #endif static const unsigned int symtab_sizes[SYM_NUM] = { 2, 32, 16, 512, 128, 16, 16, 16, }; const struct policydb_compat_info *policydb_lookup_compat(unsigned int version, unsigned int type, unsigned int target_platform) { unsigned int i; const struct policydb_compat_info *info = NULL; for (i = 0; i < sizeof(policydb_compat) / sizeof(*info); i++) { if (policydb_compat[i].version == version && policydb_compat[i].type == type && policydb_compat[i].target_platform == target_platform) { info = &policydb_compat[i]; break; } } return info; } void type_set_init(type_set_t * x) { memset(x, 0, sizeof(type_set_t)); ebitmap_init(&x->types); ebitmap_init(&x->negset); } void type_set_destroy(type_set_t * x) { if (x != NULL) { ebitmap_destroy(&x->types); ebitmap_destroy(&x->negset); } } void role_set_init(role_set_t * x) { memset(x, 0, sizeof(role_set_t)); ebitmap_init(&x->roles); } void role_set_destroy(role_set_t * x) { ebitmap_destroy(&x->roles); } void role_datum_init(role_datum_t * x) { memset(x, 0, sizeof(role_datum_t)); ebitmap_init(&x->dominates); type_set_init(&x->types); ebitmap_init(&x->cache); ebitmap_init(&x->roles); } void role_datum_destroy(role_datum_t * x) { if (x != NULL) { ebitmap_destroy(&x->dominates); type_set_destroy(&x->types); ebitmap_destroy(&x->cache); ebitmap_destroy(&x->roles); } } void type_datum_init(type_datum_t * x) { memset(x, 0, sizeof(*x)); ebitmap_init(&x->types); } void type_datum_destroy(type_datum_t * x) { if (x != NULL) { ebitmap_destroy(&x->types); } } void user_datum_init(user_datum_t * x) { memset(x, 0, sizeof(user_datum_t)); role_set_init(&x->roles); mls_semantic_range_init(&x->range); mls_semantic_level_init(&x->dfltlevel); ebitmap_init(&x->cache); mls_range_init(&x->exp_range); mls_level_init(&x->exp_dfltlevel); } void user_datum_destroy(user_datum_t * x) { if (x != NULL) { role_set_destroy(&x->roles); mls_semantic_range_destroy(&x->range); mls_semantic_level_destroy(&x->dfltlevel); ebitmap_destroy(&x->cache); mls_range_destroy(&x->exp_range); mls_level_destroy(&x->exp_dfltlevel); } } void level_datum_init(level_datum_t * x) { memset(x, 0, sizeof(level_datum_t)); } void level_datum_destroy(level_datum_t * x __attribute__ ((unused))) { /* the mls_level_t referenced by the level_datum is managed * separately for now, so there is nothing to destroy */ return; } void cat_datum_init(cat_datum_t * x) { memset(x, 0, sizeof(cat_datum_t)); } void cat_datum_destroy(cat_datum_t * x __attribute__ ((unused))) { /* it's currently a simple struct - really nothing to destroy */ return; } void class_perm_node_init(class_perm_node_t * x) { memset(x, 0, sizeof(class_perm_node_t)); } void avrule_init(avrule_t * x) { memset(x, 0, sizeof(avrule_t)); type_set_init(&x->stypes); type_set_init(&x->ttypes); } void avrule_destroy(avrule_t * x) { class_perm_node_t *cur, *next; if (x == NULL) { return; } type_set_destroy(&x->stypes); type_set_destroy(&x->ttypes); free(x->source_filename); next = x->perms; while (next) { cur = next; next = cur->next; free(cur); } free(x->xperms); } void role_trans_rule_init(role_trans_rule_t * x) { memset(x, 0, sizeof(*x)); role_set_init(&x->roles); type_set_init(&x->types); ebitmap_init(&x->classes); } static void role_trans_rule_destroy(role_trans_rule_t * x) { if (x != NULL) { role_set_destroy(&x->roles); type_set_destroy(&x->types); ebitmap_destroy(&x->classes); } } void role_trans_rule_list_destroy(role_trans_rule_t * x) { while (x != NULL) { role_trans_rule_t *next = x->next; role_trans_rule_destroy(x); free(x); x = next; } } void filename_trans_rule_init(filename_trans_rule_t * x) { memset(x, 0, sizeof(*x)); type_set_init(&x->stypes); type_set_init(&x->ttypes); } static void filename_trans_rule_destroy(filename_trans_rule_t * x) { if (!x) return; type_set_destroy(&x->stypes); type_set_destroy(&x->ttypes); free(x->name); } void filename_trans_rule_list_destroy(filename_trans_rule_t * x) { filename_trans_rule_t *next; while (x) { next = x->next; filename_trans_rule_destroy(x); free(x); x = next; } } void role_allow_rule_init(role_allow_rule_t * x) { memset(x, 0, sizeof(role_allow_rule_t)); role_set_init(&x->roles); role_set_init(&x->new_roles); } void role_allow_rule_destroy(role_allow_rule_t * x) { role_set_destroy(&x->roles); role_set_destroy(&x->new_roles); } void role_allow_rule_list_destroy(role_allow_rule_t * x) { while (x != NULL) { role_allow_rule_t *next = x->next; role_allow_rule_destroy(x); free(x); x = next; } } void range_trans_rule_init(range_trans_rule_t * x) { type_set_init(&x->stypes); type_set_init(&x->ttypes); ebitmap_init(&x->tclasses); mls_semantic_range_init(&x->trange); x->next = NULL; } void range_trans_rule_destroy(range_trans_rule_t * x) { type_set_destroy(&x->stypes); type_set_destroy(&x->ttypes); ebitmap_destroy(&x->tclasses); mls_semantic_range_destroy(&x->trange); } void range_trans_rule_list_destroy(range_trans_rule_t * x) { while (x != NULL) { range_trans_rule_t *next = x->next; range_trans_rule_destroy(x); free(x); x = next; } } void avrule_list_destroy(avrule_t * x) { avrule_t *next, *cur; if (!x) return; next = x; while (next) { cur = next; next = next->next; avrule_destroy(cur); free(cur); } } /* * Initialize the role table by implicitly adding role 'object_r'. If * the policy is a module, set object_r's scope to be SCOPE_REQ, * otherwise set it to SCOPE_DECL. */ static int roles_init(policydb_t * p) { char *key = 0; int rc; role_datum_t *role; role = calloc(1, sizeof(role_datum_t)); if (!role) { rc = -ENOMEM; goto out; } key = strdup(OBJECT_R); if (!key) { rc = -ENOMEM; goto out_free_role; } rc = symtab_insert(p, SYM_ROLES, key, role, (p->policy_type == POLICY_MOD ? SCOPE_REQ : SCOPE_DECL), 1, &role->s.value); if (rc) goto out_free_key; if (role->s.value != OBJECT_R_VAL) { rc = -EINVAL; goto out_free_role; } out: return rc; out_free_key: free(key); out_free_role: free(role); goto out; } ignore_unsigned_overflow_ static inline unsigned long partial_name_hash(unsigned long c, unsigned long prevhash) { return (prevhash + (c << 4) + (c >> 4)) * 11; } static unsigned int filenametr_hash(hashtab_t h, const_hashtab_key_t k) { const filename_trans_key_t *ft = (const filename_trans_key_t *)k; unsigned long hash; unsigned int byte_num; unsigned char focus; hash = ft->ttype ^ ft->tclass; byte_num = 0; while ((focus = ft->name[byte_num++])) hash = partial_name_hash(focus, hash); return hash & (h->size - 1); } static int filenametr_cmp(hashtab_t h __attribute__ ((unused)), const_hashtab_key_t k1, const_hashtab_key_t k2) { const filename_trans_key_t *ft1 = (const filename_trans_key_t *)k1; const filename_trans_key_t *ft2 = (const filename_trans_key_t *)k2; int v; v = spaceship_cmp(ft1->ttype, ft2->ttype); if (v) return v; v = spaceship_cmp(ft1->tclass, ft2->tclass); if (v) return v; return strcmp(ft1->name, ft2->name); } static unsigned int rangetr_hash(hashtab_t h, const_hashtab_key_t k) { const struct range_trans *key = (const struct range_trans *)k; return (key->source_type + (key->target_type << 3) + (key->target_class << 5)) & (h->size - 1); } static int rangetr_cmp(hashtab_t h __attribute__ ((unused)), const_hashtab_key_t k1, const_hashtab_key_t k2) { const struct range_trans *key1 = (const struct range_trans *)k1; const struct range_trans *key2 = (const struct range_trans *)k2; int v; v = spaceship_cmp(key1->source_type, key2->source_type); if (v) return v; v = spaceship_cmp(key1->target_type, key2->target_type); if (v) return v; v = spaceship_cmp(key1->target_class, key2->target_class); return v; } /* * Initialize a policy database structure. */ int policydb_init(policydb_t * p) { int i, rc; memset(p, 0, sizeof(policydb_t)); for (i = 0; i < SYM_NUM; i++) { p->sym_val_to_name[i] = NULL; rc = symtab_init(&p->symtab[i], symtab_sizes[i]); if (rc) goto err; } /* initialize the module stuff */ for (i = 0; i < SYM_NUM; i++) { if (symtab_init(&p->scope[i], symtab_sizes[i])) { goto err; } } if ((p->global = avrule_block_create()) == NULL || (p->global->branch_list = avrule_decl_create(1)) == NULL) { goto err; } p->decl_val_to_struct = NULL; rc = avtab_init(&p->te_avtab); if (rc) goto err; rc = roles_init(p); if (rc) goto err; rc = cond_policydb_init(p); if (rc) goto err; p->filename_trans = hashtab_create(filenametr_hash, filenametr_cmp, (1 << 10)); if (!p->filename_trans) { rc = -ENOMEM; goto err; } p->range_tr = hashtab_create(rangetr_hash, rangetr_cmp, 256); if (!p->range_tr) { rc = -ENOMEM; goto err; } ebitmap_init(&p->policycaps); ebitmap_init(&p->permissive_map); return 0; err: hashtab_destroy(p->filename_trans); hashtab_destroy(p->range_tr); for (i = 0; i < SYM_NUM; i++) { hashtab_destroy(p->symtab[i].table); hashtab_destroy(p->scope[i].table); } avrule_block_list_destroy(p->global); return rc; } int policydb_role_cache(hashtab_key_t key __attribute__ ((unused)), hashtab_datum_t datum, void *arg) { policydb_t *p; role_datum_t *role; role = (role_datum_t *) datum; p = (policydb_t *) arg; ebitmap_destroy(&role->cache); if (type_set_expand(&role->types, &role->cache, p, 1)) { return -1; } return 0; } int policydb_user_cache(hashtab_key_t key __attribute__ ((unused)), hashtab_datum_t datum, void *arg) { policydb_t *p; user_datum_t *user; user = (user_datum_t *) datum; p = (policydb_t *) arg; ebitmap_destroy(&user->cache); if (role_set_expand(&user->roles, &user->cache, p, NULL, NULL)) { return -1; } /* we do not expand user's MLS info in kernel policies because the * semantic representation is not present and we do not expand user's * MLS info in module policies because all of the necessary mls * information is not present */ if (p->policy_type != POLICY_KERN && p->policy_type != POLICY_MOD) { mls_range_destroy(&user->exp_range); if (mls_semantic_range_expand(&user->range, &user->exp_range, p, NULL)) { return -1; } mls_level_destroy(&user->exp_dfltlevel); if (mls_semantic_level_expand(&user->dfltlevel, &user->exp_dfltlevel, p, NULL)) { return -1; } } return 0; } /* * The following *_index functions are used to * define the val_to_name and val_to_struct arrays * in a policy database structure. The val_to_name * arrays are used when converting security context * structures into string representations. The * val_to_struct arrays are used when the attributes * of a class, role, or user are needed. */ static int common_index(hashtab_key_t key, hashtab_datum_t datum, void *datap) { policydb_t *p; common_datum_t *comdatum; comdatum = (common_datum_t *) datum; p = (policydb_t *) datap; if (!value_isvalid(comdatum->s.value, p->p_commons.nprim)) return -EINVAL; if (p->p_common_val_to_name[comdatum->s.value - 1] != NULL) return -EINVAL; p->p_common_val_to_name[comdatum->s.value - 1] = (char *)key; return 0; } static int class_index(hashtab_key_t key, hashtab_datum_t datum, void *datap) { policydb_t *p; class_datum_t *cladatum; cladatum = (class_datum_t *) datum; p = (policydb_t *) datap; if (!value_isvalid(cladatum->s.value, p->p_classes.nprim)) return -EINVAL; if (p->p_class_val_to_name[cladatum->s.value - 1] != NULL) return -EINVAL; p->p_class_val_to_name[cladatum->s.value - 1] = (char *)key; p->class_val_to_struct[cladatum->s.value - 1] = cladatum; return 0; } static int role_index(hashtab_key_t key, hashtab_datum_t datum, void *datap) { policydb_t *p; role_datum_t *role; role = (role_datum_t *) datum; p = (policydb_t *) datap; if (!value_isvalid(role->s.value, p->p_roles.nprim)) return -EINVAL; if (p->p_role_val_to_name[role->s.value - 1] != NULL) return -EINVAL; p->p_role_val_to_name[role->s.value - 1] = (char *)key; p->role_val_to_struct[role->s.value - 1] = role; return 0; } static int type_index(hashtab_key_t key, hashtab_datum_t datum, void *datap) { policydb_t *p; type_datum_t *typdatum; typdatum = (type_datum_t *) datum; p = (policydb_t *) datap; if (typdatum->primary) { if (!value_isvalid(typdatum->s.value, p->p_types.nprim)) return -EINVAL; if (p->p_type_val_to_name[typdatum->s.value - 1] != NULL) return -EINVAL; p->p_type_val_to_name[typdatum->s.value - 1] = (char *)key; p->type_val_to_struct[typdatum->s.value - 1] = typdatum; } return 0; } static int user_index(hashtab_key_t key, hashtab_datum_t datum, void *datap) { policydb_t *p; user_datum_t *usrdatum; usrdatum = (user_datum_t *) datum; p = (policydb_t *) datap; if (!value_isvalid(usrdatum->s.value, p->p_users.nprim)) return -EINVAL; if (p->p_user_val_to_name[usrdatum->s.value - 1] != NULL) return -EINVAL; p->p_user_val_to_name[usrdatum->s.value - 1] = (char *)key; p->user_val_to_struct[usrdatum->s.value - 1] = usrdatum; return 0; } static int sens_index(hashtab_key_t key, hashtab_datum_t datum, void *datap) { policydb_t *p; level_datum_t *levdatum; levdatum = (level_datum_t *) datum; p = (policydb_t *) datap; if (!levdatum->isalias) { if (!value_isvalid(levdatum->level->sens, p->p_levels.nprim)) return -EINVAL; if (p->p_sens_val_to_name[levdatum->level->sens - 1] != NULL) return -EINVAL; p->p_sens_val_to_name[levdatum->level->sens - 1] = (char *)key; } return 0; } static int cat_index(hashtab_key_t key, hashtab_datum_t datum, void *datap) { policydb_t *p; cat_datum_t *catdatum; catdatum = (cat_datum_t *) datum; p = (policydb_t *) datap; if (!catdatum->isalias) { if (!value_isvalid(catdatum->s.value, p->p_cats.nprim)) return -EINVAL; if (p->p_cat_val_to_name[catdatum->s.value - 1] != NULL) return -EINVAL; p->p_cat_val_to_name[catdatum->s.value - 1] = (char *)key; } return 0; } static int (*const index_f[SYM_NUM]) (hashtab_key_t key, hashtab_datum_t datum, void *datap) = { common_index, class_index, role_index, type_index, user_index, cond_index_bool, sens_index, cat_index,}; /* * Define the common val_to_name array and the class * val_to_name and val_to_struct arrays in a policy * database structure. */ int policydb_index_classes(policydb_t * p) { free(p->p_common_val_to_name); p->p_common_val_to_name = (char **) calloc(p->p_commons.nprim, sizeof(char *)); if (!p->p_common_val_to_name) return -1; if (hashtab_map(p->p_commons.table, common_index, p)) return -1; free(p->class_val_to_struct); p->class_val_to_struct = (class_datum_t **) calloc(p->p_classes.nprim, sizeof(class_datum_t *)); if (!p->class_val_to_struct) return -1; free(p->p_class_val_to_name); p->p_class_val_to_name = (char **) calloc(p->p_classes.nprim, sizeof(char *)); if (!p->p_class_val_to_name) return -1; if (hashtab_map(p->p_classes.table, class_index, p)) return -1; return 0; } int policydb_index_bools(policydb_t * p) { if (cond_init_bool_indexes(p) == -1) return -1; p->p_bool_val_to_name = (char **) calloc(p->p_bools.nprim, sizeof(char *)); if (!p->p_bool_val_to_name) return -1; if (hashtab_map(p->p_bools.table, cond_index_bool, p)) return -1; return 0; } static int policydb_index_decls(sepol_handle_t * handle, policydb_t * p) { avrule_block_t *curblock; avrule_decl_t *decl; unsigned int num_decls = 0; free(p->decl_val_to_struct); for (curblock = p->global; curblock != NULL; curblock = curblock->next) { for (decl = curblock->branch_list; decl != NULL; decl = decl->next) { num_decls++; } } p->decl_val_to_struct = calloc(num_decls, sizeof(*(p->decl_val_to_struct))); if (!p->decl_val_to_struct) { return -1; } for (curblock = p->global; curblock != NULL; curblock = curblock->next) { for (decl = curblock->branch_list; decl != NULL; decl = decl->next) { if (!value_isvalid(decl->decl_id, num_decls)) { ERR(handle, "invalid decl ID %u", decl->decl_id); return -1; } if (p->decl_val_to_struct[decl->decl_id - 1] != NULL) { ERR(handle, "duplicated decl ID %u", decl->decl_id); return -1; } p->decl_val_to_struct[decl->decl_id - 1] = decl; } } return 0; } /* * Define the other val_to_name and val_to_struct arrays * in a policy database structure. */ int policydb_index_others(sepol_handle_t * handle, policydb_t * p, unsigned verbose) { int i; if (verbose) { INFO(handle, "security: %d users, %d roles, %d types, %d bools", p->p_users.nprim, p->p_roles.nprim, p->p_types.nprim, p->p_bools.nprim); if (p->mls) INFO(handle, "security: %d sens, %d cats", p->p_levels.nprim, p->p_cats.nprim); INFO(handle, "security: %d classes, %d rules, %d cond rules", p->p_classes.nprim, p->te_avtab.nel, p->te_cond_avtab.nel); } #if 0 avtab_hash_eval(&p->te_avtab, "rules"); for (i = 0; i < SYM_NUM; i++) hashtab_hash_eval(p->symtab[i].table, symtab_name[i]); #endif free(p->role_val_to_struct); p->role_val_to_struct = (role_datum_t **) calloc(p->p_roles.nprim, sizeof(role_datum_t *)); if (!p->role_val_to_struct) return -1; free(p->user_val_to_struct); p->user_val_to_struct = (user_datum_t **) calloc(p->p_users.nprim, sizeof(user_datum_t *)); if (!p->user_val_to_struct) return -1; free(p->type_val_to_struct); p->type_val_to_struct = (type_datum_t **) calloc(p->p_types.nprim, sizeof(type_datum_t *)); if (!p->type_val_to_struct) return -1; if (cond_init_bool_indexes(p)) return -1; for (i = SYM_ROLES; i < SYM_NUM; i++) { free(p->sym_val_to_name[i]); p->sym_val_to_name[i] = NULL; if (p->symtab[i].nprim) { p->sym_val_to_name[i] = (char **) calloc(p->symtab[i].nprim, sizeof(char *)); if (!p->sym_val_to_name[i]) return -1; if (hashtab_map(p->symtab[i].table, index_f[i], p)) return -1; } } /* This pre-expands the roles and users for context validity checking */ if (hashtab_map(p->p_roles.table, policydb_role_cache, p)) return -1; if (hashtab_map(p->p_users.table, policydb_user_cache, p)) return -1; return 0; } /* * The following *_destroy functions are used to * free any memory allocated for each kind of * symbol data in the policy database. */ static int perm_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p __attribute__ ((unused))) { if (key) free(key); free(datum); return 0; } static int common_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p __attribute__ ((unused))) { common_datum_t *comdatum; if (key) free(key); comdatum = (common_datum_t *) datum; (void)hashtab_map(comdatum->permissions.table, perm_destroy, 0); hashtab_destroy(comdatum->permissions.table); free(datum); return 0; } static int class_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p __attribute__ ((unused))) { class_datum_t *cladatum; constraint_node_t *constraint, *ctemp; if (key) free(key); cladatum = (class_datum_t *) datum; if (cladatum == NULL) { return 0; } (void)hashtab_map(cladatum->permissions.table, perm_destroy, 0); hashtab_destroy(cladatum->permissions.table); constraint = cladatum->constraints; while (constraint) { constraint_expr_destroy(constraint->expr); ctemp = constraint; constraint = constraint->next; free(ctemp); } constraint = cladatum->validatetrans; while (constraint) { constraint_expr_destroy(constraint->expr); ctemp = constraint; constraint = constraint->next; free(ctemp); } if (cladatum->comkey) free(cladatum->comkey); free(datum); return 0; } static int role_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p __attribute__ ((unused))) { free(key); role_datum_destroy((role_datum_t *) datum); free(datum); return 0; } static int type_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p __attribute__ ((unused))) { free(key); type_datum_destroy((type_datum_t *) datum); free(datum); return 0; } static int user_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p __attribute__ ((unused))) { free(key); user_datum_destroy((user_datum_t *) datum); free(datum); return 0; } static int sens_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p __attribute__ ((unused))) { level_datum_t *levdatum; if (key) free(key); levdatum = (level_datum_t *) datum; if (!levdatum->isalias || !levdatum->notdefined) { mls_level_destroy(levdatum->level); free(levdatum->level); } level_datum_destroy(levdatum); free(levdatum); return 0; } static int cat_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p __attribute__ ((unused))) { if (key) free(key); cat_datum_destroy((cat_datum_t *) datum); free(datum); return 0; } static int (*const destroy_f[SYM_NUM]) (hashtab_key_t key, hashtab_datum_t datum, void *datap) = { common_destroy, class_destroy, role_destroy, type_destroy, user_destroy, cond_destroy_bool, sens_destroy, cat_destroy,}; static int filenametr_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p __attribute__ ((unused))) { filename_trans_key_t *ft = (filename_trans_key_t *)key; filename_trans_datum_t *fd = datum, *next; free(ft->name); free(key); do { next = fd->next; ebitmap_destroy(&fd->stypes); free(fd); fd = next; } while (fd); return 0; } static int range_tr_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p __attribute__ ((unused))) { struct mls_range *rt = (struct mls_range *)datum; free(key); ebitmap_destroy(&rt->level[0].cat); ebitmap_destroy(&rt->level[1].cat); free(datum); return 0; } static void ocontext_selinux_free(ocontext_t **ocontexts) { ocontext_t *c, *ctmp; int i; for (i = 0; i < OCON_NUM; i++) { c = ocontexts[i]; while (c) { ctmp = c; c = c->next; context_destroy(&ctmp->context[0]); context_destroy(&ctmp->context[1]); if (i == OCON_ISID || i == OCON_FS || i == OCON_NETIF || i == OCON_FSUSE) free(ctmp->u.name); else if (i == OCON_IBENDPORT) free(ctmp->u.ibendport.dev_name); free(ctmp); } } } static void ocontext_xen_free(ocontext_t **ocontexts) { ocontext_t *c, *ctmp; int i; for (i = 0; i < OCON_NUM; i++) { c = ocontexts[i]; while (c) { ctmp = c; c = c->next; context_destroy(&ctmp->context[0]); context_destroy(&ctmp->context[1]); if (i == OCON_ISID || i == OCON_XEN_DEVICETREE) free(ctmp->u.name); free(ctmp); } } } /* * Free any memory allocated by a policy database structure. */ void policydb_destroy(policydb_t * p) { ocontext_t *c, *ctmp; genfs_t *g, *gtmp; unsigned int i; role_allow_t *ra, *lra = NULL; role_trans_t *tr, *ltr = NULL; if (!p) return; ebitmap_destroy(&p->policycaps); ebitmap_destroy(&p->permissive_map); symtabs_destroy(p->symtab); for (i = 0; i < SYM_NUM; i++) { if (p->sym_val_to_name[i]) free(p->sym_val_to_name[i]); } if (p->class_val_to_struct) free(p->class_val_to_struct); if (p->role_val_to_struct) free(p->role_val_to_struct); if (p->user_val_to_struct) free(p->user_val_to_struct); if (p->type_val_to_struct) free(p->type_val_to_struct); free(p->decl_val_to_struct); for (i = 0; i < SYM_NUM; i++) { (void)hashtab_map(p->scope[i].table, scope_destroy, 0); hashtab_destroy(p->scope[i].table); } avrule_block_list_destroy(p->global); free(p->name); free(p->version); avtab_destroy(&p->te_avtab); if (p->target_platform == SEPOL_TARGET_SELINUX) ocontext_selinux_free(p->ocontexts); else if (p->target_platform == SEPOL_TARGET_XEN) ocontext_xen_free(p->ocontexts); g = p->genfs; while (g) { free(g->fstype); c = g->head; while (c) { ctmp = c; c = c->next; context_destroy(&ctmp->context[0]); free(ctmp->u.name); free(ctmp); } gtmp = g; g = g->next; free(gtmp); } cond_policydb_destroy(p); for (tr = p->role_tr; tr; tr = tr->next) { if (ltr) free(ltr); ltr = tr; } if (ltr) free(ltr); for (ra = p->role_allow; ra; ra = ra->next) { if (lra) free(lra); lra = ra; } if (lra) free(lra); hashtab_map(p->filename_trans, filenametr_destroy, NULL); hashtab_destroy(p->filename_trans); hashtab_map(p->range_tr, range_tr_destroy, NULL); hashtab_destroy(p->range_tr); if (p->type_attr_map) { for (i = 0; i < p->p_types.nprim; i++) { ebitmap_destroy(&p->type_attr_map[i]); } free(p->type_attr_map); } if (p->attr_type_map) { for (i = 0; i < p->p_types.nprim; i++) { ebitmap_destroy(&p->attr_type_map[i]); } free(p->attr_type_map); } return; } void symtabs_destroy(symtab_t * symtab) { int i; for (i = 0; i < SYM_NUM; i++) { (void)hashtab_map(symtab[i].table, destroy_f[i], 0); hashtab_destroy(symtab[i].table); } } int scope_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p __attribute__ ((unused))) { scope_datum_t *cur = (scope_datum_t *) datum; free(key); if (cur != NULL) { free(cur->decl_ids); } free(cur); return 0; } /* * Load the initial SIDs specified in a policy database * structure into a SID table. */ int policydb_load_isids(policydb_t * p, sidtab_t * s) { ocontext_t *head, *c; if (sepol_sidtab_init(s)) { ERR(NULL, "out of memory on SID table init"); return -1; } head = p->ocontexts[OCON_ISID]; for (c = head; c; c = c->next) { if (sepol_sidtab_insert(s, c->sid[0], &c->context[0])) { ERR(NULL, "unable to load initial SID %s", c->u.name); return -1; } } return 0; } /* Declare a symbol for a certain avrule_block context. Insert it * into a symbol table for a policy. This function will handle * inserting the appropriate scope information in addition to * inserting the symbol into the hash table. * * arguments: * policydb_t *pol module policy to modify * uint32_t sym the symbol table for insertion (SYM_*) * hashtab_key_t key the key for the symbol - not cloned * hashtab_datum_t data the data for the symbol - not cloned * scope scope of this symbol, either SCOPE_REQ or SCOPE_DECL * avrule_decl_id identifier for this symbol's encapsulating declaration * value (out) assigned value to the symbol (if value is not NULL) * * returns: * 0 success * 1 success, but symbol already existed as a requirement * (datum was not inserted and needs to be free()d) * -1 general error * -2 scope conflicted * -ENOMEM memory error * error codes from hashtab_insert */ int symtab_insert(policydb_t * pol, uint32_t sym, hashtab_key_t key, hashtab_datum_t datum, uint32_t scope, uint32_t avrule_decl_id, uint32_t * value) { int rc, retval = 0; unsigned int i; scope_datum_t *scope_datum; /* check if the symbol is already there. multiple * declarations of non-roles/non-users are illegal, but * multiple requires are allowed. */ /* FIX ME - the failures after the hashtab_insert will leave * the policy in a inconsistent state. */ rc = hashtab_insert(pol->symtab[sym].table, key, datum); if (rc == SEPOL_OK) { /* if no value is passed in the symbol is not primary * (i.e. aliases) */ if (value) *value = ++pol->symtab[sym].nprim; } else if (rc == SEPOL_EEXIST) { retval = 1; /* symbol not added -- need to free() later */ } else { return rc; } /* get existing scope information; if there is not one then * create it */ scope_datum = (scope_datum_t *) hashtab_search(pol->scope[sym].table, key); if (scope_datum == NULL) { hashtab_key_t key2 = strdup((char *)key); if (!key2) return -ENOMEM; if ((scope_datum = malloc(sizeof(*scope_datum))) == NULL) { free(key2); return -ENOMEM; } scope_datum->scope = scope; scope_datum->decl_ids = NULL; scope_datum->decl_ids_len = 0; if ((rc = hashtab_insert(pol->scope[sym].table, key2, scope_datum)) != 0) { free(key2); free(scope_datum); return rc; } } else if (scope_datum->scope == SCOPE_DECL && scope == SCOPE_DECL) { /* disallow multiple declarations for non-roles/users */ if (sym != SYM_ROLES && sym != SYM_USERS) { return -2; } /* Further confine that a role attribute can't have the same * name as another regular role, and a role attribute can't * be declared more than once. */ if (sym == SYM_ROLES) { role_datum_t *base_role; role_datum_t *cur_role = (role_datum_t *)datum; base_role = (role_datum_t *) hashtab_search(pol->symtab[sym].table, key); assert(base_role != NULL); if (!((base_role->flavor == ROLE_ROLE) && (cur_role->flavor == ROLE_ROLE))) { /* Only regular roles are allowed to have * multiple declarations. */ return -2; } } } else if (scope_datum->scope == SCOPE_REQ && scope == SCOPE_DECL) { scope_datum->scope = SCOPE_DECL; } /* search through the pre-existing list to avoid adding duplicates */ for (i = 0; i < scope_datum->decl_ids_len; i++) { if (scope_datum->decl_ids[i] == avrule_decl_id) { /* already there, so don't modify its scope */ return retval; } } if (add_i_to_a(avrule_decl_id, &scope_datum->decl_ids_len, &scope_datum->decl_ids) == -1) { return -ENOMEM; } if (scope_datum->scope == SCOPE_DECL && scope == SCOPE_REQ) { /* Need to keep the decl at the end of the list */ uint32_t len, tmp; len = scope_datum->decl_ids_len; if (len < 2) { /* This should be impossible here */ return -1; } tmp = scope_datum->decl_ids[len-2]; scope_datum->decl_ids[len-2] = scope_datum->decl_ids[len-1]; scope_datum->decl_ids[len-1] = tmp; } return retval; } static int type_set_or(type_set_t * dst, const type_set_t * a, const type_set_t * b) { type_set_init(dst); if (ebitmap_or(&dst->types, &a->types, &b->types)) { return -1; } if (ebitmap_or(&dst->negset, &a->negset, &b->negset)) { return -1; } dst->flags |= a->flags; dst->flags |= b->flags; return 0; } int type_set_cpy(type_set_t * dst, const type_set_t * src) { type_set_init(dst); dst->flags = src->flags; if (ebitmap_cpy(&dst->types, &src->types)) return -1; if (ebitmap_cpy(&dst->negset, &src->negset)) return -1; return 0; } int type_set_or_eq(type_set_t * dst, const type_set_t * other) { int ret; type_set_t tmp; if (type_set_or(&tmp, dst, other)) return -1; type_set_destroy(dst); ret = type_set_cpy(dst, &tmp); type_set_destroy(&tmp); return ret; } /***********************************************************************/ /* everything below is for policy reads */ /* The following are read functions for module structures */ static int role_set_read(role_set_t * r, struct policy_file *fp) { uint32_t buf[1]; int rc; if (ebitmap_read(&r->roles, fp)) return -1; rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) return -1; r->flags = le32_to_cpu(buf[0]); return 0; } static int type_set_read(type_set_t * t, struct policy_file *fp) { uint32_t buf[1]; int rc; if (ebitmap_read(&t->types, fp)) return -1; if (ebitmap_read(&t->negset, fp)) return -1; rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) return -1; t->flags = le32_to_cpu(buf[0]); return 0; } /* * Read a MLS range structure from a policydb binary * representation file. */ static int mls_read_range_helper(mls_range_t * r, struct policy_file *fp) { uint32_t buf[2], items; int rc; rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) goto out; items = le32_to_cpu(buf[0]); if (items > ARRAY_SIZE(buf)) { ERR(fp->handle, "range overflow"); rc = -EINVAL; goto out; } rc = next_entry(buf, fp, sizeof(uint32_t) * items); if (rc < 0) { ERR(fp->handle, "truncated range"); goto out; } r->level[0].sens = le32_to_cpu(buf[0]); if (items > 1) r->level[1].sens = le32_to_cpu(buf[1]); else r->level[1].sens = r->level[0].sens; rc = ebitmap_read(&r->level[0].cat, fp); if (rc) { ERR(fp->handle, "error reading low categories"); goto out; } if (items > 1) { rc = ebitmap_read(&r->level[1].cat, fp); if (rc) { ERR(fp->handle, "error reading high categories"); goto bad_high; } } else { rc = ebitmap_cpy(&r->level[1].cat, &r->level[0].cat); if (rc) { ERR(fp->handle, "out of memory"); goto bad_high; } } rc = 0; out: return rc; bad_high: ebitmap_destroy(&r->level[0].cat); goto out; } /* * Read a semantic MLS level structure from a policydb binary * representation file. */ static int mls_read_semantic_level_helper(mls_semantic_level_t * l, struct policy_file *fp) { uint32_t buf[2], ncat; unsigned int i; mls_semantic_cat_t *cat; int rc; mls_semantic_level_init(l); rc = next_entry(buf, fp, sizeof(uint32_t) * 2); if (rc < 0) { ERR(fp->handle, "truncated level"); goto bad; } l->sens = le32_to_cpu(buf[0]); ncat = le32_to_cpu(buf[1]); for (i = 0; i < ncat; i++) { cat = (mls_semantic_cat_t *) malloc(sizeof(mls_semantic_cat_t)); if (!cat) { ERR(fp->handle, "out of memory"); goto bad; } mls_semantic_cat_init(cat); cat->next = l->cat; l->cat = cat; rc = next_entry(buf, fp, sizeof(uint32_t) * 2); if (rc < 0) { ERR(fp->handle, "error reading level categories"); goto bad; } cat->low = le32_to_cpu(buf[0]); cat->high = le32_to_cpu(buf[1]); } return 0; bad: return -EINVAL; } /* * Read a semantic MLS range structure from a policydb binary * representation file. */ static int mls_read_semantic_range_helper(mls_semantic_range_t * r, struct policy_file *fp) { int rc; rc = mls_read_semantic_level_helper(&r->level[0], fp); if (rc) return rc; rc = mls_read_semantic_level_helper(&r->level[1], fp); return rc; } static int mls_level_to_semantic(mls_level_t * l, mls_semantic_level_t * sl) { unsigned int i; ebitmap_node_t *cnode; mls_semantic_cat_t *open_cat = NULL; mls_semantic_level_init(sl); sl->sens = l->sens; ebitmap_for_each_bit(&l->cat, cnode, i) { if (ebitmap_node_get_bit(cnode, i)) { if (open_cat) continue; open_cat = (mls_semantic_cat_t *) malloc(sizeof(mls_semantic_cat_t)); if (!open_cat) return -1; mls_semantic_cat_init(open_cat); open_cat->low = i + 1; open_cat->next = sl->cat; sl->cat = open_cat; } else { if (!open_cat) continue; open_cat->high = i; open_cat = NULL; } } if (open_cat) open_cat->high = i; return 0; } static int mls_range_to_semantic(mls_range_t * r, mls_semantic_range_t * sr) { if (mls_level_to_semantic(&r->level[0], &sr->level[0])) return -1; if (mls_level_to_semantic(&r->level[1], &sr->level[1])) return -1; return 0; } /* * Read and validate a security context structure * from a policydb binary representation file. */ static int context_read_and_validate(context_struct_t * c, policydb_t * p, struct policy_file *fp) { uint32_t buf[3]; int rc; rc = next_entry(buf, fp, sizeof(uint32_t) * 3); if (rc < 0) { ERR(fp->handle, "context truncated"); return -1; } c->user = le32_to_cpu(buf[0]); c->role = le32_to_cpu(buf[1]); c->type = le32_to_cpu(buf[2]); if ((p->policy_type == POLICY_KERN && p->policyvers >= POLICYDB_VERSION_MLS) || (p->policy_type == POLICY_BASE && p->policyvers >= MOD_POLICYDB_VERSION_MLS)) { if (mls_read_range_helper(&c->range, fp)) { ERR(fp->handle, "error reading MLS range " "of context"); return -1; } } if (!policydb_context_isvalid(p, c)) { ERR(fp->handle, "invalid security context"); context_destroy(c); return -1; } return 0; } /* * The following *_read functions are used to * read the symbol data from a policy database * binary representation file. */ static int perm_read(policydb_t * p __attribute__ ((unused)), hashtab_t h, struct policy_file *fp, uint32_t nprim) { char *key = 0; perm_datum_t *perdatum; uint32_t buf[2]; size_t len; int rc; perdatum = calloc(1, sizeof(perm_datum_t)); if (!perdatum) return -1; rc = next_entry(buf, fp, sizeof(uint32_t) * 2); if (rc < 0) goto bad; len = le32_to_cpu(buf[0]); if(str_read(&key, fp, len)) goto bad; perdatum->s.value = le32_to_cpu(buf[1]); if (!value_isvalid(perdatum->s.value, nprim)) goto bad; if (hashtab_insert(h, key, perdatum)) goto bad; return 0; bad: perm_destroy(key, perdatum, NULL); return -1; } static int common_read(policydb_t * p, hashtab_t h, struct policy_file *fp) { char *key = 0; common_datum_t *comdatum; uint32_t buf[4]; size_t len, nel; unsigned int i; int rc; comdatum = calloc(1, sizeof(common_datum_t)); if (!comdatum) return -1; rc = next_entry(buf, fp, sizeof(uint32_t) * 4); if (rc < 0) goto bad; len = le32_to_cpu(buf[0]); rc = str_read(&key, fp, len); if (rc < 0) goto bad; comdatum->s.value = le32_to_cpu(buf[1]); if (symtab_init(&comdatum->permissions, PERM_SYMTAB_SIZE)) goto bad; comdatum->permissions.nprim = le32_to_cpu(buf[2]); if (comdatum->permissions.nprim > PERM_SYMTAB_SIZE) goto bad; nel = le32_to_cpu(buf[3]); for (i = 0; i < nel; i++) { if (perm_read(p, comdatum->permissions.table, fp, comdatum->permissions.nprim)) goto bad; } if (hashtab_insert(h, key, comdatum)) goto bad; return 0; bad: common_destroy(key, comdatum, NULL); return -1; } static int read_cons_helper(policydb_t * p, constraint_node_t ** nodep, unsigned int ncons, int allowxtarget, struct policy_file *fp) { constraint_node_t *c, *lc; constraint_expr_t *e, *le; uint32_t buf[3]; size_t nexpr; unsigned int i, j; int rc, depth; lc = NULL; for (i = 0; i < ncons; i++) { c = calloc(1, sizeof(constraint_node_t)); if (!c) return -1; if (lc) lc->next = c; else *nodep = c; rc = next_entry(buf, fp, (sizeof(uint32_t) * 2)); if (rc < 0) return -1; c->permissions = le32_to_cpu(buf[0]); nexpr = le32_to_cpu(buf[1]); le = NULL; depth = -1; for (j = 0; j < nexpr; j++) { e = malloc(sizeof(constraint_expr_t)); if (!e) return -1; if (constraint_expr_init(e) == -1) { free(e); return -1; } if (le) { le->next = e; } else { c->expr = e; } rc = next_entry(buf, fp, (sizeof(uint32_t) * 3)); if (rc < 0) return -1; e->expr_type = le32_to_cpu(buf[0]); e->attr = le32_to_cpu(buf[1]); e->op = le32_to_cpu(buf[2]); switch (e->expr_type) { case CEXPR_NOT: if (depth < 0) return -1; break; case CEXPR_AND: case CEXPR_OR: if (depth < 1) return -1; depth--; break; case CEXPR_ATTR: if (depth == (CEXPR_MAXDEPTH - 1)) return -1; depth++; break; case CEXPR_NAMES: if (!allowxtarget && (e->attr & CEXPR_XTARGET)) return -1; if (depth == (CEXPR_MAXDEPTH - 1)) return -1; depth++; if (ebitmap_read(&e->names, fp)) return -1; if (p->policy_type != POLICY_KERN && type_set_read(e->type_names, fp)) return -1; else if (p->policy_type == POLICY_KERN && p->policyvers >= POLICYDB_VERSION_CONSTRAINT_NAMES && type_set_read(e->type_names, fp)) return -1; break; default: return -1; } le = e; } if (depth != 0) return -1; lc = c; } return 0; } static int class_read(policydb_t * p, hashtab_t h, struct policy_file *fp) { char *key = 0; class_datum_t *cladatum; uint32_t buf[6]; size_t len, len2, ncons, nel; unsigned int i; int rc; cladatum = (class_datum_t *) calloc(1, sizeof(class_datum_t)); if (!cladatum) return -1; rc = next_entry(buf, fp, sizeof(uint32_t) * 6); if (rc < 0) goto bad; len = le32_to_cpu(buf[0]); rc = str_read(&key, fp, len); if (rc < 0) goto bad; len2 = le32_to_cpu(buf[1]); cladatum->s.value = le32_to_cpu(buf[2]); if (cladatum->s.value > UINT16_MAX) goto bad; if (symtab_init(&cladatum->permissions, PERM_SYMTAB_SIZE)) goto bad; cladatum->permissions.nprim = le32_to_cpu(buf[3]); if (cladatum->permissions.nprim > PERM_SYMTAB_SIZE) goto bad; nel = le32_to_cpu(buf[4]); ncons = le32_to_cpu(buf[5]); if (len2) { rc = str_read(&cladatum->comkey, fp, len2); if (rc < 0) goto bad; cladatum->comdatum = hashtab_search(p->p_commons.table, cladatum->comkey); if (!cladatum->comdatum) { ERR(fp->handle, "unknown common %s", cladatum->comkey); goto bad; } } for (i = 0; i < nel; i++) { if (perm_read(p, cladatum->permissions.table, fp, cladatum->permissions.nprim)) goto bad; } if (read_cons_helper(p, &cladatum->constraints, ncons, 0, fp)) goto bad; if ((p->policy_type == POLICY_KERN && p->policyvers >= POLICYDB_VERSION_VALIDATETRANS) || (p->policy_type == POLICY_BASE && p->policyvers >= MOD_POLICYDB_VERSION_VALIDATETRANS)) { /* grab the validatetrans rules */ rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) goto bad; ncons = le32_to_cpu(buf[0]); if (read_cons_helper(p, &cladatum->validatetrans, ncons, 1, fp)) goto bad; } if ((p->policy_type == POLICY_KERN && p->policyvers >= POLICYDB_VERSION_NEW_OBJECT_DEFAULTS) || (p->policy_type == POLICY_BASE && p->policyvers >= MOD_POLICYDB_VERSION_NEW_OBJECT_DEFAULTS)) { rc = next_entry(buf, fp, sizeof(uint32_t) * 3); if (rc < 0) goto bad; cladatum->default_user = le32_to_cpu(buf[0]); cladatum->default_role = le32_to_cpu(buf[1]); cladatum->default_range = le32_to_cpu(buf[2]); } if ((p->policy_type == POLICY_KERN && p->policyvers >= POLICYDB_VERSION_DEFAULT_TYPE) || (p->policy_type == POLICY_BASE && p->policyvers >= MOD_POLICYDB_VERSION_DEFAULT_TYPE)) { rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) goto bad; cladatum->default_type = le32_to_cpu(buf[0]); } if (hashtab_insert(h, key, cladatum)) goto bad; return 0; bad: class_destroy(key, cladatum, NULL); return -1; } static int role_read(policydb_t * p, hashtab_t h, struct policy_file *fp) { char *key = 0; role_datum_t *role; uint32_t buf[3]; size_t len; int rc, to_read = 2; role = calloc(1, sizeof(role_datum_t)); if (!role) return -1; if (policydb_has_boundary_feature(p)) to_read = 3; rc = next_entry(buf, fp, sizeof(uint32_t) * to_read); if (rc < 0) goto bad; len = le32_to_cpu(buf[0]); rc = str_read(&key, fp, len); if (rc < 0) goto bad; role->s.value = le32_to_cpu(buf[1]); if (policydb_has_boundary_feature(p)) role->bounds = le32_to_cpu(buf[2]); if (ebitmap_read(&role->dominates, fp)) goto bad; if (p->policy_type == POLICY_KERN) { if (ebitmap_read(&role->types.types, fp)) goto bad; } else { if (type_set_read(&role->types, fp)) goto bad; } if (p->policy_type != POLICY_KERN && p->policyvers >= MOD_POLICYDB_VERSION_ROLEATTRIB) { rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) goto bad; role->flavor = le32_to_cpu(buf[0]); if (ebitmap_read(&role->roles, fp)) goto bad; } if (strcmp(key, OBJECT_R) == 0) { if (role->s.value != OBJECT_R_VAL) { ERR(fp->handle, "role %s has wrong value %d", OBJECT_R, role->s.value); role_destroy(key, role, NULL); return -1; } role_destroy(key, role, NULL); return 0; } if (hashtab_insert(h, key, role)) goto bad; return 0; bad: role_destroy(key, role, NULL); return -1; } static int type_read(policydb_t * p, hashtab_t h, struct policy_file *fp) { char *key = 0; type_datum_t *typdatum; uint32_t buf[5]; size_t len; int rc, to_read; int pos = 0; typdatum = calloc(1, sizeof(type_datum_t)); if (!typdatum) return -1; if (policydb_has_boundary_feature(p)) { if (p->policy_type != POLICY_KERN && p->policyvers >= MOD_POLICYDB_VERSION_BOUNDARY_ALIAS) to_read = 5; else to_read = 4; } else if (p->policy_type == POLICY_KERN) to_read = 3; else if (p->policyvers >= MOD_POLICYDB_VERSION_PERMISSIVE) to_read = 5; else to_read = 4; rc = next_entry(buf, fp, sizeof(uint32_t) * to_read); if (rc < 0) goto bad; len = le32_to_cpu(buf[pos]); typdatum->s.value = le32_to_cpu(buf[++pos]); if (policydb_has_boundary_feature(p)) { uint32_t properties; if (p->policy_type != POLICY_KERN && p->policyvers >= MOD_POLICYDB_VERSION_BOUNDARY_ALIAS) { typdatum->primary = le32_to_cpu(buf[++pos]); properties = le32_to_cpu(buf[++pos]); } else { properties = le32_to_cpu(buf[++pos]); if (properties & TYPEDATUM_PROPERTY_PRIMARY) typdatum->primary = 1; } if (properties & TYPEDATUM_PROPERTY_ATTRIBUTE) typdatum->flavor = TYPE_ATTRIB; if (properties & TYPEDATUM_PROPERTY_ALIAS && p->policy_type != POLICY_KERN) typdatum->flavor = TYPE_ALIAS; if (properties & TYPEDATUM_PROPERTY_PERMISSIVE && p->policy_type != POLICY_KERN) typdatum->flags |= TYPE_FLAGS_PERMISSIVE; typdatum->bounds = le32_to_cpu(buf[++pos]); } else { typdatum->primary = le32_to_cpu(buf[++pos]); if (p->policy_type != POLICY_KERN) { typdatum->flavor = le32_to_cpu(buf[++pos]); if (p->policyvers >= MOD_POLICYDB_VERSION_PERMISSIVE) typdatum->flags = le32_to_cpu(buf[++pos]); } } if (p->policy_type != POLICY_KERN) { if (ebitmap_read(&typdatum->types, fp)) goto bad; } rc = str_read(&key, fp, len); if (rc < 0) goto bad; if (hashtab_insert(h, key, typdatum)) goto bad; return 0; bad: type_destroy(key, typdatum, NULL); return -1; } static int role_trans_read(policydb_t *p, struct policy_file *fp) { role_trans_t **t = &p->role_tr; unsigned int i; uint32_t buf[3], nel; role_trans_t *tr, *ltr; int rc; int new_roletr = (p->policy_type == POLICY_KERN && p->policyvers >= POLICYDB_VERSION_ROLETRANS); rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) return -1; nel = le32_to_cpu(buf[0]); ltr = NULL; for (i = 0; i < nel; i++) { tr = calloc(1, sizeof(struct role_trans)); if (!tr) { return -1; } if (ltr) { ltr->next = tr; } else { *t = tr; } rc = next_entry(buf, fp, sizeof(uint32_t) * 3); if (rc < 0) return -1; tr->role = le32_to_cpu(buf[0]); tr->type = le32_to_cpu(buf[1]); tr->new_role = le32_to_cpu(buf[2]); if (new_roletr) { rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) return -1; tr->tclass = le32_to_cpu(buf[0]); } else tr->tclass = p->process_class; ltr = tr; } return 0; } static int role_allow_read(role_allow_t ** r, struct policy_file *fp) { unsigned int i; uint32_t buf[2], nel; role_allow_t *ra, *lra; int rc; rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) return -1; nel = le32_to_cpu(buf[0]); lra = NULL; for (i = 0; i < nel; i++) { ra = calloc(1, sizeof(struct role_allow)); if (!ra) { return -1; } if (lra) { lra->next = ra; } else { *r = ra; } rc = next_entry(buf, fp, sizeof(uint32_t) * 2); if (rc < 0) return -1; ra->role = le32_to_cpu(buf[0]); ra->new_role = le32_to_cpu(buf[1]); lra = ra; } return 0; } int policydb_filetrans_insert(policydb_t *p, uint32_t stype, uint32_t ttype, uint32_t tclass, const char *name, char **name_alloc, uint32_t otype, uint32_t *present_otype) { filename_trans_key_t *ft, key; filename_trans_datum_t *datum, *last; key.ttype = ttype; key.tclass = tclass; key.name = (char *)name; last = NULL; datum = hashtab_search(p->filename_trans, (hashtab_key_t)&key); while (datum) { if (ebitmap_get_bit(&datum->stypes, stype - 1)) { if (present_otype) *present_otype = datum->otype; return SEPOL_EEXIST; } if (datum->otype == otype) break; last = datum; datum = datum->next; } if (!datum) { datum = malloc(sizeof(*datum)); if (!datum) return SEPOL_ENOMEM; ebitmap_init(&datum->stypes); datum->otype = otype; datum->next = NULL; if (last) { last->next = datum; } else { char *name_dup; if (name_alloc) { name_dup = *name_alloc; *name_alloc = NULL; } else { name_dup = strdup(name); if (!name_dup) { free(datum); return SEPOL_ENOMEM; } } ft = malloc(sizeof(*ft)); if (!ft) { free(name_dup); free(datum); return SEPOL_ENOMEM; } ft->ttype = ttype; ft->tclass = tclass; ft->name = name_dup; if (hashtab_insert(p->filename_trans, (hashtab_key_t)ft, (hashtab_datum_t)datum)) { free(name_dup); free(datum); free(ft); return SEPOL_ENOMEM; } } } p->filename_trans_count++; return ebitmap_set_bit(&datum->stypes, stype - 1, 1); } static int filename_trans_read_one_compat(policydb_t *p, struct policy_file *fp) { uint32_t buf[4], len, stype, ttype, tclass, otype; char *name = NULL; int rc; rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) return -1; len = le32_to_cpu(buf[0]); rc = str_read(&name, fp, len); if (rc < 0) goto err; rc = next_entry(buf, fp, sizeof(uint32_t) * 4); if (rc < 0) goto err; stype = le32_to_cpu(buf[0]); if (stype == 0) goto err; ttype = le32_to_cpu(buf[1]); tclass = le32_to_cpu(buf[2]); otype = le32_to_cpu(buf[3]); rc = policydb_filetrans_insert(p, stype, ttype, tclass, name, &name, otype, NULL); if (rc) { if (rc != SEPOL_EEXIST) goto err; /* * Some old policies were wrongly generated with * duplicate filename transition rules. For backward * compatibility, do not reject such policies, just * ignore the duplicate. */ } free(name); return 0; err: free(name); return -1; } static int filename_trans_check_datum(filename_trans_datum_t *datum) { ebitmap_t stypes, otypes; int rc = -1; ebitmap_init(&stypes); ebitmap_init(&otypes); while (datum) { if (ebitmap_get_bit(&otypes, datum->otype)) goto out; if (ebitmap_set_bit(&otypes, datum->otype, 1)) goto out; if (ebitmap_match_any(&stypes, &datum->stypes)) goto out; if (ebitmap_union(&stypes, &datum->stypes)) goto out; datum = datum->next; } rc = 0; out: ebitmap_destroy(&stypes); ebitmap_destroy(&otypes); return rc; } static int filename_trans_read_one(policydb_t *p, struct policy_file *fp) { filename_trans_key_t *ft = NULL; filename_trans_datum_t **dst, *datum, *first = NULL; unsigned int i; uint32_t buf[3], len, ttype, tclass, ndatum; char *name = NULL; int rc; rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) return -1; len = le32_to_cpu(buf[0]); rc = str_read(&name, fp, len); if (rc < 0) goto err; rc = next_entry(buf, fp, sizeof(uint32_t) * 3); if (rc < 0) goto err; ttype = le32_to_cpu(buf[0]); tclass = le32_to_cpu(buf[1]); ndatum = le32_to_cpu(buf[2]); if (ndatum == 0) goto err; dst = &first; for (i = 0; i < ndatum; i++) { datum = malloc(sizeof(*datum)); if (!datum) goto err; datum->next = NULL; *dst = datum; /* ebitmap_read() will at least init the bitmap */ rc = ebitmap_read(&datum->stypes, fp); if (rc < 0) goto err; rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) goto err; datum->otype = le32_to_cpu(buf[0]); p->filename_trans_count += ebitmap_cardinality(&datum->stypes); dst = &datum->next; } if (ndatum > 1 && filename_trans_check_datum(first)) goto err; ft = malloc(sizeof(*ft)); if (!ft) goto err; ft->ttype = ttype; ft->tclass = tclass; ft->name = name; rc = hashtab_insert(p->filename_trans, (hashtab_key_t)ft, (hashtab_datum_t)first); if (rc) goto err; return 0; err: free(ft); free(name); while (first) { datum = first; first = first->next; ebitmap_destroy(&datum->stypes); free(datum); } return -1; } static int filename_trans_read(policydb_t *p, struct policy_file *fp) { unsigned int i; uint32_t buf[1], nel; int rc; rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) return -1; nel = le32_to_cpu(buf[0]); if (p->policyvers < POLICYDB_VERSION_COMP_FTRANS) { for (i = 0; i < nel; i++) { rc = filename_trans_read_one_compat(p, fp); if (rc < 0) return -1; } } else { for (i = 0; i < nel; i++) { rc = filename_trans_read_one(p, fp); if (rc < 0) return -1; } } return 0; } static int ocontext_read_xen(const struct policydb_compat_info *info, policydb_t *p, struct policy_file *fp) { unsigned int i, j; size_t nel, len; ocontext_t *l, *c; uint32_t buf[8]; int rc; for (i = 0; i < info->ocon_num; i++) { rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) return -1; nel = le32_to_cpu(buf[0]); l = NULL; for (j = 0; j < nel; j++) { c = calloc(1, sizeof(ocontext_t)); if (!c) return -1; if (l) l->next = c; else p->ocontexts[i] = c; l = c; switch (i) { case OCON_XEN_ISID: rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) return -1; c->sid[0] = le32_to_cpu(buf[0]); if (is_saturated(c->sid[0])) return -1; if (context_read_and_validate (&c->context[0], p, fp)) return -1; break; case OCON_XEN_PIRQ: rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) return -1; c->u.pirq = le32_to_cpu(buf[0]); if (context_read_and_validate (&c->context[0], p, fp)) return -1; break; case OCON_XEN_IOPORT: rc = next_entry(buf, fp, sizeof(uint32_t) * 2); if (rc < 0) return -1; c->u.ioport.low_ioport = le32_to_cpu(buf[0]); c->u.ioport.high_ioport = le32_to_cpu(buf[1]); if (context_read_and_validate (&c->context[0], p, fp)) return -1; break; case OCON_XEN_IOMEM: if (p->policyvers >= POLICYDB_VERSION_XEN_DEVICETREE) { uint64_t b64[2]; rc = next_entry(b64, fp, sizeof(uint64_t) * 2); if (rc < 0) return -1; c->u.iomem.low_iomem = le64_to_cpu(b64[0]); c->u.iomem.high_iomem = le64_to_cpu(b64[1]); } else { rc = next_entry(buf, fp, sizeof(uint32_t) * 2); if (rc < 0) return -1; c->u.iomem.low_iomem = le32_to_cpu(buf[0]); c->u.iomem.high_iomem = le32_to_cpu(buf[1]); } if (context_read_and_validate (&c->context[0], p, fp)) return -1; break; case OCON_XEN_PCIDEVICE: rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) return -1; c->u.device = le32_to_cpu(buf[0]); if (context_read_and_validate (&c->context[0], p, fp)) return -1; break; case OCON_XEN_DEVICETREE: rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) return -1; len = le32_to_cpu(buf[0]); rc = str_read(&c->u.name, fp, len); if (rc < 0) return -1; if (context_read_and_validate (&c->context[0], p, fp)) return -1; break; default: /* should never get here */ ERR(fp->handle, "Unknown Xen ocontext"); return -1; } } } return 0; } static int ocontext_read_selinux(const struct policydb_compat_info *info, policydb_t * p, struct policy_file *fp) { unsigned int i, j; size_t nel, len; ocontext_t *l, *c; uint32_t buf[8]; int rc; for (i = 0; i < info->ocon_num; i++) { rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) return -1; nel = le32_to_cpu(buf[0]); l = NULL; for (j = 0; j < nel; j++) { c = calloc(1, sizeof(ocontext_t)); if (!c) { return -1; } if (l) { l->next = c; } else { p->ocontexts[i] = c; } l = c; switch (i) { case OCON_ISID: rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) return -1; c->sid[0] = le32_to_cpu(buf[0]); if (is_saturated(c->sid[0])) return -1; if (context_read_and_validate (&c->context[0], p, fp)) return -1; break; case OCON_FS: case OCON_NETIF: rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) return -1; len = le32_to_cpu(buf[0]); if (len > 63) return -1; rc = str_read(&c->u.name, fp, len); if (rc < 0) return -1; if (context_read_and_validate (&c->context[0], p, fp)) return -1; if (context_read_and_validate (&c->context[1], p, fp)) return -1; break; case OCON_IBPKEY: { uint32_t pkey_lo, pkey_hi; rc = next_entry(buf, fp, sizeof(uint32_t) * 4); if (rc < 0) return -1; pkey_lo = le32_to_cpu(buf[2]); pkey_hi = le32_to_cpu(buf[3]); if (pkey_lo > UINT16_MAX || pkey_hi > UINT16_MAX) return -1; c->u.ibpkey.low_pkey = pkey_lo; c->u.ibpkey.high_pkey = pkey_hi; /* we want c->u.ibpkey.subnet_prefix in network * (big-endian) order, just memcpy it */ memcpy(&c->u.ibpkey.subnet_prefix, buf, sizeof(c->u.ibpkey.subnet_prefix)); if (context_read_and_validate (&c->context[0], p, fp)) return -1; break; } case OCON_IBENDPORT: { uint32_t port; rc = next_entry(buf, fp, sizeof(uint32_t) * 2); if (rc < 0) return -1; len = le32_to_cpu(buf[0]); if (len == 0 || len > IB_DEVICE_NAME_MAX - 1) return -1; port = le32_to_cpu(buf[1]); if (port > UINT8_MAX || port == 0) return -1; rc = str_read(&c->u.ibendport.dev_name, fp, len); if (rc < 0) return -1; c->u.ibendport.port = port; if (context_read_and_validate (&c->context[0], p, fp)) return -1; break; } case OCON_PORT: rc = next_entry(buf, fp, sizeof(uint32_t) * 3); if (rc < 0) return -1; c->u.port.protocol = le32_to_cpu(buf[0]); c->u.port.low_port = le32_to_cpu(buf[1]); c->u.port.high_port = le32_to_cpu(buf[2]); if (context_read_and_validate (&c->context[0], p, fp)) return -1; break; case OCON_NODE: rc = next_entry(buf, fp, sizeof(uint32_t) * 2); if (rc < 0) return -1; c->u.node.addr = buf[0]; /* network order */ c->u.node.mask = buf[1]; /* network order */ if (context_read_and_validate (&c->context[0], p, fp)) return -1; break; case OCON_FSUSE: rc = next_entry(buf, fp, sizeof(uint32_t) * 2); if (rc < 0) return -1; c->v.behavior = le32_to_cpu(buf[0]); len = le32_to_cpu(buf[1]); rc = str_read(&c->u.name, fp, len); if (rc < 0) return -1; if (context_read_and_validate (&c->context[0], p, fp)) return -1; break; case OCON_NODE6:{ int k; rc = next_entry(buf, fp, sizeof(uint32_t) * 8); if (rc < 0) return -1; for (k = 0; k < 4; k++) /* network order */ c->u.node6.addr[k] = buf[k]; for (k = 0; k < 4; k++) /* network order */ c->u.node6.mask[k] = buf[k + 4]; if (context_read_and_validate (&c->context[0], p, fp)) return -1; break; } default:{ ERR(fp->handle, "Unknown SELinux ocontext"); return -1; } } } } return 0; } static int ocontext_read(const struct policydb_compat_info *info, policydb_t *p, struct policy_file *fp) { int rc = -1; switch (p->target_platform) { case SEPOL_TARGET_SELINUX: rc = ocontext_read_selinux(info, p, fp); break; case SEPOL_TARGET_XEN: rc = ocontext_read_xen(info, p, fp); break; default: ERR(fp->handle, "Unknown target"); } return rc; } static int genfs_read(policydb_t * p, struct policy_file *fp) { uint32_t buf[1]; size_t nel, nel2, len, len2; genfs_t *genfs_p, *newgenfs, *genfs; size_t i, j; ocontext_t *l, *c, *newc = NULL; int rc; rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) goto bad; nel = le32_to_cpu(buf[0]); genfs_p = NULL; for (i = 0; i < nel; i++) { rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) goto bad; len = le32_to_cpu(buf[0]); newgenfs = calloc(1, sizeof(genfs_t)); if (!newgenfs) goto bad; rc = str_read(&newgenfs->fstype, fp, len); if (rc < 0) { free(newgenfs->fstype); free(newgenfs); goto bad; } for (genfs_p = NULL, genfs = p->genfs; genfs; genfs_p = genfs, genfs = genfs->next) { if (strcmp(newgenfs->fstype, genfs->fstype) == 0) { ERR(fp->handle, "dup genfs fstype %s", newgenfs->fstype); free(newgenfs->fstype); free(newgenfs); goto bad; } if (strcmp(newgenfs->fstype, genfs->fstype) < 0) break; } newgenfs->next = genfs; if (genfs_p) genfs_p->next = newgenfs; else p->genfs = newgenfs; rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) goto bad; nel2 = le32_to_cpu(buf[0]); for (j = 0; j < nel2; j++) { newc = calloc(1, sizeof(ocontext_t)); if (!newc) { goto bad; } rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) goto bad; len = le32_to_cpu(buf[0]); rc = str_read(&newc->u.name, fp, len); if (rc < 0) goto bad; rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) goto bad; newc->v.sclass = le32_to_cpu(buf[0]); if (context_read_and_validate(&newc->context[0], p, fp)) goto bad; for (l = NULL, c = newgenfs->head; c; l = c, c = c->next) { if (!strcmp(newc->u.name, c->u.name) && (!c->v.sclass || !newc->v.sclass || newc->v.sclass == c->v.sclass)) { ERR(fp->handle, "dup genfs entry " "(%s,%s)", newgenfs->fstype, c->u.name); goto bad; } len = strlen(newc->u.name); len2 = strlen(c->u.name); if (len > len2) break; } newc->next = c; if (l) l->next = newc; else newgenfs->head = newc; /* clear newc after a new owner has the pointer */ newc = NULL; } } return 0; bad: if (newc) { context_destroy(&newc->context[0]); context_destroy(&newc->context[1]); free(newc->u.name); free(newc); } return -1; } /* * Read a MLS level structure from a policydb binary * representation file. */ static int mls_read_level(mls_level_t * lp, struct policy_file *fp) { uint32_t buf[1]; int rc; mls_level_init(lp); rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) { ERR(fp->handle, "truncated level"); goto bad; } lp->sens = le32_to_cpu(buf[0]); if (ebitmap_read(&lp->cat, fp)) { ERR(fp->handle, "error reading level categories"); goto bad; } return 0; bad: return -EINVAL; } static int user_read(policydb_t * p, hashtab_t h, struct policy_file *fp) { char *key = 0; user_datum_t *usrdatum; uint32_t buf[3]; size_t len; int rc, to_read = 2; usrdatum = calloc(1, sizeof(user_datum_t)); if (!usrdatum) return -1; if (policydb_has_boundary_feature(p)) to_read = 3; rc = next_entry(buf, fp, sizeof(uint32_t) * to_read); if (rc < 0) goto bad; len = le32_to_cpu(buf[0]); rc = str_read(&key, fp, len); if (rc < 0) goto bad; usrdatum->s.value = le32_to_cpu(buf[1]); if (policydb_has_boundary_feature(p)) usrdatum->bounds = le32_to_cpu(buf[2]); if (p->policy_type == POLICY_KERN) { if (ebitmap_read(&usrdatum->roles.roles, fp)) goto bad; } else { if (role_set_read(&usrdatum->roles, fp)) goto bad; } /* users were not allowed in mls modules before version * MOD_POLICYDB_VERSION_MLS_USERS, but they could have been * required - the mls fields will be empty. user declarations in * non-mls modules will also have empty mls fields */ if ((p->policy_type == POLICY_KERN && p->policyvers >= POLICYDB_VERSION_MLS) || (p->policy_type == POLICY_MOD && p->policyvers >= MOD_POLICYDB_VERSION_MLS && p->policyvers < MOD_POLICYDB_VERSION_MLS_USERS) || (p->policy_type == POLICY_BASE && p->policyvers >= MOD_POLICYDB_VERSION_MLS && p->policyvers < MOD_POLICYDB_VERSION_MLS_USERS)) { if (mls_read_range_helper(&usrdatum->exp_range, fp)) goto bad; if (mls_read_level(&usrdatum->exp_dfltlevel, fp)) goto bad; if (p->policy_type != POLICY_KERN) { if (mls_range_to_semantic(&usrdatum->exp_range, &usrdatum->range)) goto bad; if (mls_level_to_semantic(&usrdatum->exp_dfltlevel, &usrdatum->dfltlevel)) goto bad; } } else if ((p->policy_type == POLICY_MOD && p->policyvers >= MOD_POLICYDB_VERSION_MLS_USERS) || (p->policy_type == POLICY_BASE && p->policyvers >= MOD_POLICYDB_VERSION_MLS_USERS)) { if (mls_read_semantic_range_helper(&usrdatum->range, fp)) goto bad; if (mls_read_semantic_level_helper(&usrdatum->dfltlevel, fp)) goto bad; } if (hashtab_insert(h, key, usrdatum)) goto bad; return 0; bad: user_destroy(key, usrdatum, NULL); return -1; } static int sens_read(policydb_t * p __attribute__ ((unused)), hashtab_t h, struct policy_file *fp) { char *key = 0; level_datum_t *levdatum; uint32_t buf[2], len; int rc; levdatum = malloc(sizeof(level_datum_t)); if (!levdatum) return -1; level_datum_init(levdatum); rc = next_entry(buf, fp, (sizeof(uint32_t) * 2)); if (rc < 0) goto bad; len = le32_to_cpu(buf[0]); rc = str_read(&key, fp, len); if (rc < 0) goto bad; levdatum->isalias = le32_to_cpu(buf[1]); levdatum->level = malloc(sizeof(mls_level_t)); if (!levdatum->level || mls_read_level(levdatum->level, fp)) goto bad; if (hashtab_insert(h, key, levdatum)) goto bad; return 0; bad: sens_destroy(key, levdatum, NULL); return -1; } static int cat_read(policydb_t * p __attribute__ ((unused)), hashtab_t h, struct policy_file *fp) { char *key = 0; cat_datum_t *catdatum; uint32_t buf[3], len; int rc; catdatum = malloc(sizeof(cat_datum_t)); if (!catdatum) return -1; cat_datum_init(catdatum); rc = next_entry(buf, fp, (sizeof(uint32_t) * 3)); if (rc < 0) goto bad; len = le32_to_cpu(buf[0]); rc = str_read(&key, fp, len); if (rc < 0) goto bad; catdatum->s.value = le32_to_cpu(buf[1]); catdatum->isalias = le32_to_cpu(buf[2]); if (hashtab_insert(h, key, catdatum)) goto bad; return 0; bad: cat_destroy(key, catdatum, NULL); return -1; } static int (*const read_f[SYM_NUM]) (policydb_t * p, hashtab_t h, struct policy_file * fp) = { common_read, class_read, role_read, type_read, user_read, cond_read_bool, sens_read, cat_read,}; /************** module reading functions below **************/ static avrule_t *avrule_read(policydb_t * p, struct policy_file *fp) { unsigned int i; uint32_t buf[2], len; class_perm_node_t *cur, *tail = NULL; avrule_t *avrule; int rc; avrule = (avrule_t *) malloc(sizeof(avrule_t)); if (!avrule) return NULL; avrule_init(avrule); rc = next_entry(buf, fp, sizeof(uint32_t) * 2); if (rc < 0) goto bad; avrule->specified = le32_to_cpu(buf[0]); avrule->flags = le32_to_cpu(buf[1]); if (type_set_read(&avrule->stypes, fp)) goto bad; if (type_set_read(&avrule->ttypes, fp)) goto bad; rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) goto bad; len = le32_to_cpu(buf[0]); for (i = 0; i < len; i++) { cur = (class_perm_node_t *) malloc(sizeof(class_perm_node_t)); if (!cur) goto bad; class_perm_node_init(cur); rc = next_entry(buf, fp, sizeof(uint32_t) * 2); if (rc < 0) { free(cur); goto bad; } cur->tclass = le32_to_cpu(buf[0]); cur->data = le32_to_cpu(buf[1]); if (!tail) { avrule->perms = cur; } else { tail->next = cur; } tail = cur; } if (avrule->specified & AVRULE_XPERMS) { uint8_t buf8; size_t nel = ARRAY_SIZE(avrule->xperms->perms); uint32_t buf32[nel]; if (p->policyvers < MOD_POLICYDB_VERSION_XPERMS_IOCTL) { ERR(fp->handle, "module policy version %u does not support ioctl" " extended permissions rules and one was specified", p->policyvers); goto bad; } if (p->target_platform != SEPOL_TARGET_SELINUX) { ERR(fp->handle, "Target platform %s does not support ioctl" " extended permissions rules and one was specified", policydb_target_strings[p->target_platform]); goto bad; } avrule->xperms = calloc(1, sizeof(*avrule->xperms)); if (!avrule->xperms) goto bad; rc = next_entry(&buf8, fp, sizeof(uint8_t)); if (rc < 0) { ERR(fp->handle, "truncated entry"); goto bad; } avrule->xperms->specified = buf8; rc = next_entry(&buf8, fp, sizeof(uint8_t)); if (rc < 0) { ERR(fp->handle, "truncated entry"); goto bad; } avrule->xperms->driver = buf8; rc = next_entry(buf32, fp, sizeof(uint32_t)*nel); if (rc < 0) { ERR(fp->handle, "truncated entry"); goto bad; } for (i = 0; i < nel; i++) avrule->xperms->perms[i] = le32_to_cpu(buf32[i]); } return avrule; bad: if (avrule) { avrule_destroy(avrule); free(avrule); } return NULL; } static int range_read(policydb_t * p, struct policy_file *fp) { uint32_t buf[2], nel; range_trans_t *rt = NULL; struct mls_range *r = NULL; range_trans_rule_t *rtr = NULL, *lrtr = NULL; unsigned int i; int new_rangetr = (p->policy_type == POLICY_KERN && p->policyvers >= POLICYDB_VERSION_RANGETRANS); int rc; rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) return -1; nel = le32_to_cpu(buf[0]); for (i = 0; i < nel; i++) { rt = calloc(1, sizeof(range_trans_t)); if (!rt) return -1; rc = next_entry(buf, fp, (sizeof(uint32_t) * 2)); if (rc < 0) goto err; rt->source_type = le32_to_cpu(buf[0]); if (!value_isvalid(rt->source_type, p->p_types.nprim)) goto err; rt->target_type = le32_to_cpu(buf[1]); if (!value_isvalid(rt->target_type, p->p_types.nprim)) goto err; if (new_rangetr) { rc = next_entry(buf, fp, (sizeof(uint32_t))); if (rc < 0) goto err; rt->target_class = le32_to_cpu(buf[0]); } else rt->target_class = p->process_class; if (!value_isvalid(rt->target_class, p->p_classes.nprim)) goto err; r = calloc(1, sizeof(*r)); if (!r) goto err; if (mls_read_range_helper(r, fp)) goto err; if (p->policy_type == POLICY_KERN) { rc = hashtab_insert(p->range_tr, (hashtab_key_t)rt, r); if (rc) goto err; rt = NULL; r = NULL; continue; } /* Module policy: convert to range_trans_rule and discard. */ rtr = malloc(sizeof(range_trans_rule_t)); if (!rtr) goto err; range_trans_rule_init(rtr); if (ebitmap_set_bit(&rtr->stypes.types, rt->source_type - 1, 1)) goto err; if (ebitmap_set_bit(&rtr->ttypes.types, rt->target_type - 1, 1)) goto err; if (ebitmap_set_bit(&rtr->tclasses, rt->target_class - 1, 1)) goto err; if (mls_range_to_semantic(r, &rtr->trange)) goto err; if (lrtr) lrtr->next = rtr; else p->global->enabled->range_tr_rules = rtr; free(rt); rt = NULL; free(r); r = NULL; lrtr = rtr; } return 0; err: free(rt); if (r) { mls_range_destroy(r); free(r); } if (rtr) { range_trans_rule_destroy(rtr); free(rtr); } return -1; } int avrule_read_list(policydb_t * p, avrule_t ** avrules, struct policy_file *fp) { unsigned int i; avrule_t *cur, *tail; uint32_t buf[1], len; int rc; *avrules = tail = NULL; rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) { return -1; } len = le32_to_cpu(buf[0]); for (i = 0; i < len; i++) { cur = avrule_read(p, fp); if (!cur) { return -1; } if (!tail) { *avrules = cur; } else { tail->next = cur; } tail = cur; } return 0; } static int role_trans_rule_read(policydb_t *p, role_trans_rule_t ** r, struct policy_file *fp) { uint32_t buf[1], nel; unsigned int i; role_trans_rule_t *tr, *ltr; int rc; rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) return -1; nel = le32_to_cpu(buf[0]); ltr = NULL; for (i = 0; i < nel; i++) { tr = malloc(sizeof(role_trans_rule_t)); if (!tr) { return -1; } role_trans_rule_init(tr); if (ltr) { ltr->next = tr; } else { *r = tr; } if (role_set_read(&tr->roles, fp)) return -1; if (type_set_read(&tr->types, fp)) return -1; if (p->policyvers >= MOD_POLICYDB_VERSION_ROLETRANS) { if (ebitmap_read(&tr->classes, fp)) return -1; } else { if (!p->process_class) return -1; if (ebitmap_set_bit(&tr->classes, p->process_class - 1, 1)) return -1; } rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) return -1; tr->new_role = le32_to_cpu(buf[0]); ltr = tr; } return 0; } static int role_allow_rule_read(role_allow_rule_t ** r, struct policy_file *fp) { unsigned int i; uint32_t buf[1], nel; role_allow_rule_t *ra, *lra; int rc; rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) return -1; nel = le32_to_cpu(buf[0]); lra = NULL; for (i = 0; i < nel; i++) { ra = malloc(sizeof(role_allow_rule_t)); if (!ra) { return -1; } role_allow_rule_init(ra); if (lra) { lra->next = ra; } else { *r = ra; } if (role_set_read(&ra->roles, fp)) return -1; if (role_set_read(&ra->new_roles, fp)) return -1; lra = ra; } return 0; } static int filename_trans_rule_read(policydb_t *p, filename_trans_rule_t **r, struct policy_file *fp) { uint32_t buf[3], nel, i, len; unsigned int entries; filename_trans_rule_t *ftr, *lftr; int rc; rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) return -1; nel = le32_to_cpu(buf[0]); lftr = NULL; for (i = 0; i < nel; i++) { ftr = malloc(sizeof(*ftr)); if (!ftr) return -1; filename_trans_rule_init(ftr); if (lftr) lftr->next = ftr; else *r = ftr; lftr = ftr; rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) return -1; len = le32_to_cpu(buf[0]); rc = str_read(&ftr->name, fp, len); if (rc < 0) return -1; if (type_set_read(&ftr->stypes, fp)) return -1; if (type_set_read(&ftr->ttypes, fp)) return -1; if (p->policyvers >= MOD_POLICYDB_VERSION_SELF_TYPETRANS) entries = 3; else entries = 2; rc = next_entry(buf, fp, sizeof(uint32_t) * entries); if (rc < 0) return -1; ftr->tclass = le32_to_cpu(buf[0]); ftr->otype = le32_to_cpu(buf[1]); if (p->policyvers >= MOD_POLICYDB_VERSION_SELF_TYPETRANS) ftr->flags = le32_to_cpu(buf[2]); } return 0; } static int range_trans_rule_read(range_trans_rule_t ** r, struct policy_file *fp) { uint32_t buf[1], nel; unsigned int i; range_trans_rule_t *rt, *lrt = NULL; int rc; rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) return -1; nel = le32_to_cpu(buf[0]); for (i = 0; i < nel; i++) { rt = malloc(sizeof(range_trans_rule_t)); if (!rt) { return -1; } range_trans_rule_init(rt); if (lrt) lrt->next = rt; else *r = rt; if (type_set_read(&rt->stypes, fp)) return -1; if (type_set_read(&rt->ttypes, fp)) return -1; if (ebitmap_read(&rt->tclasses, fp)) return -1; if (mls_read_semantic_range_helper(&rt->trange, fp)) return -1; lrt = rt; } return 0; } static int scope_index_read(scope_index_t * scope_index, unsigned int num_scope_syms, struct policy_file *fp) { unsigned int i; uint32_t buf[1]; int rc; for (i = 0; i < num_scope_syms; i++) { if (ebitmap_read(scope_index->scope + i, fp) < 0) { return -1; } } rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) return -1; scope_index->class_perms_len = le32_to_cpu(buf[0]); if (is_saturated(scope_index->class_perms_len) || exceeds_available_bytes(fp, scope_index->class_perms_len, sizeof(uint32_t) * 3)) return -1; if (scope_index->class_perms_len == 0) { scope_index->class_perms_map = NULL; return 0; } if ((scope_index->class_perms_map = calloc(scope_index->class_perms_len, sizeof(*scope_index->class_perms_map))) == NULL) { return -1; } for (i = 0; i < scope_index->class_perms_len; i++) { if (ebitmap_read(scope_index->class_perms_map + i, fp) < 0) { return -1; } } return 0; } static int avrule_decl_read(policydb_t * p, avrule_decl_t * decl, unsigned int num_scope_syms, struct policy_file *fp) { uint32_t buf[2], nprim, nel; unsigned int i, j; int rc; rc = next_entry(buf, fp, sizeof(uint32_t) * 2); if (rc < 0) return -1; decl->decl_id = le32_to_cpu(buf[0]); decl->enabled = le32_to_cpu(buf[1]); if (cond_read_list(p, &decl->cond_list, fp) == -1 || avrule_read_list(p, &decl->avrules, fp) == -1 || role_trans_rule_read(p, &decl->role_tr_rules, fp) == -1 || role_allow_rule_read(&decl->role_allow_rules, fp) == -1) { return -1; } if (p->policyvers >= MOD_POLICYDB_VERSION_FILENAME_TRANS && filename_trans_rule_read(p, &decl->filename_trans_rules, fp)) return -1; if (p->policyvers >= MOD_POLICYDB_VERSION_RANGETRANS && range_trans_rule_read(&decl->range_tr_rules, fp) == -1) { return -1; } if (scope_index_read(&decl->required, num_scope_syms, fp) == -1 || scope_index_read(&decl->declared, num_scope_syms, fp) == -1) { return -1; } for (i = 0; i < num_scope_syms; i++) { rc = next_entry(buf, fp, sizeof(uint32_t) * 2); if (rc < 0) return -1; nprim = le32_to_cpu(buf[0]); if (is_saturated(nprim)) return -1; nel = le32_to_cpu(buf[1]); for (j = 0; j < nel; j++) { if (read_f[i] (p, decl->symtab[i].table, fp)) { return -1; } } decl->symtab[i].nprim = nprim; } return 0; } static int avrule_block_read(policydb_t * p, avrule_block_t ** block, unsigned int num_scope_syms, struct policy_file *fp) { avrule_block_t *last_block = NULL, *curblock; uint32_t buf[1], num_blocks, nel; int rc; assert(*block == NULL); rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) return -1; num_blocks = le32_to_cpu(buf[0]); nel = num_blocks; while (num_blocks > 0) { avrule_decl_t *last_decl = NULL, *curdecl; uint32_t num_decls; if ((curblock = calloc(1, sizeof(*curblock))) == NULL) { return -1; } rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) { free(curblock); return -1; } /* if this is the first block its non-optional, else its optional */ if (num_blocks != nel) curblock->flags |= AVRULE_OPTIONAL; num_decls = le32_to_cpu(buf[0]); while (num_decls > 0) { if ((curdecl = avrule_decl_create(0)) == NULL) { avrule_block_destroy(curblock); return -1; } if (avrule_decl_read(p, curdecl, num_scope_syms, fp) == -1) { avrule_decl_destroy(curdecl); avrule_block_destroy(curblock); return -1; } if (curdecl->enabled) { if (curblock->enabled != NULL) { /* probably a corrupt file */ avrule_decl_destroy(curdecl); avrule_block_destroy(curblock); return -1; } curblock->enabled = curdecl; } /* one must be careful to reconstruct the * decl chain in its correct order */ if (curblock->branch_list == NULL) { curblock->branch_list = curdecl; } else { assert(last_decl); last_decl->next = curdecl; } last_decl = curdecl; num_decls--; } if (*block == NULL) { *block = curblock; } else { assert(last_block); last_block->next = curblock; } last_block = curblock; num_blocks--; } return 0; } static int scope_read(policydb_t * p, int symnum, struct policy_file *fp) { scope_datum_t *scope = NULL; uint32_t buf[2]; char *key = NULL; size_t key_len; unsigned int i; hashtab_t h = p->scope[symnum].table; int rc; rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) goto cleanup; key_len = le32_to_cpu(buf[0]); rc = str_read(&key, fp, key_len); if (rc < 0) goto cleanup; /* ensure that there already exists a symbol with this key */ if (hashtab_search(p->symtab[symnum].table, key) == NULL) { goto cleanup; } if ((scope = calloc(1, sizeof(*scope))) == NULL) { goto cleanup; } rc = next_entry(buf, fp, sizeof(uint32_t) * 2); if (rc < 0) goto cleanup; scope->scope = le32_to_cpu(buf[0]); scope->decl_ids_len = le32_to_cpu(buf[1]); if (zero_or_saturated(scope->decl_ids_len) || exceeds_available_bytes(fp, scope->decl_ids_len, sizeof(uint32_t))) { ERR(fp->handle, "invalid scope with no declaration"); goto cleanup; } if ((scope->decl_ids = calloc(scope->decl_ids_len, sizeof(uint32_t))) == NULL) { goto cleanup; } rc = next_entry(scope->decl_ids, fp, sizeof(uint32_t) * scope->decl_ids_len); if (rc < 0) goto cleanup; for (i = 0; i < scope->decl_ids_len; i++) { scope->decl_ids[i] = le32_to_cpu(scope->decl_ids[i]); } if (strcmp(key, "object_r") == 0 && h == p->p_roles_scope.table) { /* object_r was already added to this table in roles_init() */ scope_destroy(key, scope, NULL); } else { if (hashtab_insert(h, key, scope)) { goto cleanup; } } return 0; cleanup: scope_destroy(key, scope, NULL); return -1; } static sepol_security_class_t policydb_string_to_security_class( struct policydb *policydb, const char *class_name) { class_datum_t *tclass_datum; tclass_datum = hashtab_search(policydb->p_classes.table, class_name); if (!tclass_datum) return 0; return tclass_datum->s.value; } static sepol_access_vector_t policydb_string_to_av_perm( struct policydb *policydb, sepol_security_class_t tclass, const char *perm_name) { class_datum_t *tclass_datum; perm_datum_t *perm_datum; if (!tclass || tclass > policydb->p_classes.nprim) return 0; tclass_datum = policydb->class_val_to_struct[tclass - 1]; perm_datum = (perm_datum_t *) hashtab_search(tclass_datum->permissions.table, perm_name); if (perm_datum != NULL) return UINT32_C(1) << (perm_datum->s.value - 1); if (tclass_datum->comdatum == NULL) return 0; perm_datum = (perm_datum_t *) hashtab_search(tclass_datum->comdatum->permissions.table, perm_name); if (perm_datum != NULL) return UINT32_C(1) << (perm_datum->s.value - 1); return 0; } /* * Read the configuration data from a policy database binary * representation file into a policy database structure. */ int policydb_read(policydb_t * p, struct policy_file *fp, unsigned verbose) { unsigned int i, j, r_policyvers; uint32_t buf[5], nprim; size_t len, nel; char *policydb_str; const struct policydb_compat_info *info; unsigned int policy_type, bufindex; ebitmap_node_t *tnode; int rc; /* Read the magic number and string length. */ rc = next_entry(buf, fp, sizeof(uint32_t) * 2); if (rc < 0) return POLICYDB_ERROR; for (i = 0; i < 2; i++) buf[i] = le32_to_cpu(buf[i]); if (buf[0] == POLICYDB_MAGIC) { policy_type = POLICY_KERN; } else if (buf[0] == POLICYDB_MOD_MAGIC) { policy_type = POLICY_MOD; } else { ERR(fp->handle, "policydb magic number %#08x does not " "match expected magic number %#08x or %#08x", buf[0], POLICYDB_MAGIC, POLICYDB_MOD_MAGIC); return POLICYDB_ERROR; } len = buf[1]; if (len == 0 || len > POLICYDB_STRING_MAX_LENGTH) { ERR(fp->handle, "policydb string length %s ", len ? "too long" : "zero"); return POLICYDB_ERROR; } policydb_str = malloc(len + 1); if (!policydb_str) { ERR(fp->handle, "unable to allocate memory for policydb " "string of length %zu", len); return POLICYDB_ERROR; } rc = next_entry(policydb_str, fp, len); if (rc < 0) { ERR(fp->handle, "truncated policydb string identifier"); free(policydb_str); return POLICYDB_ERROR; } policydb_str[len] = 0; if (policy_type == POLICY_KERN) { for (i = 0; i < POLICYDB_TARGET_SZ; i++) { if ((strcmp(policydb_str, policydb_target_strings[i]) == 0)) { policydb_set_target_platform(p, i); break; } } if (i == POLICYDB_TARGET_SZ) { ERR(fp->handle, "cannot find a valid target for policy " "string %s", policydb_str); free(policydb_str); return POLICYDB_ERROR; } } else { if (strcmp(policydb_str, POLICYDB_MOD_STRING)) { ERR(fp->handle, "invalid string identifier %s", policydb_str); free(policydb_str); return POLICYDB_ERROR; } } /* Done with policydb_str. */ free(policydb_str); policydb_str = NULL; /* Read the version, config, and table sizes (and policy type if it's a module). */ if (policy_type == POLICY_KERN) nel = 4; else nel = 5; rc = next_entry(buf, fp, sizeof(uint32_t) * nel); if (rc < 0) return POLICYDB_ERROR; for (i = 0; i < nel; i++) buf[i] = le32_to_cpu(buf[i]); bufindex = 0; if (policy_type == POLICY_MOD) { /* We know it's a module but not whether it's a base module or regular binary policy module. buf[0] tells us which. */ policy_type = buf[bufindex]; if (policy_type != POLICY_MOD && policy_type != POLICY_BASE) { ERR(fp->handle, "unknown module type: %#08x", policy_type); return POLICYDB_ERROR; } bufindex++; } r_policyvers = buf[bufindex]; if (policy_type == POLICY_KERN) { if (r_policyvers < POLICYDB_VERSION_MIN || r_policyvers > POLICYDB_VERSION_MAX) { ERR(fp->handle, "policydb version %d does not match " "my version range %d-%d", buf[bufindex], POLICYDB_VERSION_MIN, POLICYDB_VERSION_MAX); return POLICYDB_ERROR; } } else if (policy_type == POLICY_BASE || policy_type == POLICY_MOD) { if (r_policyvers < MOD_POLICYDB_VERSION_MIN || r_policyvers > MOD_POLICYDB_VERSION_MAX) { ERR(fp->handle, "policydb module version %d does " "not match my version range %d-%d", buf[bufindex], MOD_POLICYDB_VERSION_MIN, MOD_POLICYDB_VERSION_MAX); return POLICYDB_ERROR; } } else { assert(0); } bufindex++; /* Set the policy type and version from the read values. */ p->policy_type = policy_type; p->policyvers = r_policyvers; if (buf[bufindex] & POLICYDB_CONFIG_MLS) { p->mls = 1; } else { p->mls = 0; } p->handle_unknown = buf[bufindex] & POLICYDB_CONFIG_UNKNOWN_MASK; bufindex++; info = policydb_lookup_compat(r_policyvers, policy_type, p->target_platform); if (!info) { ERR(fp->handle, "unable to find policy compat info " "for version %d", r_policyvers); goto bad; } if (buf[bufindex] != info->sym_num || buf[bufindex + 1] != info->ocon_num) { ERR(fp->handle, "policydb table sizes (%d,%d) do not " "match mine (%d,%d)", buf[bufindex], buf[bufindex + 1], info->sym_num, info->ocon_num); goto bad; } if (p->policy_type == POLICY_MOD) { /* Get the module name and version */ if ((rc = next_entry(buf, fp, sizeof(uint32_t))) < 0) { goto bad; } len = le32_to_cpu(buf[0]); rc = str_read(&p->name, fp, len); if (rc < 0) goto bad; if ((rc = next_entry(buf, fp, sizeof(uint32_t))) < 0) { goto bad; } len = le32_to_cpu(buf[0]); rc = str_read(&p->version, fp, len); if (rc < 0) goto bad; } if ((p->policyvers >= POLICYDB_VERSION_POLCAP && p->policy_type == POLICY_KERN) || (p->policyvers >= MOD_POLICYDB_VERSION_POLCAP && p->policy_type == POLICY_BASE) || (p->policyvers >= MOD_POLICYDB_VERSION_POLCAP && p->policy_type == POLICY_MOD)) { if (ebitmap_read(&p->policycaps, fp)) goto bad; } if (p->policyvers >= POLICYDB_VERSION_PERMISSIVE && p->policy_type == POLICY_KERN) { if (ebitmap_read(&p->permissive_map, fp)) goto bad; } for (i = 0; i < info->sym_num; i++) { rc = next_entry(buf, fp, sizeof(uint32_t) * 2); if (rc < 0) goto bad; nprim = le32_to_cpu(buf[0]); if (is_saturated(nprim) || exceeds_available_bytes(fp, nprim, sizeof(uint32_t) * 3)) goto bad; nel = le32_to_cpu(buf[1]); if (nel && !nprim) { ERR(fp->handle, "unexpected items in symbol table with no symbol"); goto bad; } for (j = 0; j < nel; j++) { if (read_f[i] (p, p->symtab[i].table, fp)) goto bad; } p->symtab[i].nprim = nprim; } switch (p->target_platform) { case SEPOL_TARGET_SELINUX: p->process_class = policydb_string_to_security_class(p, "process"); p->dir_class = policydb_string_to_security_class(p, "dir"); break; case SEPOL_TARGET_XEN: p->process_class = policydb_string_to_security_class(p, "domain"); break; default: break; } if (policy_type == POLICY_KERN) { if (avtab_read(&p->te_avtab, fp, r_policyvers)) goto bad; if (r_policyvers >= POLICYDB_VERSION_BOOL) if (cond_read_list(p, &p->cond_list, fp)) goto bad; if (role_trans_read(p, fp)) goto bad; if (role_allow_read(&p->role_allow, fp)) goto bad; if (r_policyvers >= POLICYDB_VERSION_FILENAME_TRANS && filename_trans_read(p, fp)) goto bad; } else { /* first read the AV rule blocks, then the scope tables */ avrule_block_destroy(p->global); p->global = NULL; if (avrule_block_read(p, &p->global, info->sym_num, fp) == -1) { goto bad; } if (p->global == NULL) { ERR(fp->handle, "no avrule block in policy"); goto bad; } for (i = 0; i < info->sym_num; i++) { if ((rc = next_entry(buf, fp, sizeof(uint32_t))) < 0) { goto bad; } nel = le32_to_cpu(buf[0]); for (j = 0; j < nel; j++) { if (scope_read(p, i, fp)) goto bad; } } } if (policydb_index_decls(fp->handle, p)) goto bad; if (policydb_index_classes(p)) goto bad; switch (p->target_platform) { case SEPOL_TARGET_SELINUX: /* fall through */ case SEPOL_TARGET_XEN: p->process_trans = policydb_string_to_av_perm(p, p->process_class, "transition"); p->process_trans_dyntrans = p->process_trans | policydb_string_to_av_perm(p, p->process_class, "dyntransition"); break; default: break; } if (policydb_index_others(fp->handle, p, verbose)) goto bad; if (ocontext_read(info, p, fp) == -1) { goto bad; } if (genfs_read(p, fp) == -1) { goto bad; } if ((p->policy_type == POLICY_KERN && p->policyvers >= POLICYDB_VERSION_MLS) || (p->policy_type == POLICY_BASE && p->policyvers >= MOD_POLICYDB_VERSION_MLS && p->policyvers < MOD_POLICYDB_VERSION_RANGETRANS)) { if (range_read(p, fp)) { goto bad; } } if (policy_type == POLICY_KERN) { p->type_attr_map = calloc(p->p_types.nprim, sizeof(ebitmap_t)); p->attr_type_map = calloc(p->p_types.nprim, sizeof(ebitmap_t)); if (!p->type_attr_map || !p->attr_type_map) goto bad; for (i = 0; i < p->p_types.nprim; i++) { if (r_policyvers >= POLICYDB_VERSION_AVTAB) { if (ebitmap_read(&p->type_attr_map[i], fp)) goto bad; ebitmap_for_each_positive_bit(&p->type_attr_map[i], tnode, j) { if (i == j) continue; if (j >= p->p_types.nprim) goto bad; if (ebitmap_set_bit (&p->attr_type_map[j], i, 1)) goto bad; } } /* add the type itself as the degenerate case */ if (p->type_val_to_struct[i] && ebitmap_set_bit(&p->type_attr_map[i], i, 1)) goto bad; if (p->type_val_to_struct[i] && p->type_val_to_struct[i]->flavor != TYPE_ATTRIB) { if (ebitmap_set_bit(&p->attr_type_map[i], i, 1)) goto bad; } } } if (policydb_validate(fp->handle, p)) goto bad; return POLICYDB_SUCCESS; bad: return POLICYDB_ERROR; } int policydb_reindex_users(policydb_t * p) { unsigned int i = SYM_USERS; if (p->user_val_to_struct) free(p->user_val_to_struct); if (p->sym_val_to_name[i]) free(p->sym_val_to_name[i]); p->user_val_to_struct = (user_datum_t **) calloc(p->p_users.nprim, sizeof(user_datum_t *)); if (!p->user_val_to_struct) return -1; p->sym_val_to_name[i] = (char **) calloc(p->symtab[i].nprim, sizeof(char *)); if (!p->sym_val_to_name[i]) return -1; if (hashtab_map(p->symtab[i].table, index_f[i], p)) return -1; /* Expand user roles for context validity checking */ if (hashtab_map(p->p_users.table, policydb_user_cache, p)) return -1; return 0; } void policy_file_init(policy_file_t *pf) { memset(pf, 0, sizeof(policy_file_t)); } int policydb_set_target_platform(policydb_t *p, int platform) { if (platform == SEPOL_TARGET_SELINUX) p->target_platform = SEPOL_TARGET_SELINUX; else if (platform == SEPOL_TARGET_XEN) p->target_platform = SEPOL_TARGET_XEN; else return -1; return 0; } int policydb_sort_ocontexts(policydb_t *p) { return sort_ocontexts(p); } libsepol-3.8.1/src/policydb_convert.c000066400000000000000000000040721476211737200176510ustar00rootroot00000000000000#include #include "private.h" #include "debug.h" #include /* Construct a policydb from the supplied (data, len) pair */ int policydb_from_image(sepol_handle_t * handle, void *data, size_t len, policydb_t * policydb) { policy_file_t pf; policy_file_init(&pf); pf.type = PF_USE_MEMORY; pf.data = data; pf.len = len; pf.handle = handle; if (policydb_read(policydb, &pf, 0)) { policydb_destroy(policydb); ERR(handle, "policy image is invalid"); errno = EINVAL; return STATUS_ERR; } return STATUS_SUCCESS; } /* Write a policydb to a memory region, and return the (data, len) pair. */ int policydb_to_image(sepol_handle_t * handle, policydb_t * policydb, void **newdata, size_t * newlen) { void *tmp_data = NULL; size_t tmp_len; policy_file_t pf; struct policydb tmp_policydb; /* Compute the length for the new policy image. */ policy_file_init(&pf); pf.type = PF_LEN; pf.handle = handle; if (policydb_write(policydb, &pf)) { ERR(handle, "could not compute policy length"); errno = EINVAL; goto err; } /* Allocate the new policy image. */ pf.type = PF_USE_MEMORY; pf.data = malloc(pf.len); if (!pf.data) { ERR(handle, "out of memory"); goto err; } /* Need to save len and data prior to modification by policydb_write. */ tmp_len = pf.len; tmp_data = pf.data; /* Write out the new policy image. */ if (policydb_write(policydb, &pf)) { ERR(handle, "could not write policy"); errno = EINVAL; goto err; } /* Verify the new policy image. */ pf.type = PF_USE_MEMORY; pf.data = tmp_data; pf.len = tmp_len; if (policydb_init(&tmp_policydb)) { ERR(handle, "Out of memory"); errno = ENOMEM; goto err; } if (policydb_read(&tmp_policydb, &pf, 0)) { ERR(handle, "new policy image is invalid"); errno = EINVAL; goto err; } policydb_destroy(&tmp_policydb); /* Update (newdata, newlen) */ *newdata = tmp_data; *newlen = tmp_len; /* Recover */ return STATUS_SUCCESS; err: ERR(handle, "could not create policy image"); /* Recover */ free(tmp_data); return STATUS_ERR; } libsepol-3.8.1/src/policydb_internal.h000066400000000000000000000002421476211737200200050ustar00rootroot00000000000000#ifndef _SEPOL_POLICYDB_INTERNAL_H_ #define _SEPOL_POLICYDB_INTERNAL_H_ #include extern const char * const policydb_target_strings[]; #endif libsepol-3.8.1/src/policydb_public.c000066400000000000000000000077361476211737200174610ustar00rootroot00000000000000#include #include "debug.h" #include #include "policydb_internal.h" /* Policy file interfaces. */ int sepol_policy_file_create(sepol_policy_file_t ** pf) { *pf = calloc(1, sizeof(sepol_policy_file_t)); if (!(*pf)) return -1; return 0; } void sepol_policy_file_set_mem(sepol_policy_file_t * spf, char *data, size_t len) { struct policy_file *pf = &spf->pf; if (!len) { pf->type = PF_LEN; return; } pf->type = PF_USE_MEMORY; pf->data = data; pf->len = len; pf->size = len; return; } void sepol_policy_file_set_fp(sepol_policy_file_t * spf, FILE * fp) { struct policy_file *pf = &spf->pf; pf->type = PF_USE_STDIO; pf->fp = fp; return; } int sepol_policy_file_get_len(sepol_policy_file_t * spf, size_t * len) { struct policy_file *pf = &spf->pf; if (pf->type != PF_LEN) return -1; *len = pf->len; return 0; } void sepol_policy_file_set_handle(sepol_policy_file_t * pf, sepol_handle_t * handle) { pf->pf.handle = handle; } void sepol_policy_file_free(sepol_policy_file_t * pf) { free(pf); } /* Policydb interfaces. */ int sepol_policydb_create(sepol_policydb_t ** sp) { policydb_t *p; *sp = malloc(sizeof(sepol_policydb_t)); if (!(*sp)) return -1; p = &(*sp)->p; if (policydb_init(p)) { free(*sp); *sp = NULL; return -1; } return 0; } void sepol_policydb_free(sepol_policydb_t * p) { if (!p) return; policydb_destroy(&p->p); free(p); } int sepol_policy_kern_vers_min(void) { return POLICYDB_VERSION_MIN; } int sepol_policy_kern_vers_max(void) { return POLICYDB_VERSION_MAX; } int sepol_policydb_set_typevers(sepol_policydb_t * sp, unsigned int type) { struct policydb *p = &sp->p; switch (type) { case POLICY_KERN: p->policyvers = POLICYDB_VERSION_MAX; break; case POLICY_BASE: case POLICY_MOD: p->policyvers = MOD_POLICYDB_VERSION_MAX; break; default: return -1; } p->policy_type = type; return 0; } int sepol_policydb_set_vers(sepol_policydb_t * sp, unsigned int vers) { struct policydb *p = &sp->p; switch (p->policy_type) { case POLICY_KERN: if (vers < POLICYDB_VERSION_MIN || vers > POLICYDB_VERSION_MAX) return -1; break; case POLICY_BASE: case POLICY_MOD: if (vers < MOD_POLICYDB_VERSION_MIN || vers > MOD_POLICYDB_VERSION_MAX) return -1; break; default: return -1; } p->policyvers = vers; return 0; } int sepol_policydb_set_handle_unknown(sepol_policydb_t * sp, unsigned int handle_unknown) { struct policydb *p = &sp->p; switch (handle_unknown) { case SEPOL_DENY_UNKNOWN: case SEPOL_REJECT_UNKNOWN: case SEPOL_ALLOW_UNKNOWN: break; default: return -1; } p->handle_unknown = handle_unknown; return 0; } int sepol_policydb_set_target_platform(sepol_policydb_t * sp, int target_platform) { struct policydb *p = &sp->p; switch (target_platform) { case SEPOL_TARGET_SELINUX: case SEPOL_TARGET_XEN: break; default: return -1; } p->target_platform = target_platform; return 0; } int sepol_policydb_optimize(sepol_policydb_t * p) { return policydb_optimize(&p->p); } int sepol_policydb_read(sepol_policydb_t * p, sepol_policy_file_t * pf) { return policydb_read(&p->p, &pf->pf, 0); } int sepol_policydb_write(sepol_policydb_t * p, sepol_policy_file_t * pf) { return policydb_write(&p->p, &pf->pf); } int sepol_policydb_from_image(sepol_handle_t * handle, void *data, size_t len, sepol_policydb_t * p) { return policydb_from_image(handle, data, len, &p->p); } int sepol_policydb_to_image(sepol_handle_t * handle, sepol_policydb_t * p, void **newdata, size_t * newlen) { return policydb_to_image(handle, &p->p, newdata, newlen); } int sepol_policydb_mls_enabled(const sepol_policydb_t * p) { return p->p.mls; } /* * Enable compatibility mode for SELinux network checks iff * the packet class is not defined in the policy. */ #define PACKET_CLASS_NAME "packet" int sepol_policydb_compat_net(const sepol_policydb_t * p) { return (hashtab_search(p->p.p_classes.table, PACKET_CLASS_NAME) == NULL); } libsepol-3.8.1/src/policydb_validate.c000066400000000000000000001235371476211737200177720ustar00rootroot00000000000000 #include #include #include #include #include #include "debug.h" #include "kernel_to_common.h" #include "policydb_validate.h" #define bool_xor(a, b) (!(a) != !(b)) #define bool_xnor(a, b) (!bool_xor(a, b)) #define PERMISSION_MASK(nprim) ((nprim) == PERM_SYMTAB_SIZE ? (~UINT32_C(0)) : ((UINT32_C(1) << (nprim)) - 1)) typedef struct validate { uint32_t nprim; ebitmap_t gaps; } validate_t; typedef struct map_arg { validate_t *flavors; sepol_handle_t *handle; const policydb_t *policy; int conditional; } map_arg_t; typedef struct perm_arg { uint32_t visited; const uint32_t nprim; const uint32_t inherited_nprim; } perm_arg_t; static int create_gap_ebitmap(char **val_to_name, uint32_t nprim, ebitmap_t *gaps) { uint32_t i; ebitmap_init(gaps); for (i = 0; i < nprim; i++) { if (!val_to_name[i]) { if (ebitmap_set_bit(gaps, i, 1)) return -1; } } return 0; } static int validate_init(validate_t *flavor, char **val_to_name, uint32_t nprim) { flavor->nprim = nprim; if (create_gap_ebitmap(val_to_name, nprim, &flavor->gaps)) return -1; return 0; } static int validate_array_init(const policydb_t *p, validate_t flavors[]) { if (validate_init(&flavors[SYM_COMMONS], p->p_common_val_to_name, p->p_commons.nprim)) goto bad; if (validate_init(&flavors[SYM_CLASSES], p->p_class_val_to_name, p->p_classes.nprim)) goto bad; if (validate_init(&flavors[SYM_ROLES], p->p_role_val_to_name, p->p_roles.nprim)) goto bad; if (p->policy_type != POLICY_KERN || p->policyvers < POLICYDB_VERSION_AVTAB || p->policyvers > POLICYDB_VERSION_PERMISSIVE) { if (validate_init(&flavors[SYM_TYPES], p->p_type_val_to_name, p->p_types.nprim)) goto bad; } else { /* * For policy versions between 20 and 23, attributes exist in the policy, * but they only exist in the type_attr_map, so there will be references * to gaps and we just have to treat this case as if there were no gaps. */ flavors[SYM_TYPES].nprim = p->p_types.nprim; ebitmap_init(&flavors[SYM_TYPES].gaps); } if (validate_init(&flavors[SYM_USERS], p->p_user_val_to_name, p->p_users.nprim)) goto bad; if (validate_init(&flavors[SYM_BOOLS], p->p_bool_val_to_name, p->p_bools.nprim)) goto bad; if (validate_init(&flavors[SYM_LEVELS], p->p_sens_val_to_name, p->p_levels.nprim)) goto bad; if (validate_init(&flavors[SYM_CATS], p->p_cat_val_to_name, p->p_cats.nprim)) goto bad; return 0; bad: return -1; } /* * Functions to validate both kernel and module policydbs */ int value_isvalid(uint32_t value, uint32_t nprim) { if (!value || value > nprim) return 0; return 1; } static int validate_value(uint32_t value, const validate_t *flavor) { if (!value || value > flavor->nprim) goto bad; if (ebitmap_get_bit(&flavor->gaps, value-1)) goto bad; return 0; bad: return -1; } static int validate_ebitmap(const ebitmap_t *map, const validate_t *flavor) { if (ebitmap_length(map) > 0 && ebitmap_highest_set_bit(map) >= flavor->nprim) goto bad; if (ebitmap_match_any(map, &flavor->gaps)) goto bad; return 0; bad: return -1; } static int validate_type_set(const type_set_t *type_set, const validate_t *type) { if (validate_ebitmap(&type_set->types, type)) goto bad; if (validate_ebitmap(&type_set->negset, type)) goto bad; switch (type_set->flags) { case 0: case TYPE_STAR: case TYPE_COMP: break; default: goto bad; } return 0; bad: return -1; } static int validate_empty_type_set(const type_set_t *type_set) { if (!ebitmap_is_empty(&type_set->types)) goto bad; if (!ebitmap_is_empty(&type_set->negset)) goto bad; if (type_set->flags != 0) goto bad; return 0; bad: return -1; } static int validate_role_set(const role_set_t *role_set, const validate_t *role) { if (validate_ebitmap(&role_set->roles, role)) goto bad; switch (role_set->flags) { case 0: case ROLE_STAR: case ROLE_COMP: break; default: goto bad; } return 0; bad: return -1; } static int validate_scope(__attribute__ ((unused)) hashtab_key_t k, hashtab_datum_t d, void *args) { const scope_datum_t *scope_datum = (scope_datum_t *)d; const uint32_t *nprim = (uint32_t *)args; uint32_t i; switch (scope_datum->scope) { case SCOPE_REQ: case SCOPE_DECL: break; default: goto bad; } for (i = 0; i < scope_datum->decl_ids_len; i++) { if (!value_isvalid(scope_datum->decl_ids[i], *nprim)) goto bad; } return 0; bad: return -1; } static int validate_scopes(sepol_handle_t *handle, const symtab_t scopes[], const avrule_block_t *block) { const avrule_decl_t *decl; unsigned int i; uint32_t num_decls = 0; for (; block != NULL; block = block->next) { for (decl = block->branch_list; decl; decl = decl->next) { num_decls++; } } for (i = 0; i < SYM_NUM; i++) { if (hashtab_map(scopes[i].table, validate_scope, &num_decls)) goto bad; } return 0; bad: ERR(handle, "Invalid scope"); return -1; } static int validate_constraint_nodes(sepol_handle_t *handle, uint32_t nperms, const constraint_node_t *cons, validate_t flavors[]) { const constraint_expr_t *cexp; const int is_validatetrans = (nperms == UINT32_MAX); int depth; if (cons && nperms == 0) goto bad; for (; cons; cons = cons->next) { if (is_validatetrans && cons->permissions != 0) goto bad; if (!is_validatetrans && cons->permissions == 0) goto bad; if (!is_validatetrans && nperms != PERM_SYMTAB_SIZE && cons->permissions >= (UINT32_C(1) << nperms)) goto bad; if (!cons->expr) goto bad; depth = -1; for (cexp = cons->expr; cexp; cexp = cexp->next) { if (cexp->expr_type == CEXPR_NAMES) { if (depth >= (CEXPR_MAXDEPTH - 1)) goto bad; depth++; if (cexp->attr & CEXPR_XTARGET && !is_validatetrans) goto bad; if (!(cexp->attr & CEXPR_TYPE)) { if (validate_empty_type_set(cexp->type_names)) goto bad; } switch (cexp->op) { case CEXPR_EQ: case CEXPR_NEQ: break; default: goto bad; } switch (cexp->attr) { case CEXPR_USER: case CEXPR_USER | CEXPR_TARGET: case CEXPR_USER | CEXPR_XTARGET: if (validate_ebitmap(&cexp->names, &flavors[SYM_USERS])) goto bad; break; case CEXPR_ROLE: case CEXPR_ROLE | CEXPR_TARGET: case CEXPR_ROLE | CEXPR_XTARGET: if (validate_ebitmap(&cexp->names, &flavors[SYM_ROLES])) goto bad; break; case CEXPR_TYPE: case CEXPR_TYPE | CEXPR_TARGET: case CEXPR_TYPE | CEXPR_XTARGET: if (validate_ebitmap(&cexp->names, &flavors[SYM_TYPES])) goto bad; if (validate_type_set(cexp->type_names, &flavors[SYM_TYPES])) goto bad; break; default: goto bad; } } else if (cexp->expr_type == CEXPR_ATTR) { if (depth >= (CEXPR_MAXDEPTH - 1)) goto bad; depth++; if (!ebitmap_is_empty(&cexp->names)) goto bad; if (validate_empty_type_set(cexp->type_names)) goto bad; switch (cexp->op) { case CEXPR_EQ: case CEXPR_NEQ: break; case CEXPR_DOM: case CEXPR_DOMBY: case CEXPR_INCOMP: if ((cexp->attr & CEXPR_USER) || (cexp->attr & CEXPR_TYPE)) goto bad; break; default: goto bad; } switch (cexp->attr) { case CEXPR_USER: case CEXPR_ROLE: case CEXPR_TYPE: case CEXPR_L1L2: case CEXPR_L1H2: case CEXPR_H1L2: case CEXPR_H1H2: case CEXPR_L1H1: case CEXPR_L2H2: break; default: goto bad; } } else { switch (cexp->expr_type) { case CEXPR_NOT: if (depth < 0) goto bad; break; case CEXPR_AND: case CEXPR_OR: if (depth < 1) goto bad; depth--; break; default: goto bad; } if (cexp->op != 0) goto bad; if (cexp->attr != 0) goto bad; if (!ebitmap_is_empty(&cexp->names)) goto bad; if (validate_empty_type_set(cexp->type_names)) goto bad; } } if (depth != 0) goto bad; } return 0; bad: ERR(handle, "Invalid constraint expr"); return -1; } static int perm_visit(__attribute__((__unused__)) hashtab_key_t k, hashtab_datum_t d, void *args) { perm_arg_t *pargs = args; const perm_datum_t *perdatum = d; if (!value_isvalid(perdatum->s.value, pargs->nprim)) return -1; if (pargs->inherited_nprim != 0 && value_isvalid(perdatum->s.value, pargs->inherited_nprim)) return -1; if ((UINT32_C(1) << (perdatum->s.value - 1)) & pargs->visited) return -1; pargs->visited |= (UINT32_C(1) << (perdatum->s.value - 1)); return 0; } static int validate_permission_symtab(sepol_handle_t *handle, const symtab_t *permissions, uint32_t inherited_nprim) { /* Check each entry has a different valid value and is not overriding an inherited one */ perm_arg_t pargs = { .visited = 0, .nprim = permissions->nprim, .inherited_nprim = inherited_nprim }; if (hashtab_map(permissions->table, perm_visit, &pargs)) goto bad; return 0; bad: ERR(handle, "Invalid permission table"); return -1; } static int validate_common_datum(sepol_handle_t *handle, const common_datum_t *common, validate_t flavors[]) { if (validate_value(common->s.value, &flavors[SYM_COMMONS])) goto bad; if (common->permissions.nprim == 0 || common->permissions.nprim > PERM_SYMTAB_SIZE) goto bad; if (common->permissions.nprim != common->permissions.table->nel) goto bad; if (validate_permission_symtab(handle, &common->permissions, 0)) goto bad; return 0; bad: ERR(handle, "Invalid common class datum"); return -1; } static int validate_common_datum_wrapper(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, void *args) { map_arg_t *margs = args; return validate_common_datum(margs->handle, d, margs->flavors); } static int validate_class_datum(sepol_handle_t *handle, const class_datum_t *class, validate_t flavors[]) { if (class->s.value > UINT16_MAX || validate_value(class->s.value, &flavors[SYM_CLASSES])) goto bad; if (class->comdatum && validate_common_datum(handle, class->comdatum, flavors)) goto bad; /* empty classes are permitted */ if (class->permissions.nprim > PERM_SYMTAB_SIZE || class->permissions.table->nel > PERM_SYMTAB_SIZE) goto bad; if (class->permissions.nprim != (class->permissions.table->nel + (class->comdatum ? class->comdatum->permissions.table->nel : 0))) goto bad; if (validate_permission_symtab(handle, &class->permissions, class->comdatum ? class->comdatum->permissions.nprim : 0)) goto bad; if (validate_constraint_nodes(handle, class->permissions.nprim, class->constraints, flavors)) goto bad; if (validate_constraint_nodes(handle, UINT32_MAX, class->validatetrans, flavors)) goto bad; switch (class->default_user) { case 0: case DEFAULT_SOURCE: case DEFAULT_TARGET: break; default: goto bad; } switch (class->default_role) { case 0: case DEFAULT_SOURCE: case DEFAULT_TARGET: break; default: goto bad; } switch (class->default_type) { case 0: case DEFAULT_SOURCE: case DEFAULT_TARGET: break; default: goto bad; } switch (class->default_range) { case 0: case DEFAULT_SOURCE_LOW: case DEFAULT_SOURCE_HIGH: case DEFAULT_SOURCE_LOW_HIGH: case DEFAULT_TARGET_LOW: case DEFAULT_TARGET_HIGH: case DEFAULT_TARGET_LOW_HIGH: case DEFAULT_GLBLUB: break; default: goto bad; } return 0; bad: ERR(handle, "Invalid class datum"); return -1; } static int validate_class_datum_wrapper(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, void *args) { map_arg_t *margs = args; return validate_class_datum(margs->handle, d, margs->flavors); } static int validate_role_datum(sepol_handle_t *handle, const role_datum_t *role, validate_t flavors[]) { if (validate_value(role->s.value, &flavors[SYM_ROLES])) goto bad; if (validate_ebitmap(&role->dominates, &flavors[SYM_ROLES])) goto bad; if (validate_type_set(&role->types, &flavors[SYM_TYPES])) goto bad; if (role->bounds && validate_value(role->bounds, &flavors[SYM_ROLES])) goto bad; if (validate_ebitmap(&role->roles, &flavors[SYM_ROLES])) goto bad; switch(role->flavor) { case ROLE_ROLE: case ROLE_ATTRIB: break; default: goto bad; } return 0; bad: ERR(handle, "Invalid role datum"); return -1; } static int validate_role_datum_wrapper(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, void *args) { map_arg_t *margs = args; return validate_role_datum(margs->handle, d, margs->flavors); } static int validate_simpletype(uint32_t value, const policydb_t *p, const validate_t flavors[SYM_NUM]) { const type_datum_t *type; if (validate_value(value, &flavors[SYM_TYPES])) goto bad; type = p->type_val_to_struct[value - 1]; if (!type) goto bad; if (type->flavor == TYPE_ATTRIB) goto bad; return 0; bad: return -1; } static int validate_type_datum(sepol_handle_t *handle, const type_datum_t *type, const policydb_t *p, validate_t flavors[]) { if (validate_value(type->s.value, &flavors[SYM_TYPES])) goto bad; if (type->primary && validate_value(type->primary, &flavors[SYM_TYPES])) goto bad; switch (type->flavor) { case TYPE_TYPE: case TYPE_ALIAS: if (!ebitmap_is_empty(&type->types)) goto bad; if (type->bounds && validate_simpletype(type->bounds, p, flavors)) goto bad; break; case TYPE_ATTRIB: if (validate_ebitmap(&type->types, &flavors[SYM_TYPES])) goto bad; if (type->bounds) goto bad; break; default: goto bad; } switch (type->flags) { case 0: case TYPE_FLAGS_PERMISSIVE: case TYPE_FLAGS_EXPAND_ATTR_TRUE: case TYPE_FLAGS_EXPAND_ATTR_FALSE: case TYPE_FLAGS_EXPAND_ATTR: break; default: goto bad; } return 0; bad: ERR(handle, "Invalid type datum"); return -1; } static int validate_type_datum_wrapper(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, void *args) { map_arg_t *margs = args; return validate_type_datum(margs->handle, d, margs->policy, margs->flavors); } static int validate_mls_semantic_cat(const mls_semantic_cat_t *cat, const validate_t *cats) { for (; cat; cat = cat->next) { if (validate_value(cat->low, cats)) goto bad; if (validate_value(cat->high, cats)) goto bad; if (cat->low > cat->high) goto bad; } return 0; bad: return -1; } static int validate_mls_semantic_level(const mls_semantic_level_t *level, const validate_t *sens, const validate_t *cats) { if (level->sens == 0) return 0; if (validate_value(level->sens, sens)) goto bad; if (validate_mls_semantic_cat(level->cat, cats)) goto bad; return 0; bad: return -1; } static int validate_mls_semantic_range(const mls_semantic_range_t *range, const validate_t *sens, const validate_t *cats) { if (validate_mls_semantic_level(&range->level[0], sens, cats)) goto bad; if (validate_mls_semantic_level(&range->level[1], sens, cats)) goto bad; return 0; bad: return -1; } static int validate_mls_level(const mls_level_t *level, const validate_t *sens, const validate_t *cats) { if (validate_value(level->sens, sens)) goto bad; if (validate_ebitmap(&level->cat, cats)) goto bad; return 0; bad: return -1; } static int validate_level_datum(sepol_handle_t *handle, const level_datum_t *level, validate_t flavors[], const policydb_t *p) { if (level->notdefined != 0) goto bad; if (validate_mls_level(level->level, &flavors[SYM_LEVELS], &flavors[SYM_CATS])) goto bad; if (level->isalias) { const mls_level_t *l1 = level->level; const mls_level_t *l2; const level_datum_t *actual = (level_datum_t *) hashtab_search(p->p_levels.table, p->p_sens_val_to_name[l1->sens - 1]); if (!actual) goto bad; l2 = actual->level; if (!ebitmap_cmp(&l1->cat, &l2->cat)) goto bad; } return 0; bad: ERR(handle, "Invalid level datum"); return -1; } static int validate_level_datum_wrapper(__attribute__ ((unused)) hashtab_key_t k, hashtab_datum_t d, void *args) { map_arg_t *margs = args; return validate_level_datum(margs->handle, d, margs->flavors, margs->policy); } static int validate_mls_range(const mls_range_t *range, const validate_t *sens, const validate_t *cats) { if (validate_mls_level(&range->level[0], sens, cats)) goto bad; if (validate_mls_level(&range->level[1], sens, cats)) goto bad; return 0; bad: return -1; } static int validate_user_datum(sepol_handle_t *handle, const user_datum_t *user, validate_t flavors[], const policydb_t *p) { if (validate_value(user->s.value, &flavors[SYM_USERS])) goto bad; if (validate_role_set(&user->roles, &flavors[SYM_ROLES])) goto bad; if (validate_mls_semantic_range(&user->range, &flavors[SYM_LEVELS], &flavors[SYM_CATS])) goto bad; if (validate_mls_semantic_level(&user->dfltlevel, &flavors[SYM_LEVELS], &flavors[SYM_CATS])) goto bad; if (p->mls && p->policy_type != POLICY_MOD && validate_mls_range(&user->exp_range, &flavors[SYM_LEVELS], &flavors[SYM_CATS])) goto bad; if (p->mls && p->policy_type != POLICY_MOD && validate_mls_level(&user->exp_dfltlevel, &flavors[SYM_LEVELS], &flavors[SYM_CATS])) goto bad; if (user->bounds && validate_value(user->bounds, &flavors[SYM_USERS])) goto bad; return 0; bad: ERR(handle, "Invalid user datum"); return -1; } static int validate_user_datum_wrapper(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, void *args) { map_arg_t *margs = args; return validate_user_datum(margs->handle, d, margs->flavors, margs->policy); } static int validate_bool_datum(sepol_handle_t *handle, const cond_bool_datum_t *boolean, validate_t flavors[]) { if (validate_value(boolean->s.value, &flavors[SYM_BOOLS])) goto bad; switch (boolean->state) { case 0: case 1: break; default: goto bad; } switch (boolean->flags) { case 0: case COND_BOOL_FLAGS_TUNABLE: break; default: goto bad; } return 0; bad: ERR(handle, "Invalid bool datum"); return -1; } static int validate_bool_datum_wrapper(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, void *args) { map_arg_t *margs = args; return validate_bool_datum(margs->handle, d, margs->flavors); } static int validate_datum_array_gaps(sepol_handle_t *handle, const policydb_t *p, validate_t flavors[]) { uint32_t i; for (i = 0; i < p->p_classes.nprim; i++) { if (bool_xnor(p->class_val_to_struct[i], ebitmap_get_bit(&flavors[SYM_CLASSES].gaps, i))) goto bad; } for (i = 0; i < p->p_roles.nprim; i++) { if (bool_xnor(p->role_val_to_struct[i], ebitmap_get_bit(&flavors[SYM_ROLES].gaps, i))) goto bad; } /* * For policy versions between 20 and 23, attributes exist in the policy, * but only in the type_attr_map, so all gaps must be assumed to be valid. */ if (p->policy_type != POLICY_KERN || p->policyvers < POLICYDB_VERSION_AVTAB || p->policyvers > POLICYDB_VERSION_PERMISSIVE) { for (i = 0; i < p->p_types.nprim; i++) { if (bool_xnor(p->type_val_to_struct[i], ebitmap_get_bit(&flavors[SYM_TYPES].gaps, i))) goto bad; } } for (i = 0; i < p->p_users.nprim; i++) { if (bool_xnor(p->user_val_to_struct[i], ebitmap_get_bit(&flavors[SYM_USERS].gaps, i))) goto bad; } for (i = 0; i < p->p_bools.nprim; i++) { if (bool_xnor(p->bool_val_to_struct[i], ebitmap_get_bit(&flavors[SYM_BOOLS].gaps, i))) goto bad; } return 0; bad: ERR(handle, "Invalid datum array gaps"); return -1; } static int validate_datum(__attribute__ ((unused))hashtab_key_t k, hashtab_datum_t d, void *args) { symtab_datum_t *s = d; uint32_t *nprim = (uint32_t *)args; return !value_isvalid(s->value, *nprim); } static int validate_datum_array_entries(sepol_handle_t *handle, const policydb_t *p, validate_t flavors[]) { map_arg_t margs = { flavors, handle, p, 0 }; if (hashtab_map(p->p_commons.table, validate_common_datum_wrapper, &margs)) goto bad; if (hashtab_map(p->p_classes.table, validate_class_datum_wrapper, &margs)) goto bad; if (hashtab_map(p->p_roles.table, validate_role_datum_wrapper, &margs)) goto bad; if (hashtab_map(p->p_types.table, validate_type_datum_wrapper, &margs)) goto bad; if (hashtab_map(p->p_users.table, validate_user_datum_wrapper, &margs)) goto bad; if (p->mls && hashtab_map(p->p_levels.table, validate_level_datum_wrapper, &margs)) goto bad; if (hashtab_map(p->p_cats.table, validate_datum, &flavors[SYM_CATS])) goto bad; if (hashtab_map(p->p_bools.table, validate_bool_datum_wrapper, &margs)) goto bad; return 0; bad: ERR(handle, "Invalid datum array entries"); return -1; } /* * Functions to validate a kernel policydb */ static int validate_avtab_key(const avtab_key_t *key, int conditional, const policydb_t *p, validate_t flavors[]) { if (p->policy_type == POLICY_KERN && key->specified & AVTAB_TYPE) { if (validate_simpletype(key->source_type, p, flavors)) goto bad; if (validate_simpletype(key->target_type, p, flavors)) goto bad; } else { if (validate_value(key->source_type, &flavors[SYM_TYPES])) goto bad; if (validate_value(key->target_type, &flavors[SYM_TYPES])) goto bad; } if (validate_value(key->target_class, &flavors[SYM_CLASSES])) goto bad; switch (0xFFF & key->specified) { case AVTAB_ALLOWED: case AVTAB_AUDITALLOW: case AVTAB_AUDITDENY: case AVTAB_TRANSITION: case AVTAB_MEMBER: case AVTAB_CHANGE: break; case AVTAB_XPERMS_ALLOWED: case AVTAB_XPERMS_AUDITALLOW: case AVTAB_XPERMS_DONTAUDIT: if (p->target_platform != SEPOL_TARGET_SELINUX) goto bad; if (conditional && !policydb_has_cond_xperms_feature(p)) goto bad; break; default: goto bad; } return 0; bad: return -1; } static int validate_xperms(const avtab_extended_perms_t *xperms) { switch (xperms->specified) { case AVTAB_XPERMS_IOCTLDRIVER: case AVTAB_XPERMS_IOCTLFUNCTION: case AVTAB_XPERMS_NLMSG: break; default: goto bad; } return 0; bad: return -1; } static int validate_access_vector(sepol_handle_t *handle, const policydb_t *p, sepol_security_class_t tclass, sepol_access_vector_t av) { const class_datum_t *cladatum = p->class_val_to_struct[tclass - 1]; /* * Check that at least one permission bit is valid. * Older compilers might set invalid bits for the wildcard permission. */ if (!(av & PERMISSION_MASK(cladatum->permissions.nprim))) goto bad; return 0; bad: ERR(handle, "Invalid access vector"); return -1; } static int validate_avtab_key_and_datum(avtab_key_t *k, avtab_datum_t *d, void *args) { map_arg_t *margs = args; if (validate_avtab_key(k, margs->conditional, margs->policy, margs->flavors)) return -1; if (k->specified & AVTAB_AV) { uint32_t data = d->data; if ((0xFFF & k->specified) == AVTAB_AUDITDENY) data = ~data; if (validate_access_vector(margs->handle, margs->policy, k->target_class, data)) return -1; } if ((k->specified & AVTAB_TYPE) && validate_simpletype(d->data, margs->policy, margs->flavors)) return -1; if (k->specified & AVTAB_XPERMS) { uint32_t data = d->data; /* checkpolicy does not touch data for xperms, CIL sets it. */ if (data != 0 && validate_access_vector(margs->handle, margs->policy, k->target_class, data)) return -1; if (validate_xperms(d->xperms)) return -1; } return 0; } static int validate_avtab(sepol_handle_t *handle, const avtab_t *avtab, const policydb_t *p, validate_t flavors[]) { map_arg_t margs = { flavors, handle, p, 0 }; if (avtab_map(avtab, validate_avtab_key_and_datum, &margs)) { ERR(handle, "Invalid avtab"); return -1; } return 0; } static int validate_cond_av_list(sepol_handle_t *handle, const cond_av_list_t *cond_av, const policydb_t *p, validate_t flavors[]) { struct avtab_node *avtab_ptr; map_arg_t margs = { flavors, handle, p, 1 }; for (; cond_av; cond_av = cond_av->next) for (avtab_ptr = cond_av->node; avtab_ptr; avtab_ptr = avtab_ptr->next) if (validate_avtab_key_and_datum(&avtab_ptr->key, &avtab_ptr->datum, &margs)) goto bad; return 0; bad: ERR(handle, "Invalid cond av list"); return -1; } static int validate_avrules(sepol_handle_t *handle, const avrule_t *avrule, int conditional, const policydb_t *p, validate_t flavors[]) { const class_perm_node_t *classperm; for (; avrule; avrule = avrule->next) { if (validate_type_set(&avrule->stypes, &flavors[SYM_TYPES])) goto bad; if (validate_type_set(&avrule->ttypes, &flavors[SYM_TYPES])) goto bad; switch(avrule->specified) { case AVRULE_ALLOWED: case AVRULE_AUDITALLOW: case AVRULE_AUDITDENY: case AVRULE_DONTAUDIT: case AVRULE_TRANSITION: case AVRULE_MEMBER: case AVRULE_CHANGE: break; case AVRULE_NEVERALLOW: case AVRULE_XPERMS_ALLOWED: case AVRULE_XPERMS_AUDITALLOW: case AVRULE_XPERMS_DONTAUDIT: case AVRULE_XPERMS_NEVERALLOW: if (conditional && !policydb_has_cond_xperms_feature(p)) goto bad; break; default: goto bad; } for (classperm = avrule->perms; classperm; classperm = classperm->next) { if (validate_value(classperm->tclass, &flavors[SYM_CLASSES])) goto bad; if ((avrule->specified & AVRULE_TYPE) && validate_simpletype(classperm->data, p, flavors)) goto bad; } if (avrule->specified & AVRULE_XPERMS) { if (p->target_platform != SEPOL_TARGET_SELINUX) goto bad; if (!avrule->xperms) goto bad; switch (avrule->xperms->specified) { case AVRULE_XPERMS_IOCTLFUNCTION: case AVRULE_XPERMS_IOCTLDRIVER: case AVRULE_XPERMS_NLMSG: break; default: goto bad; } } else if (avrule->xperms) goto bad; switch(avrule->flags) { case 0: break; case RULE_SELF: if (p->policyvers != POLICY_KERN && p->policyvers < MOD_POLICYDB_VERSION_SELF_TYPETRANS && (avrule->specified & AVRULE_TYPE)) goto bad; break; case RULE_NOTSELF: switch(avrule->specified) { case AVRULE_NEVERALLOW: case AVRULE_XPERMS_NEVERALLOW: break; default: goto bad; } break; default: goto bad; } } return 0; bad: ERR(handle, "Invalid avrule"); return -1; } static int validate_bool_id_array(sepol_handle_t *handle, const uint32_t bool_ids[], unsigned int nbools, const validate_t *boolean) { unsigned int i; if (nbools >= COND_MAX_BOOLS) goto bad; for (i=0; i < nbools; i++) { if (validate_value(bool_ids[i], boolean)) goto bad; } return 0; bad: ERR(handle, "Invalid bool id array"); return -1; } static int validate_cond_expr(sepol_handle_t *handle, const struct cond_expr *expr, const validate_t *boolean) { int depth = -1; if (!expr) goto bad; for (; expr; expr = expr->next) { switch(expr->expr_type) { case COND_BOOL: if (validate_value(expr->boolean, boolean)) goto bad; if (depth >= (COND_EXPR_MAXDEPTH - 1)) goto bad; depth++; break; case COND_NOT: if (depth < 0) goto bad; if (expr->boolean != 0) goto bad; break; case COND_OR: case COND_AND: case COND_XOR: case COND_EQ: case COND_NEQ: if (depth < 1) goto bad; if (expr->boolean != 0) goto bad; depth--; break; default: goto bad; } } if (depth != 0) goto bad; return 0; bad: ERR(handle, "Invalid cond expression"); return -1; } static int validate_cond_list(sepol_handle_t *handle, const cond_list_t *cond, const policydb_t *p, validate_t flavors[]) { for (; cond; cond = cond->next) { if (validate_cond_expr(handle, cond->expr, &flavors[SYM_BOOLS])) goto bad; if (validate_cond_av_list(handle, cond->true_list, p, flavors)) goto bad; if (validate_cond_av_list(handle, cond->false_list, p, flavors)) goto bad; if (validate_avrules(handle, cond->avtrue_list, 1, p, flavors)) goto bad; if (validate_avrules(handle, cond->avfalse_list, 1, p, flavors)) goto bad; if (validate_bool_id_array(handle, cond->bool_ids, cond->nbools, &flavors[SYM_BOOLS])) goto bad; switch (cond->cur_state) { case 0: case 1: break; default: goto bad; } switch (cond->flags) { case 0: case COND_NODE_FLAGS_TUNABLE: break; default: goto bad; } } return 0; bad: ERR(handle, "Invalid cond list"); return -1; } static int validate_role_transes(sepol_handle_t *handle, const role_trans_t *role_trans, validate_t flavors[]) { for (; role_trans; role_trans = role_trans->next) { if (validate_value(role_trans->role, &flavors[SYM_ROLES])) goto bad; if (validate_value(role_trans->type, &flavors[SYM_TYPES])) goto bad; if (validate_value(role_trans->tclass, &flavors[SYM_CLASSES])) goto bad; if (validate_value(role_trans->new_role, &flavors[SYM_ROLES])) goto bad; } return 0; bad: ERR(handle, "Invalid role trans"); return -1; } static int validate_role_allows(sepol_handle_t *handle, const role_allow_t *role_allow, validate_t flavors[]) { for (; role_allow; role_allow = role_allow->next) { if (validate_value(role_allow->role, &flavors[SYM_ROLES])) goto bad; if (validate_value(role_allow->new_role, &flavors[SYM_ROLES])) goto bad; } return 0; bad: ERR(handle, "Invalid role allow"); return -1; } static int validate_filename_trans(hashtab_key_t k, hashtab_datum_t d, void *args) { const filename_trans_key_t *ftk = (filename_trans_key_t *)k; const filename_trans_datum_t *ftd = d; const map_arg_t *margs = args; const validate_t *flavors = margs->flavors; const policydb_t *p = margs->policy; if (validate_value(ftk->ttype, &flavors[SYM_TYPES])) goto bad; if (validate_value(ftk->tclass, &flavors[SYM_CLASSES])) goto bad; if (!ftd) goto bad; for (; ftd; ftd = ftd->next) { if (validate_ebitmap(&ftd->stypes, &flavors[SYM_TYPES])) goto bad; if (validate_simpletype(ftd->otype, p, flavors)) goto bad; } return 0; bad: return -1; } static int validate_filename_trans_hashtab(sepol_handle_t *handle, const policydb_t *p, validate_t flavors[]) { map_arg_t margs = { flavors, handle, p, 0 }; if (hashtab_map(p->filename_trans, validate_filename_trans, &margs)) { ERR(handle, "Invalid filename trans"); return -1; } return 0; } static int validate_context(const context_struct_t *con, validate_t flavors[], int mls) { if (validate_value(con->user, &flavors[SYM_USERS])) return -1; if (validate_value(con->role, &flavors[SYM_ROLES])) return -1; if (validate_value(con->type, &flavors[SYM_TYPES])) return -1; if (mls && validate_mls_range(&con->range, &flavors[SYM_LEVELS], &flavors[SYM_CATS])) return -1; return 0; } static int validate_ocontexts(sepol_handle_t *handle, const policydb_t *p, validate_t flavors[]) { const ocontext_t *octx; unsigned int i; for (i = 0; i < OCON_NUM; i++) { for (octx = p->ocontexts[i]; octx; octx = octx->next) { if (validate_context(&octx->context[0], flavors, p->mls)) goto bad; if (p->target_platform == SEPOL_TARGET_SELINUX) { switch (i) { case OCON_ISID: if (octx->sid[0] == SEPOL_SECSID_NULL || octx->sid[0] >= SELINUX_SID_SZ) goto bad; break; case OCON_FS: case OCON_NETIF: if (validate_context(&octx->context[1], flavors, p->mls)) goto bad; if (!octx->u.name) goto bad; break; case OCON_PORT: if (octx->u.port.low_port > octx->u.port.high_port) goto bad; break; case OCON_FSUSE: switch (octx->v.behavior) { case SECURITY_FS_USE_XATTR: case SECURITY_FS_USE_TRANS: case SECURITY_FS_USE_TASK: break; default: goto bad; } if (!octx->u.name) goto bad; break; case OCON_IBPKEY: if (octx->u.ibpkey.low_pkey > octx->u.ibpkey.high_pkey) goto bad; break; case OCON_IBENDPORT: if (octx->u.ibendport.port == 0) goto bad; if (!octx->u.ibendport.dev_name) goto bad; break; } } else if (p->target_platform == SEPOL_TARGET_XEN) { switch(i) { case OCON_XEN_ISID: if (octx->sid[0] == SEPOL_SECSID_NULL || octx->sid[0] >= XEN_SID_SZ) goto bad; break; case OCON_XEN_IOPORT: if (octx->u.ioport.low_ioport > octx->u.ioport.high_ioport) goto bad; break; case OCON_XEN_IOMEM: if (octx->u.iomem.low_iomem > octx->u.iomem.high_iomem) goto bad; if (p->policyvers < POLICYDB_VERSION_XEN_DEVICETREE && octx->u.iomem.high_iomem > 0xFFFFFFFFULL) goto bad; break; case OCON_XEN_DEVICETREE: if (!octx->u.name) goto bad; break; } } } } return 0; bad: ERR(handle, "Invalid ocontext"); return -1; } static int validate_genfs(sepol_handle_t *handle, const policydb_t *p, validate_t flavors[]) { const genfs_t *genfs; const ocontext_t *octx; for (genfs = p->genfs; genfs; genfs = genfs->next) { for (octx = genfs->head; octx; octx = octx->next) { if (validate_context(&octx->context[0], flavors, p->mls)) goto bad; if (octx->v.sclass && validate_value(octx->v.sclass, &flavors[SYM_CLASSES])) goto bad; } if (!genfs->fstype) goto bad; } return 0; bad: ERR(handle, "Invalid genfs"); return -1; } /* * Functions to validate a module policydb */ static int validate_role_trans_rules(sepol_handle_t *handle, const role_trans_rule_t *role_trans, validate_t flavors[]) { for (; role_trans; role_trans = role_trans->next) { if (validate_role_set(&role_trans->roles, &flavors[SYM_ROLES])) goto bad; if (validate_type_set(&role_trans->types, &flavors[SYM_TYPES])) goto bad; if (validate_ebitmap(&role_trans->classes, &flavors[SYM_CLASSES])) goto bad; if (validate_value(role_trans->new_role, &flavors[SYM_ROLES])) goto bad; } return 0; bad: ERR(handle, "Invalid role trans rule"); return -1; } static int validate_role_allow_rules(sepol_handle_t *handle, const role_allow_rule_t *role_allow, validate_t flavors[]) { for (; role_allow; role_allow = role_allow->next) { if (validate_role_set(&role_allow->roles, &flavors[SYM_ROLES])) goto bad; if (validate_role_set(&role_allow->new_roles, &flavors[SYM_ROLES])) goto bad; } return 0; bad: ERR(handle, "Invalid role allow rule"); return -1; } static int validate_range_trans_rules(sepol_handle_t *handle, const range_trans_rule_t *range_trans, validate_t flavors[]) { for (; range_trans; range_trans = range_trans->next) { if (validate_type_set(&range_trans->stypes, &flavors[SYM_TYPES])) goto bad; if (validate_type_set(&range_trans->ttypes, &flavors[SYM_TYPES])) goto bad; if (validate_ebitmap(&range_trans->tclasses, &flavors[SYM_CLASSES])) goto bad; if (validate_mls_semantic_range(&range_trans->trange, &flavors[SYM_LEVELS], &flavors[SYM_CATS])) goto bad; } return 0; bad: ERR(handle, "Invalid range trans rule"); return -1; } static int validate_scope_index(sepol_handle_t *handle, const scope_index_t *scope_index, validate_t flavors[]) { uint32_t i; if (!ebitmap_is_empty(&scope_index->scope[SYM_COMMONS])) goto bad; if (validate_ebitmap(&scope_index->p_classes_scope, &flavors[SYM_CLASSES])) goto bad; if (validate_ebitmap(&scope_index->p_roles_scope, &flavors[SYM_ROLES])) goto bad; if (validate_ebitmap(&scope_index->p_types_scope, &flavors[SYM_TYPES])) goto bad; if (validate_ebitmap(&scope_index->p_users_scope, &flavors[SYM_USERS])) goto bad; if (validate_ebitmap(&scope_index->p_bools_scope, &flavors[SYM_BOOLS])) goto bad; if (validate_ebitmap(&scope_index->p_sens_scope, &flavors[SYM_LEVELS])) goto bad; if (validate_ebitmap(&scope_index->p_cat_scope, &flavors[SYM_CATS])) goto bad; for (i = 0; i < scope_index->class_perms_len; i++) if (validate_value(i + 1, &flavors[SYM_CLASSES])) goto bad; return 0; bad: ERR(handle, "Invalid scope"); return -1; } static int validate_filename_trans_rules(sepol_handle_t *handle, const filename_trans_rule_t *filename_trans, const policydb_t *p, validate_t flavors[]) { for (; filename_trans; filename_trans = filename_trans->next) { if (validate_type_set(&filename_trans->stypes, &flavors[SYM_TYPES])) goto bad; if (validate_type_set(&filename_trans->ttypes, &flavors[SYM_TYPES])) goto bad; if (validate_value(filename_trans->tclass,&flavors[SYM_CLASSES] )) goto bad; if (validate_simpletype(filename_trans->otype, p, flavors)) goto bad; /* currently only the RULE_SELF flag can be set */ switch (filename_trans->flags) { case 0: break; case RULE_SELF: if (p->policyvers != POLICY_KERN && p->policyvers < MOD_POLICYDB_VERSION_SELF_TYPETRANS) goto bad; break; default: goto bad; } } return 0; bad: ERR(handle, "Invalid filename trans rule list"); return -1; } static int validate_symtabs(sepol_handle_t *handle, const symtab_t symtabs[], validate_t flavors[]) { unsigned int i; for (i = 0; i < SYM_NUM; i++) { if (hashtab_map(symtabs[i].table, validate_datum, &flavors[i].nprim)) { ERR(handle, "Invalid symtab"); return -1; } } return 0; } static int validate_avrule_blocks(sepol_handle_t *handle, const avrule_block_t *avrule_block, const policydb_t *p, validate_t flavors[]) { const avrule_decl_t *decl; for (; avrule_block; avrule_block = avrule_block->next) { for (decl = avrule_block->branch_list; decl != NULL; decl = decl->next) { if (validate_cond_list(handle, decl->cond_list, p, flavors)) goto bad; if (validate_avrules(handle, decl->avrules, 0, p, flavors)) goto bad; if (validate_role_trans_rules(handle, decl->role_tr_rules, flavors)) goto bad; if (validate_role_allow_rules(handle, decl->role_allow_rules, flavors)) goto bad; if (validate_range_trans_rules(handle, decl->range_tr_rules, flavors)) goto bad; if (validate_scope_index(handle, &decl->required, flavors)) goto bad; if (validate_scope_index(handle, &decl->declared, flavors)) goto bad; if (validate_filename_trans_rules(handle, decl->filename_trans_rules, p, flavors)) goto bad; if (validate_symtabs(handle, decl->symtab, flavors)) goto bad; } switch (avrule_block->flags) { case 0: case AVRULE_OPTIONAL: break; default: goto bad; } } return 0; bad: ERR(handle, "Invalid avrule block"); return -1; } static int validate_permissives(sepol_handle_t *handle, const policydb_t *p, validate_t flavors[]) { ebitmap_node_t *node; uint32_t i; ebitmap_for_each_positive_bit(&p->permissive_map, node, i) { if (validate_simpletype(i, p, flavors)) goto bad; } return 0; bad: ERR(handle, "Invalid permissive type"); return -1; } static int validate_range_transition(hashtab_key_t key, hashtab_datum_t data, void *args) { const range_trans_t *rt = (const range_trans_t *)key; const mls_range_t *r = data; const map_arg_t *margs = args; const validate_t *flavors = margs->flavors; if (validate_value(rt->source_type, &flavors[SYM_TYPES])) goto bad; if (validate_value(rt->target_type, &flavors[SYM_TYPES])) goto bad; if (validate_value(rt->target_class, &flavors[SYM_CLASSES])) goto bad; if (validate_mls_range(r, &flavors[SYM_LEVELS], &flavors[SYM_CATS])) goto bad; return 0; bad: return -1; } static int validate_range_transitions(sepol_handle_t *handle, const policydb_t *p, validate_t flavors[]) { map_arg_t margs = { flavors, handle, p, 0 }; if (hashtab_map(p->range_tr, validate_range_transition, &margs)) { ERR(handle, "Invalid range transition"); return -1; } return 0; } static int validate_typeattr_map(sepol_handle_t *handle, const policydb_t *p, validate_t flavors[]) { const ebitmap_t *maps = p->type_attr_map; uint32_t i; if (p->policy_type == POLICY_KERN) { for (i = 0; i < p->p_types.nprim; i++) { if (validate_ebitmap(&maps[i], &flavors[SYM_TYPES])) goto bad; } } else if (maps) goto bad; return 0; bad: ERR(handle, "Invalid type attr map"); return -1; } static int validate_attrtype_map(sepol_handle_t *handle, const policydb_t *p, validate_t flavors[]) { const ebitmap_t *maps = p->attr_type_map; uint32_t i; if (p->policy_type == POLICY_KERN) { for (i = 0; i < p->p_types.nprim; i++) { if (validate_ebitmap(&maps[i], &flavors[SYM_TYPES])) goto bad; } } else if (maps) goto bad; return 0; bad: ERR(handle, "Invalid attr type map"); return -1; } static int validate_properties(sepol_handle_t *handle, const policydb_t *p) { switch (p->policy_type) { case POLICY_KERN: if (p->policyvers < POLICYDB_VERSION_MIN || p->policyvers > POLICYDB_VERSION_MAX) goto bad; if (p->mls && p->policyvers < POLICYDB_VERSION_MLS) goto bad; break; case POLICY_BASE: case POLICY_MOD: if (p->policyvers < MOD_POLICYDB_VERSION_MIN || p->policyvers > MOD_POLICYDB_VERSION_MAX) goto bad; if (p->mls && p->policyvers < MOD_POLICYDB_VERSION_MLS) goto bad; break; default: goto bad; } switch (p->target_platform) { case SEPOL_TARGET_SELINUX: case SEPOL_TARGET_XEN: break; default: goto bad; } switch (p->mls) { case 0: case 1: break; default: goto bad; } switch (p->handle_unknown) { case SEPOL_DENY_UNKNOWN: case SEPOL_REJECT_UNKNOWN: case SEPOL_ALLOW_UNKNOWN: break; default: goto bad; } return 0; bad: ERR(handle, "Invalid policy property"); return -1; } static int validate_policycaps(sepol_handle_t *handle, const policydb_t *p) { ebitmap_node_t *node; uint32_t i; ebitmap_for_each_positive_bit(&p->policycaps, node, i) { if (!sepol_polcap_getname(i)) goto bad; } return 0; bad: ERR(handle, "Invalid policy capability"); return -1; } static void validate_array_destroy(validate_t flavors[]) { unsigned int i; for (i = 0; i < SYM_NUM; i++) { ebitmap_destroy(&flavors[i].gaps); } } /* * Validate policydb */ int policydb_validate(sepol_handle_t *handle, const policydb_t *p) { validate_t flavors[SYM_NUM] = {}; if (validate_array_init(p, flavors)) goto bad; if (validate_properties(handle, p)) goto bad; if (validate_policycaps(handle, p)) goto bad; if (p->policy_type == POLICY_KERN) { if (validate_avtab(handle, &p->te_avtab, p, flavors)) goto bad; if (p->policyvers >= POLICYDB_VERSION_BOOL) if (validate_cond_list(handle, p->cond_list, p, flavors)) goto bad; if (validate_role_transes(handle, p->role_tr, flavors)) goto bad; if (validate_role_allows(handle, p->role_allow, flavors)) goto bad; if (p->policyvers >= POLICYDB_VERSION_FILENAME_TRANS) if (validate_filename_trans_hashtab(handle, p, flavors)) goto bad; } else { if (validate_avrule_blocks(handle, p->global, p, flavors)) goto bad; } if (validate_ocontexts(handle, p, flavors)) goto bad; if (validate_genfs(handle, p, flavors)) goto bad; if (validate_scopes(handle, p->scope, p->global)) goto bad; if (validate_datum_array_gaps(handle, p, flavors)) goto bad; if (validate_datum_array_entries(handle, p, flavors)) goto bad; if (validate_permissives(handle, p, flavors)) goto bad; if (validate_range_transitions(handle, p, flavors)) goto bad; if (validate_typeattr_map(handle, p, flavors)) goto bad; if (validate_attrtype_map(handle, p, flavors)) goto bad; validate_array_destroy(flavors); return 0; bad: ERR(handle, "Invalid policydb"); validate_array_destroy(flavors); return -1; } libsepol-3.8.1/src/policydb_validate.h000066400000000000000000000003141476211737200177620ustar00rootroot00000000000000#include #include #include int value_isvalid(uint32_t value, uint32_t nprim); int policydb_validate(sepol_handle_t *handle, const policydb_t *p); libsepol-3.8.1/src/port_internal.h000066400000000000000000000002011476211737200171570ustar00rootroot00000000000000#ifndef _SEPOL_PORT_INTERNAL_H_ #define _SEPOL_PORT_INTERNAL_H_ #include #include #endif libsepol-3.8.1/src/port_record.c000066400000000000000000000112451476211737200166260ustar00rootroot00000000000000#include #include #include "port_internal.h" #include "context_internal.h" #include "debug.h" struct sepol_port { /* Low - High range. Same for single ports. */ int low, high; /* Protocol */ int proto; /* Context */ sepol_context_t *con; }; struct sepol_port_key { /* Low - High range. Same for single ports. */ int low, high; /* Protocol */ int proto; }; /* Key */ int sepol_port_key_create(sepol_handle_t * handle, int low, int high, int proto, sepol_port_key_t ** key_ptr) { sepol_port_key_t *tmp_key = (sepol_port_key_t *) malloc(sizeof(sepol_port_key_t)); if (!tmp_key) { ERR(handle, "out of memory, could not create " "port key"); return STATUS_ERR; } tmp_key->low = low; tmp_key->high = high; tmp_key->proto = proto; *key_ptr = tmp_key; return STATUS_SUCCESS; } void sepol_port_key_unpack(const sepol_port_key_t * key, int *low, int *high, int *proto) { *low = key->low; *high = key->high; *proto = key->proto; } int sepol_port_key_extract(sepol_handle_t * handle, const sepol_port_t * port, sepol_port_key_t ** key_ptr) { if (sepol_port_key_create (handle, port->low, port->high, port->proto, key_ptr) < 0) { ERR(handle, "could not extract key from port %s %d:%d", sepol_port_get_proto_str(port->proto), port->low, port->high); return STATUS_ERR; } return STATUS_SUCCESS; } void sepol_port_key_free(sepol_port_key_t * key) { free(key); } int sepol_port_compare(const sepol_port_t * port, const sepol_port_key_t * key) { if ((port->low == key->low) && (port->high == key->high) && (port->proto == key->proto)) return 0; if (port->low < key->low) return -1; else if (key->low < port->low) return 1; else if (port->high < key->high) return -1; else if (key->high < port->high) return 1; else if (port->proto < key->proto) return -1; else return 1; } int sepol_port_compare2(const sepol_port_t * port, const sepol_port_t * port2) { if ((port->low == port2->low) && (port->high == port2->high) && (port->proto == port2->proto)) return 0; if (port->low < port2->low) return -1; else if (port2->low < port->low) return 1; else if (port->high < port2->high) return -1; else if (port2->high < port->high) return 1; else if (port->proto < port2->proto) return -1; else return 1; } /* Port */ int sepol_port_get_low(const sepol_port_t * port) { return port->low; } int sepol_port_get_high(const sepol_port_t * port) { return port->high; } void sepol_port_set_port(sepol_port_t * port, int port_num) { port->low = port_num; port->high = port_num; } void sepol_port_set_range(sepol_port_t * port, int low, int high) { port->low = low; port->high = high; } /* Protocol */ int sepol_port_get_proto(const sepol_port_t * port) { return port->proto; } const char *sepol_port_get_proto_str(int proto) { switch (proto) { case SEPOL_PROTO_UDP: return "udp"; case SEPOL_PROTO_TCP: return "tcp"; case SEPOL_PROTO_DCCP: return "dccp"; case SEPOL_PROTO_SCTP: return "sctp"; default: return "???"; } } void sepol_port_set_proto(sepol_port_t * port, int proto) { port->proto = proto; } /* Create */ int sepol_port_create(sepol_handle_t * handle, sepol_port_t ** port) { sepol_port_t *tmp_port = (sepol_port_t *) malloc(sizeof(sepol_port_t)); if (!tmp_port) { ERR(handle, "out of memory, could not create " "port record"); return STATUS_ERR; } tmp_port->low = 0; tmp_port->high = 0; tmp_port->proto = SEPOL_PROTO_UDP; tmp_port->con = NULL; *port = tmp_port; return STATUS_SUCCESS; } /* Deep copy clone */ int sepol_port_clone(sepol_handle_t * handle, const sepol_port_t * port, sepol_port_t ** port_ptr) { sepol_port_t *new_port = NULL; if (sepol_port_create(handle, &new_port) < 0) goto err; new_port->low = port->low; new_port->high = port->high; new_port->proto = port->proto; if (port->con && (sepol_context_clone(handle, port->con, &new_port->con) < 0)) goto err; *port_ptr = new_port; return STATUS_SUCCESS; err: ERR(handle, "could not clone port record"); sepol_port_free(new_port); return STATUS_ERR; } /* Destroy */ void sepol_port_free(sepol_port_t * port) { if (!port) return; sepol_context_free(port->con); free(port); } /* Context */ sepol_context_t *sepol_port_get_con(const sepol_port_t * port) { return port->con; } int sepol_port_set_con(sepol_handle_t * handle, sepol_port_t * port, sepol_context_t * con) { sepol_context_t *newcon; if (sepol_context_clone(handle, con, &newcon) < 0) { ERR(handle, "out of memory, could not set port context"); return STATUS_ERR; } sepol_context_free(port->con); port->con = newcon; return STATUS_SUCCESS; } libsepol-3.8.1/src/ports.c000066400000000000000000000163441476211737200154600ustar00rootroot00000000000000#include #ifndef IPPROTO_DCCP #define IPPROTO_DCCP 33 #endif #ifndef IPPROTO_SCTP #define IPPROTO_SCTP 132 #endif #include #include "debug.h" #include "context.h" #include "handle.h" #include #include "port_internal.h" static inline int sepol2ipproto(sepol_handle_t * handle, int proto) { switch (proto) { case SEPOL_PROTO_TCP: return IPPROTO_TCP; case SEPOL_PROTO_UDP: return IPPROTO_UDP; case SEPOL_PROTO_DCCP: return IPPROTO_DCCP; case SEPOL_PROTO_SCTP: return IPPROTO_SCTP; default: ERR(handle, "unsupported protocol %u", proto); return STATUS_ERR; } } static inline int ipproto2sepol(sepol_handle_t * handle, int proto) { switch (proto) { case IPPROTO_TCP: return SEPOL_PROTO_TCP; case IPPROTO_UDP: return SEPOL_PROTO_UDP; case IPPROTO_DCCP: return SEPOL_PROTO_DCCP; case IPPROTO_SCTP: return SEPOL_PROTO_SCTP; default: ERR(handle, "invalid protocol %u " "found in policy", proto); return STATUS_ERR; } } /* Create a low level port structure from * a high level representation */ static int port_from_record(sepol_handle_t * handle, const policydb_t * policydb, ocontext_t ** port, const sepol_port_t * data) { ocontext_t *tmp_port = NULL; context_struct_t *tmp_con = NULL; int tmp_proto; int low = sepol_port_get_low(data); int high = sepol_port_get_high(data); int proto = sepol_port_get_proto(data); tmp_port = (ocontext_t *) calloc(1, sizeof(ocontext_t)); if (!tmp_port) goto omem; /* Process protocol */ tmp_proto = sepol2ipproto(handle, proto); if (tmp_proto < 0) goto err; tmp_port->u.port.protocol = tmp_proto; /* Port range */ tmp_port->u.port.low_port = low; tmp_port->u.port.high_port = high; if (tmp_port->u.port.low_port > tmp_port->u.port.high_port) { ERR(handle, "low port %d exceeds high port %d", tmp_port->u.port.low_port, tmp_port->u.port.high_port); goto err; } /* Context */ if (context_from_record(handle, policydb, &tmp_con, sepol_port_get_con(data)) < 0) goto err; context_cpy(&tmp_port->context[0], tmp_con); context_destroy(tmp_con); free(tmp_con); tmp_con = NULL; *port = tmp_port; return STATUS_SUCCESS; omem: ERR(handle, "out of memory"); err: if (tmp_port != NULL) { context_destroy(&tmp_port->context[0]); free(tmp_port); } context_destroy(tmp_con); free(tmp_con); ERR(handle, "could not create port structure for range %u:%u (%s)", low, high, sepol_port_get_proto_str(proto)); return STATUS_ERR; } static int port_to_record(sepol_handle_t * handle, const policydb_t * policydb, ocontext_t * port, sepol_port_t ** record) { int proto = port->u.port.protocol; int low = port->u.port.low_port; int high = port->u.port.high_port; context_struct_t *con = &port->context[0]; int rec_proto = -1; sepol_context_t *tmp_con = NULL; sepol_port_t *tmp_record = NULL; if (sepol_port_create(handle, &tmp_record) < 0) goto err; rec_proto = ipproto2sepol(handle, proto); if (rec_proto < 0) goto err; sepol_port_set_proto(tmp_record, rec_proto); sepol_port_set_range(tmp_record, low, high); if (context_to_record(handle, policydb, con, &tmp_con) < 0) goto err; if (sepol_port_set_con(handle, tmp_record, tmp_con) < 0) goto err; sepol_context_free(tmp_con); *record = tmp_record; return STATUS_SUCCESS; err: ERR(handle, "could not convert port range %u - %u (%s) " "to record", low, high, sepol_port_get_proto_str(rec_proto)); sepol_context_free(tmp_con); sepol_port_free(tmp_record); return STATUS_ERR; } /* Return the number of ports */ extern int sepol_port_count(sepol_handle_t * handle __attribute__ ((unused)), const sepol_policydb_t * p, unsigned int *response) { unsigned int count = 0; ocontext_t *c, *head; const policydb_t *policydb = &p->p; head = policydb->ocontexts[OCON_PORT]; for (c = head; c != NULL; c = c->next) count++; *response = count; return STATUS_SUCCESS; } /* Check if a port exists */ int sepol_port_exists(sepol_handle_t * handle, const sepol_policydb_t * p, const sepol_port_key_t * key, int *response) { const policydb_t *policydb = &p->p; ocontext_t *c, *head; int low, high, proto; const char *proto_str; sepol_port_key_unpack(key, &low, &high, &proto); proto_str = sepol_port_get_proto_str(proto); proto = sepol2ipproto(handle, proto); if (proto < 0) goto err; head = policydb->ocontexts[OCON_PORT]; for (c = head; c; c = c->next) { int proto2 = c->u.port.protocol; int low2 = c->u.port.low_port; int high2 = c->u.port.high_port; if (proto == proto2 && low2 == low && high2 == high) { *response = 1; return STATUS_SUCCESS; } } *response = 0; return STATUS_SUCCESS; err: ERR(handle, "could not check if port range %u - %u (%s) exists", low, high, proto_str); return STATUS_ERR; } /* Query a port */ int sepol_port_query(sepol_handle_t * handle, const sepol_policydb_t * p, const sepol_port_key_t * key, sepol_port_t ** response) { const policydb_t *policydb = &p->p; ocontext_t *c, *head; int low, high, proto; const char *proto_str; sepol_port_key_unpack(key, &low, &high, &proto); proto_str = sepol_port_get_proto_str(proto); proto = sepol2ipproto(handle, proto); if (proto < 0) goto err; head = policydb->ocontexts[OCON_PORT]; for (c = head; c; c = c->next) { int proto2 = c->u.port.protocol; int low2 = c->u.port.low_port; int high2 = c->u.port.high_port; if (proto == proto2 && low2 == low && high2 == high) { if (port_to_record(handle, policydb, c, response) < 0) goto err; return STATUS_SUCCESS; } } *response = NULL; return STATUS_SUCCESS; err: ERR(handle, "could not query port range %u - %u (%s)", low, high, proto_str); return STATUS_ERR; } /* Load a port into policy */ int sepol_port_modify(sepol_handle_t * handle, sepol_policydb_t * p, const sepol_port_key_t * key, const sepol_port_t * data) { policydb_t *policydb = &p->p; ocontext_t *port = NULL; int low, high, proto; const char *proto_str; sepol_port_key_unpack(key, &low, &high, &proto); proto_str = sepol_port_get_proto_str(proto); proto = sepol2ipproto(handle, proto); if (proto < 0) goto err; if (port_from_record(handle, policydb, &port, data) < 0) goto err; /* Attach to context list */ port->next = policydb->ocontexts[OCON_PORT]; policydb->ocontexts[OCON_PORT] = port; return STATUS_SUCCESS; err: ERR(handle, "could not load port range %u - %u (%s)", low, high, proto_str); if (port != NULL) { context_destroy(&port->context[0]); free(port); } return STATUS_ERR; } int sepol_port_iterate(sepol_handle_t * handle, const sepol_policydb_t * p, int (*fn) (const sepol_port_t * port, void *fn_arg), void *arg) { const policydb_t *policydb = &p->p; ocontext_t *c, *head; sepol_port_t *port = NULL; head = policydb->ocontexts[OCON_PORT]; for (c = head; c; c = c->next) { int status; if (port_to_record(handle, policydb, c, &port) < 0) goto err; /* Invoke handler */ status = fn(port, arg); if (status < 0) goto err; sepol_port_free(port); port = NULL; /* Handler requested exit */ if (status > 0) break; } return STATUS_SUCCESS; err: ERR(handle, "could not iterate over ports"); sepol_port_free(port); return STATUS_ERR; } libsepol-3.8.1/src/private.h000066400000000000000000000053571476211737200157720ustar00rootroot00000000000000/* Private definitions for libsepol. */ /* Endian conversion for reading and writing binary policies */ #include #ifdef __APPLE__ #include #include #else #include #include #endif #include #ifdef __APPLE__ #define __BYTE_ORDER BYTE_ORDER #define __LITTLE_ENDIAN LITTLE_ENDIAN #endif #if __BYTE_ORDER == __LITTLE_ENDIAN #define cpu_to_le16(x) (x) #define le16_to_cpu(x) (x) #define cpu_to_le32(x) (x) #define le32_to_cpu(x) (x) #define cpu_to_le64(x) (x) #define le64_to_cpu(x) (x) #else #define cpu_to_le16(x) bswap_16(x) #define le16_to_cpu(x) bswap_16(x) #define cpu_to_le32(x) bswap_32(x) #define le32_to_cpu(x) bswap_32(x) #define cpu_to_le64(x) bswap_64(x) #define le64_to_cpu(x) bswap_64(x) #endif #undef min #define min(a,b) (((a) < (b)) ? (a) : (b)) #undef max #define max(a,b) ((a) >= (b) ? (a) : (b)) #define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0])) static inline int exceeds_available_bytes(const struct policy_file *fp, size_t x, size_t req_elem_size) { size_t req_size; /* Remaining input size is only available for mmap'ed memory */ if (fp->type != PF_USE_MEMORY) return 0; if (__builtin_mul_overflow(x, req_elem_size, &req_size)) return 1; return req_size > fp->len; } #define is_saturated(x) ((x) == (typeof(x))-1) #define zero_or_saturated(x) (((x) == 0) || is_saturated(x)) #define spaceship_cmp(a, b) (((a) > (b)) - ((a) < (b))) /* Use to ignore intentional unsigned under- and overflows while running under UBSAN. */ #if defined(__clang__) && defined(__clang_major__) && (__clang_major__ >= 4) #if (__clang_major__ >= 12) #define ignore_unsigned_overflow_ __attribute__((no_sanitize("unsigned-integer-overflow", "unsigned-shift-base"))) #else #define ignore_unsigned_overflow_ __attribute__((no_sanitize("unsigned-integer-overflow"))) #endif #else #define ignore_unsigned_overflow_ #endif /* Policy compatibility information. */ struct policydb_compat_info { unsigned int type; unsigned int version; unsigned int sym_num; unsigned int ocon_num; unsigned int target_platform; }; extern const struct policydb_compat_info *policydb_lookup_compat(unsigned int version, unsigned int type, unsigned int target_platform); /* Reading from a policy "file". */ extern int next_entry(void *buf, struct policy_file *fp, size_t bytes); extern size_t put_entry(const void *ptr, size_t size, size_t n, struct policy_file *fp); extern int str_read(char **strp, struct policy_file *fp, size_t len); #ifndef HAVE_REALLOCARRAY static inline void* reallocarray(void *ptr, size_t nmemb, size_t size) { if (size && nmemb > (size_t)-1 / size) { errno = ENOMEM; return NULL; } return realloc(ptr, nmemb * size); } #endif libsepol-3.8.1/src/services.c000066400000000000000000001572031476211737200161340ustar00rootroot00000000000000/* * Author : Stephen Smalley, */ /* * Updated: Trusted Computer Solutions, Inc. * * Support for enhanced MLS infrastructure. * * Updated: Frank Mayer * and Karl MacMillan * * Added conditional policy language extensions * * Updated: Red Hat, Inc. James Morris * * Fine-grained netlink support * IPv6 support * Code cleanup * * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. * Copyright (C) 2003 - 2004 Tresys Technology, LLC * Copyright (C) 2003 - 2004 Red Hat, Inc. * Copyright (C) 2017 Mellanox Technologies Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* FLASK */ /* * Implementation of the security services. */ /* Initial sizes malloc'd for sepol_compute_av_reason_buffer() support */ #define REASON_BUF_SIZE 2048 #define EXPR_BUF_SIZE 1024 #define STACK_LEN 32 #include #include #include #include #include #include #include #include #include #include #include #include "debug.h" #include "private.h" #include "context.h" #include "mls.h" #include "flask.h" #define BUG() do { ERR(NULL, "Badness at %s:%d", __FILE__, __LINE__); } while (0) static int selinux_enforcing = 1; static sidtab_t mysidtab, *sidtab = &mysidtab; static policydb_t mypolicydb, *policydb = &mypolicydb; /* Used by sepol_compute_av_reason_buffer() to keep track of entries */ static int reason_buf_used; static int reason_buf_len; /* Stack services for RPN to infix conversion. */ static char **stack; static int stack_len; static int next_stack_entry; static void push(char *expr_ptr) { if (next_stack_entry >= stack_len) { char **new_stack; int new_stack_len; if (stack_len == 0) new_stack_len = STACK_LEN; else new_stack_len = stack_len * 2; new_stack = reallocarray(stack, new_stack_len, sizeof(*stack)); if (!new_stack) { ERR(NULL, "unable to allocate stack space"); return; } stack_len = new_stack_len; stack = new_stack; } stack[next_stack_entry] = expr_ptr; next_stack_entry++; } static char *pop(void) { next_stack_entry--; if (next_stack_entry < 0) { next_stack_entry = 0; ERR(NULL, "pop called with no stack entries"); return NULL; } return stack[next_stack_entry]; } /* End Stack services */ int sepol_set_sidtab(sidtab_t * s) { sidtab = s; return 0; } int sepol_set_policydb(policydb_t * p) { policydb = p; return 0; } int sepol_set_policydb_from_file(FILE * fp) { struct policy_file pf; policy_file_init(&pf); pf.fp = fp; pf.type = PF_USE_STDIO; if (mypolicydb.policy_type) policydb_destroy(&mypolicydb); if (policydb_init(&mypolicydb)) { ERR(NULL, "Out of memory!"); return -1; } if (policydb_read(&mypolicydb, &pf, 0)) { policydb_destroy(&mypolicydb); ERR(NULL, "can't read binary policy: %m"); return -1; } policydb = &mypolicydb; return sepol_sidtab_init(sidtab); } /* * The largest sequence number that has been used when * providing an access decision to the access vector cache. * The sequence number only changes when a policy change * occurs. */ static uint32_t latest_granting = 0; /* * cat_expr_buf adds a string to an expression buffer and handles * realloc's if buffer is too small. The array of expression text * buffer pointers and its counter are globally defined here as * constraint_expr_eval_reason() sets them up and cat_expr_buf * updates the e_buf pointer. */ static int expr_counter; static char **expr_list; static int expr_buf_used; static int expr_buf_len; static void cat_expr_buf(char *e_buf, const char *string) { int len, new_buf_len; char *p, *new_buf; while (1) { p = e_buf + expr_buf_used; len = snprintf(p, expr_buf_len - expr_buf_used, "%s", string); if (len < 0 || len >= expr_buf_len - expr_buf_used) { new_buf_len = expr_buf_len + EXPR_BUF_SIZE; new_buf = realloc(e_buf, new_buf_len); if (!new_buf) { ERR(NULL, "failed to realloc expr buffer"); return; } /* Update new ptr in expr list and locally + new len */ expr_list[expr_counter] = new_buf; e_buf = new_buf; expr_buf_len = new_buf_len; } else { expr_buf_used += len; return; } } } /* * If the POLICY_KERN version is >= POLICYDB_VERSION_CONSTRAINT_NAMES, * then for 'types' only, read the types_names->types list as it will * contain a list of types and attributes that were defined in the * policy source. * For user and role plus types (for policy vers < * POLICYDB_VERSION_CONSTRAINT_NAMES) just read the e->names list. */ static void get_name_list(constraint_expr_t *e, int type, const char *src, const char *op, int failed) { ebitmap_t *types; int rc = 0; unsigned int i; char tmp_buf[128]; int counter = 0; if (policydb->policy_type == POLICY_KERN && policydb->policyvers >= POLICYDB_VERSION_CONSTRAINT_NAMES && type == CEXPR_TYPE) types = &e->type_names->types; else types = &e->names; /* Find out how many entries */ for (i = ebitmap_startbit(types); i < ebitmap_length(types); i++) { rc = ebitmap_get_bit(types, i); if (rc == 0) continue; else counter++; } snprintf(tmp_buf, sizeof(tmp_buf), "(%s%s", src, op); cat_expr_buf(expr_list[expr_counter], tmp_buf); if (counter == 0) cat_expr_buf(expr_list[expr_counter], " "); if (counter > 1) cat_expr_buf(expr_list[expr_counter], " {"); if (counter >= 1) { for (i = ebitmap_startbit(types); i < ebitmap_length(types); i++) { rc = ebitmap_get_bit(types, i); if (rc == 0) continue; /* Collect entries */ switch (type) { case CEXPR_USER: snprintf(tmp_buf, sizeof(tmp_buf), " %s", policydb->p_user_val_to_name[i]); break; case CEXPR_ROLE: snprintf(tmp_buf, sizeof(tmp_buf), " %s", policydb->p_role_val_to_name[i]); break; case CEXPR_TYPE: snprintf(tmp_buf, sizeof(tmp_buf), " %s", policydb->p_type_val_to_name[i]); break; } cat_expr_buf(expr_list[expr_counter], tmp_buf); } } if (counter > 1) cat_expr_buf(expr_list[expr_counter], " }"); if (failed) cat_expr_buf(expr_list[expr_counter], " -Fail-) "); else cat_expr_buf(expr_list[expr_counter], ") "); return; } static void msgcat(const char *src, const char *tgt, const char *op, int failed) { char tmp_buf[128]; if (failed) snprintf(tmp_buf, sizeof(tmp_buf), "(%s %s %s -Fail-) ", src, op, tgt); else snprintf(tmp_buf, sizeof(tmp_buf), "(%s %s %s) ", src, op, tgt); cat_expr_buf(expr_list[expr_counter], tmp_buf); } /* Returns a buffer with class, statement type and permissions */ static char *get_class_info(sepol_security_class_t tclass, constraint_node_t *constraint, context_struct_t *xcontext) { constraint_expr_t *e; int mls, state_num; /* Determine statement type */ const char *statements[] = { "constrain ", /* 0 */ "mlsconstrain ", /* 1 */ "validatetrans ", /* 2 */ "mlsvalidatetrans ", /* 3 */ 0 }; size_t class_buf_len = 0; size_t new_class_buf_len; size_t buf_used; int len; char *class_buf = NULL, *p; char *new_class_buf = NULL; /* Find if MLS statement or not */ mls = 0; for (e = constraint->expr; e; e = e->next) { if (e->attr >= CEXPR_L1L2) { mls = 1; break; } } if (xcontext == NULL) state_num = mls + 0; else state_num = mls + 2; while (1) { new_class_buf_len = class_buf_len + EXPR_BUF_SIZE; new_class_buf = realloc(class_buf, new_class_buf_len); if (!new_class_buf) { free(class_buf); return NULL; } class_buf_len = new_class_buf_len; class_buf = new_class_buf; buf_used = 0; p = class_buf; /* Add statement type */ len = snprintf(p, class_buf_len - buf_used, "%s", statements[state_num]); if (len < 0 || (size_t)len >= class_buf_len - buf_used) continue; /* Add class entry */ p += len; buf_used += len; len = snprintf(p, class_buf_len - buf_used, "%s ", policydb->p_class_val_to_name[tclass - 1]); if (len < 0 || (size_t)len >= class_buf_len - buf_used) continue; /* Add permission entries (validatetrans does not have perms) */ p += len; buf_used += len; if (state_num < 2) { char *permstr = sepol_av_to_string(policydb, tclass, constraint->permissions); len = snprintf(p, class_buf_len - buf_used, "{%s } (", permstr ?: ""); free(permstr); } else { len = snprintf(p, class_buf_len - buf_used, "("); } if (len < 0 || (size_t)len >= class_buf_len - buf_used) continue; break; } return class_buf; } /* * Modified version of constraint_expr_eval that will process each * constraint as before but adds the information to text buffers that * will hold various components. The expression will be in RPN format, * therefore there is a stack based RPN to infix converter to produce * the final readable constraint. * * Return the boolean value of a constraint expression * when it is applied to the specified source and target * security contexts. * * xcontext is a special beast... It is used by the validatetrans rules * only. For these rules, scontext is the context before the transition, * tcontext is the context after the transition, and xcontext is the * context of the process performing the transition. All other callers * of constraint_expr_eval_reason should pass in NULL for xcontext. * * This function will also build a buffer as the constraint is processed * for analysis. If this option is not required, then: * 'tclass' should be '0' and r_buf MUST be NULL. */ static int constraint_expr_eval_reason(context_struct_t *scontext, context_struct_t *tcontext, context_struct_t *xcontext, sepol_security_class_t tclass, constraint_node_t *constraint, char **r_buf, unsigned int flags) { uint32_t val1, val2; context_struct_t *c; role_datum_t *r1, *r2; mls_level_t *l1, *l2; constraint_expr_t *e; int s[CEXPR_MAXDEPTH] = {}; int sp = -1; char tmp_buf[128]; /* * Define the s_t_x_num values that make up r1, t2 etc. in text strings * Set 1 = source, 2 = target, 3 = xcontext for validatetrans */ #define SOURCE 1 #define TARGET 2 #define XTARGET 3 int s_t_x_num; /* Set 0 = fail, u = CEXPR_USER, r = CEXPR_ROLE, t = CEXPR_TYPE */ int u_r_t = 0; char *src = NULL; char *tgt = NULL; int rc = 0, x; char *class_buf = NULL; int expr_list_len = 0; int expr_count; /* * The array of expression answer buffer pointers and counter. */ char **answer_list = NULL; int answer_counter = 0; /* The pop operands */ char *a; char *b; int a_len, b_len; class_buf = get_class_info(tclass, constraint, xcontext); if (!class_buf) { ERR(NULL, "failed to allocate class buffer"); return -ENOMEM; } /* Original function but with buffer support */ expr_counter = 0; expr_list = NULL; for (e = constraint->expr; e; e = e->next) { /* Allocate a stack to hold expression buffer entries */ if (expr_counter >= expr_list_len) { char **new_expr_list; int new_expr_list_len; if (expr_list_len == 0) new_expr_list_len = STACK_LEN; else new_expr_list_len = expr_list_len * 2; new_expr_list = reallocarray(expr_list, new_expr_list_len, sizeof(*expr_list)); if (!new_expr_list) { ERR(NULL, "failed to allocate expr buffer stack"); rc = -ENOMEM; goto out; } expr_list_len = new_expr_list_len; expr_list = new_expr_list; } /* * malloc a buffer to store each expression text component. If * buffer is too small cat_expr_buf() will realloc extra space. */ expr_buf_len = EXPR_BUF_SIZE; expr_list[expr_counter] = malloc(expr_buf_len); if (!expr_list[expr_counter]) { ERR(NULL, "failed to allocate expr buffer"); rc = -ENOMEM; goto out; } expr_buf_used = 0; /* Now process each expression of the constraint */ switch (e->expr_type) { case CEXPR_NOT: if (sp < 0) { BUG(); rc = -EINVAL; goto out; } s[sp] = !s[sp]; cat_expr_buf(expr_list[expr_counter], "not"); break; case CEXPR_AND: if (sp < 1) { BUG(); rc = -EINVAL; goto out; } sp--; s[sp] &= s[sp + 1]; cat_expr_buf(expr_list[expr_counter], "and"); break; case CEXPR_OR: if (sp < 1) { BUG(); rc = -EINVAL; goto out; } sp--; s[sp] |= s[sp + 1]; cat_expr_buf(expr_list[expr_counter], "or"); break; case CEXPR_ATTR: if (sp == (CEXPR_MAXDEPTH - 1)) goto out; switch (e->attr) { case CEXPR_USER: val1 = scontext->user; val2 = tcontext->user; free(src); src = strdup("u1"); free(tgt); tgt = strdup("u2"); break; case CEXPR_TYPE: val1 = scontext->type; val2 = tcontext->type; free(src); src = strdup("t1"); free(tgt); tgt = strdup("t2"); break; case CEXPR_ROLE: val1 = scontext->role; val2 = tcontext->role; r1 = policydb->role_val_to_struct[val1 - 1]; r2 = policydb->role_val_to_struct[val2 - 1]; free(src); src = strdup("r1"); free(tgt); tgt = strdup("r2"); switch (e->op) { case CEXPR_DOM: s[++sp] = ebitmap_get_bit(&r1->dominates, val2 - 1); msgcat(src, tgt, "dom", s[sp] == 0); expr_counter++; continue; case CEXPR_DOMBY: s[++sp] = ebitmap_get_bit(&r2->dominates, val1 - 1); msgcat(src, tgt, "domby", s[sp] == 0); expr_counter++; continue; case CEXPR_INCOMP: s[++sp] = (!ebitmap_get_bit(&r1->dominates, val2 - 1) && !ebitmap_get_bit(&r2->dominates, val1 - 1)); msgcat(src, tgt, "incomp", s[sp] == 0); expr_counter++; continue; default: break; } break; case CEXPR_L1L2: l1 = &(scontext->range.level[0]); l2 = &(tcontext->range.level[0]); free(src); src = strdup("l1"); free(tgt); tgt = strdup("l2"); goto mls_ops; case CEXPR_L1H2: l1 = &(scontext->range.level[0]); l2 = &(tcontext->range.level[1]); free(src); src = strdup("l1"); free(tgt); tgt = strdup("h2"); goto mls_ops; case CEXPR_H1L2: l1 = &(scontext->range.level[1]); l2 = &(tcontext->range.level[0]); free(src); src = strdup("h1"); free(tgt); tgt = strdup("l2"); goto mls_ops; case CEXPR_H1H2: l1 = &(scontext->range.level[1]); l2 = &(tcontext->range.level[1]); free(src); src = strdup("h1"); free(tgt); tgt = strdup("h2"); goto mls_ops; case CEXPR_L1H1: l1 = &(scontext->range.level[0]); l2 = &(scontext->range.level[1]); free(src); src = strdup("l1"); free(tgt); tgt = strdup("h1"); goto mls_ops; case CEXPR_L2H2: l1 = &(tcontext->range.level[0]); l2 = &(tcontext->range.level[1]); free(src); src = strdup("l2"); free(tgt); tgt = strdup("h2"); mls_ops: switch (e->op) { case CEXPR_EQ: s[++sp] = mls_level_eq(l1, l2); msgcat(src, tgt, "eq", s[sp] == 0); expr_counter++; continue; case CEXPR_NEQ: s[++sp] = !mls_level_eq(l1, l2); msgcat(src, tgt, "!=", s[sp] == 0); expr_counter++; continue; case CEXPR_DOM: s[++sp] = mls_level_dom(l1, l2); msgcat(src, tgt, "dom", s[sp] == 0); expr_counter++; continue; case CEXPR_DOMBY: s[++sp] = mls_level_dom(l2, l1); msgcat(src, tgt, "domby", s[sp] == 0); expr_counter++; continue; case CEXPR_INCOMP: s[++sp] = mls_level_incomp(l2, l1); msgcat(src, tgt, "incomp", s[sp] == 0); expr_counter++; continue; default: BUG(); goto out; } break; default: BUG(); goto out; } switch (e->op) { case CEXPR_EQ: s[++sp] = (val1 == val2); msgcat(src, tgt, "==", s[sp] == 0); break; case CEXPR_NEQ: s[++sp] = (val1 != val2); msgcat(src, tgt, "!=", s[sp] == 0); break; default: BUG(); goto out; } break; case CEXPR_NAMES: if (sp == (CEXPR_MAXDEPTH - 1)) goto out; s_t_x_num = SOURCE; c = scontext; if (e->attr & CEXPR_TARGET) { s_t_x_num = TARGET; c = tcontext; } else if (e->attr & CEXPR_XTARGET) { s_t_x_num = XTARGET; c = xcontext; } if (!c) { BUG(); goto out; } if (e->attr & CEXPR_USER) { u_r_t = CEXPR_USER; val1 = c->user; snprintf(tmp_buf, sizeof(tmp_buf), "u%d ", s_t_x_num); free(src); src = strdup(tmp_buf); } else if (e->attr & CEXPR_ROLE) { u_r_t = CEXPR_ROLE; val1 = c->role; snprintf(tmp_buf, sizeof(tmp_buf), "r%d ", s_t_x_num); free(src); src = strdup(tmp_buf); } else if (e->attr & CEXPR_TYPE) { u_r_t = CEXPR_TYPE; val1 = c->type; snprintf(tmp_buf, sizeof(tmp_buf), "t%d ", s_t_x_num); free(src); src = strdup(tmp_buf); } else { BUG(); goto out; } switch (e->op) { case CEXPR_EQ: s[++sp] = ebitmap_get_bit(&e->names, val1 - 1); get_name_list(e, u_r_t, src, "==", s[sp] == 0); break; case CEXPR_NEQ: s[++sp] = !ebitmap_get_bit(&e->names, val1 - 1); get_name_list(e, u_r_t, src, "!=", s[sp] == 0); break; default: BUG(); goto out; } break; default: BUG(); goto out; } expr_counter++; } /* * At this point each expression of the constraint is in * expr_list[n+1] and in RPN format. Now convert to 'infix' */ /* * Save expr count but zero expr_counter to detect if * 'BUG(); goto out;' was called as we need to release any used * expr_list malloc's. Normally they are released by the RPN to * infix code. */ expr_count = expr_counter; expr_counter = 0; /* * Generate the same number of answer buffer entries as expression * buffers (as there will never be more). */ answer_list = calloc(expr_count, sizeof(*answer_list)); if (!answer_list) { ERR(NULL, "failed to allocate answer stack"); rc = -ENOMEM; goto out; } /* Convert constraint from RPN to infix notation. */ for (x = 0; x != expr_count; x++) { if (strncmp(expr_list[x], "and", 3) == 0 || strncmp(expr_list[x], "or", 2) == 0) { b = pop(); b_len = strlen(b); a = pop(); a_len = strlen(a); /* get a buffer to hold the answer */ answer_list[answer_counter] = malloc(a_len + b_len + 8); if (!answer_list[answer_counter]) { ERR(NULL, "failed to allocate answer buffer"); rc = -ENOMEM; goto out; } memset(answer_list[answer_counter], '\0', a_len + b_len + 8); sprintf(answer_list[answer_counter], "%s %s %s", a, expr_list[x], b); push(answer_list[answer_counter++]); free(a); free(b); free(expr_list[x]); } else if (strncmp(expr_list[x], "not", 3) == 0) { b = pop(); b_len = strlen(b); answer_list[answer_counter] = malloc(b_len + 8); if (!answer_list[answer_counter]) { ERR(NULL, "failed to allocate answer buffer"); rc = -ENOMEM; goto out; } memset(answer_list[answer_counter], '\0', b_len + 8); if (strncmp(b, "not", 3) == 0) sprintf(answer_list[answer_counter], "%s (%s)", expr_list[x], b); else sprintf(answer_list[answer_counter], "%s%s", expr_list[x], b); push(answer_list[answer_counter++]); free(b); free(expr_list[x]); } else { push(expr_list[x]); } } /* Get the final answer from tos and build constraint text */ a = pop(); /* validatetrans / constraint calculation: rc = 0 is denied, rc = 1 is granted */ sprintf(tmp_buf, "%s %s\n", xcontext ? "Validatetrans" : "Constraint", s[0] ? "GRANTED" : "DENIED"); /* * This will add the constraints to the callers reason buffer (who is * responsible for freeing the memory). It will handle any realloc's * should the buffer be too short. * The reason_buf_used and reason_buf_len counters are defined * globally as multiple constraints can be in the buffer. */ if (r_buf && ((s[0] == 0) || ((s[0] == 1 && (flags & SHOW_GRANTED) == SHOW_GRANTED)))) { int len; char *p; /* * These contain the constraint components that are added to the * callers reason buffer. */ const char *buffers[] = { class_buf, a, "); ", tmp_buf, 0 }; for (x = 0; buffers[x] != NULL; x++) { while (1) { p = *r_buf ? (*r_buf + reason_buf_used) : NULL; len = snprintf(p, reason_buf_len - reason_buf_used, "%s", buffers[x]); if (len < 0 || len >= reason_buf_len - reason_buf_used) { int new_buf_len = reason_buf_len + REASON_BUF_SIZE; char *new_buf = realloc(*r_buf, new_buf_len); if (!new_buf) { ERR(NULL, "failed to realloc reason buffer"); goto out1; } *r_buf = new_buf; reason_buf_len = new_buf_len; continue; } else { reason_buf_used += len; break; } } } } out1: rc = s[0]; free(a); out: free(class_buf); free(src); free(tgt); if (expr_counter) { for (x = 0; expr_list[x] != NULL; x++) free(expr_list[x]); } free(answer_list); free(expr_list); return rc; } /* Forward declaration */ static int context_struct_compute_av(context_struct_t * scontext, context_struct_t * tcontext, sepol_security_class_t tclass, sepol_access_vector_t requested, struct sepol_av_decision *avd, unsigned int *reason, char **r_buf, unsigned int flags); static void type_attribute_bounds_av(context_struct_t *scontext, context_struct_t *tcontext, sepol_security_class_t tclass, sepol_access_vector_t requested, struct sepol_av_decision *avd, unsigned int *reason) { context_struct_t lo_scontext; context_struct_t lo_tcontext, *tcontextp = tcontext; struct sepol_av_decision lo_avd; type_datum_t *source; type_datum_t *target; sepol_access_vector_t masked = 0; source = policydb->type_val_to_struct[scontext->type - 1]; if (!source->bounds) return; target = policydb->type_val_to_struct[tcontext->type - 1]; memset(&lo_avd, 0, sizeof(lo_avd)); memcpy(&lo_scontext, scontext, sizeof(lo_scontext)); lo_scontext.type = source->bounds; if (target->bounds) { memcpy(&lo_tcontext, tcontext, sizeof(lo_tcontext)); lo_tcontext.type = target->bounds; tcontextp = &lo_tcontext; } context_struct_compute_av(&lo_scontext, tcontextp, tclass, requested, &lo_avd, NULL, /* reason intentionally omitted */ NULL, 0); masked = ~lo_avd.allowed & avd->allowed; if (!masked) return; /* no masked permission */ /* mask violated permissions */ avd->allowed &= ~masked; if (reason) *reason |= SEPOL_COMPUTEAV_BOUNDS; } /* * Compute access vectors based on a context structure pair for * the permissions in a particular class. */ static int context_struct_compute_av(context_struct_t * scontext, context_struct_t * tcontext, sepol_security_class_t tclass, sepol_access_vector_t requested, struct sepol_av_decision *avd, unsigned int *reason, char **r_buf, unsigned int flags) { constraint_node_t *constraint; struct role_allow *ra; avtab_key_t avkey; class_datum_t *tclass_datum; avtab_ptr_t node; ebitmap_t *sattr, *tattr; ebitmap_node_t *snode, *tnode; unsigned int i, j; if (!tclass || tclass > policydb->p_classes.nprim) { ERR(NULL, "unrecognized class %d", tclass); return -EINVAL; } tclass_datum = policydb->class_val_to_struct[tclass - 1]; /* * Initialize the access vectors to the default values. */ avd->allowed = 0; avd->decided = 0xffffffff; avd->auditallow = 0; avd->auditdeny = 0xffffffff; avd->seqno = latest_granting; if (reason) *reason = 0; /* * If a specific type enforcement rule was defined for * this permission check, then use it. */ avkey.target_class = tclass; avkey.specified = AVTAB_AV; sattr = &policydb->type_attr_map[scontext->type - 1]; tattr = &policydb->type_attr_map[tcontext->type - 1]; ebitmap_for_each_positive_bit(sattr, snode, i) { ebitmap_for_each_positive_bit(tattr, tnode, j) { avkey.source_type = i + 1; avkey.target_type = j + 1; for (node = avtab_search_node(&policydb->te_avtab, &avkey); node != NULL; node = avtab_search_node_next(node, avkey.specified)) { if (node->key.specified == AVTAB_ALLOWED) avd->allowed |= node->datum.data; else if (node->key.specified == AVTAB_AUDITALLOW) avd->auditallow |= node->datum.data; else if (node->key.specified == AVTAB_AUDITDENY) avd->auditdeny &= node->datum.data; } /* Check conditional av table for additional permissions */ cond_compute_av(&policydb->te_cond_avtab, &avkey, avd); } } if (requested & ~avd->allowed) { if (reason) *reason |= SEPOL_COMPUTEAV_TE; requested &= avd->allowed; } /* * Remove any permissions prohibited by a constraint (this includes * the MLS policy). */ constraint = tclass_datum->constraints; while (constraint) { if ((constraint->permissions & (avd->allowed)) && !constraint_expr_eval_reason(scontext, tcontext, NULL, tclass, constraint, r_buf, flags)) { avd->allowed = (avd->allowed) & ~(constraint->permissions); } constraint = constraint->next; } if (requested & ~avd->allowed) { if (reason) *reason |= SEPOL_COMPUTEAV_CONS; requested &= avd->allowed; } /* * If checking process transition permission and the * role is changing, then check the (current_role, new_role) * pair. */ if (tclass == policydb->process_class && (avd->allowed & policydb->process_trans_dyntrans) && scontext->role != tcontext->role) { for (ra = policydb->role_allow; ra; ra = ra->next) { if (scontext->role == ra->role && tcontext->role == ra->new_role) break; } if (!ra) avd->allowed &= ~policydb->process_trans_dyntrans; } if (requested & ~avd->allowed) { if (reason) *reason |= SEPOL_COMPUTEAV_RBAC; requested &= avd->allowed; } type_attribute_bounds_av(scontext, tcontext, tclass, requested, avd, reason); return 0; } /* * sepol_validate_transition_reason_buffer - the reason buffer is realloc'd * in the constraint_expr_eval_reason() function. */ 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) { 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 sepol_compute_av_reason(sepol_security_id_t ssid, sepol_security_id_t tsid, sepol_security_class_t tclass, sepol_access_vector_t requested, struct sepol_av_decision *avd, unsigned int *reason) { context_struct_t *scontext = 0, *tcontext = 0; int rc = 0; scontext = sepol_sidtab_search(sidtab, ssid); if (!scontext) { ERR(NULL, "unrecognized source SID %d", ssid); rc = -EINVAL; goto out; } tcontext = sepol_sidtab_search(sidtab, tsid); if (!tcontext) { ERR(NULL, "unrecognized target SID %d", tsid); rc = -EINVAL; goto out; } rc = context_struct_compute_av(scontext, tcontext, tclass, requested, avd, reason, NULL, 0); out: return rc; } /* * sepol_compute_av_reason_buffer - the reason buffer is malloc'd to * REASON_BUF_SIZE. If the buffer size is exceeded, then it is realloc'd * in the constraint_expr_eval_reason() function. */ int sepol_compute_av_reason_buffer(sepol_security_id_t ssid, sepol_security_id_t tsid, sepol_security_class_t tclass, sepol_access_vector_t requested, struct sepol_av_decision *avd, unsigned int *reason, char **reason_buf, unsigned int flags) { context_struct_t *scontext = 0, *tcontext = 0; int rc = 0; scontext = sepol_sidtab_search(sidtab, ssid); if (!scontext) { ERR(NULL, "unrecognized source SID %d", ssid); rc = -EINVAL; goto out; } tcontext = sepol_sidtab_search(sidtab, tsid); if (!tcontext) { ERR(NULL, "unrecognized target SID %d", tsid); rc = -EINVAL; goto out; } /* * Set the buffer to NULL as constraints may not be processed. * If a buffer is required, then the routines in * constraint_expr_eval_reason will realloc in REASON_BUF_SIZE * chunks (as it gets called for each constraint processed). * We just make sure these start from zero. */ *reason_buf = NULL; reason_buf_used = 0; reason_buf_len = 0; rc = context_struct_compute_av(scontext, tcontext, tclass, requested, avd, reason, reason_buf, flags); out: return rc; } int sepol_compute_av(sepol_security_id_t ssid, sepol_security_id_t tsid, sepol_security_class_t tclass, sepol_access_vector_t requested, struct sepol_av_decision *avd) { unsigned int reason = 0; return sepol_compute_av_reason(ssid, tsid, tclass, requested, avd, &reason); } /* * Return a class ID associated with the class string specified by * class_name. */ int sepol_string_to_security_class(const char *class_name, sepol_security_class_t *tclass) { class_datum_t *tclass_datum; tclass_datum = hashtab_search(policydb->p_classes.table, class_name); if (!tclass_datum) { ERR(NULL, "unrecognized class %s", class_name); return STATUS_ERR; } *tclass = tclass_datum->s.value; return STATUS_SUCCESS; } /* * Return access vector bit associated with the class ID and permission * string. */ int sepol_string_to_av_perm(sepol_security_class_t tclass, const char *perm_name, sepol_access_vector_t *av) { class_datum_t *tclass_datum; perm_datum_t *perm_datum; if (!tclass || tclass > policydb->p_classes.nprim) { ERR(NULL, "unrecognized class %d", tclass); return -EINVAL; } tclass_datum = policydb->class_val_to_struct[tclass - 1]; /* Check for unique perms then the common ones (if any) */ perm_datum = (perm_datum_t *) hashtab_search(tclass_datum->permissions.table, perm_name); if (perm_datum != NULL) { *av = UINT32_C(1) << (perm_datum->s.value - 1); return STATUS_SUCCESS; } if (tclass_datum->comdatum == NULL) goto out; perm_datum = (perm_datum_t *) hashtab_search(tclass_datum->comdatum->permissions.table, perm_name); if (perm_datum != NULL) { *av = UINT32_C(1) << (perm_datum->s.value - 1); return STATUS_SUCCESS; } out: ERR(NULL, "could not convert %s to av bit", perm_name); return STATUS_ERR; } const char *sepol_av_perm_to_string(sepol_security_class_t tclass, sepol_access_vector_t av) { static char avbuf[1024]; char *avstr = sepol_av_to_string(policydb, tclass, av); size_t len; memset(avbuf, 0, sizeof(avbuf)); if (avstr) { len = strlen(avstr); if (len < sizeof(avbuf)) { strcpy(avbuf, avstr); } else { sprintf(avbuf, ""); } free(avstr); } else { sprintf(avbuf, ""); } return avbuf; } /* * Write the security context string representation of * the context associated with `sid' into a dynamically * allocated string of the correct size. Set `*scontext' * to point to this string and set `*scontext_len' to * the length of the string. */ int sepol_sid_to_context(sepol_security_id_t sid, sepol_security_context_t * scontext, size_t * scontext_len) { context_struct_t *context; int rc = 0; context = sepol_sidtab_search(sidtab, sid); if (!context) { ERR(NULL, "unrecognized SID %d", sid); rc = -EINVAL; goto out; } rc = context_to_string(NULL, policydb, context, scontext, scontext_len); out: return rc; } /* * Return a SID associated with the security context that * has the string representation specified by `scontext'. */ int sepol_context_to_sid(sepol_const_security_context_t scontext, size_t scontext_len, sepol_security_id_t * sid) { context_struct_t *context = NULL; /* First, create the context */ if (context_from_string(NULL, policydb, &context, scontext, scontext_len) < 0) goto err; /* Obtain the new sid */ if (sid && (sepol_sidtab_context_to_sid(sidtab, context, sid) < 0)) goto err; context_destroy(context); free(context); return STATUS_SUCCESS; err: if (context) { context_destroy(context); free(context); } ERR(NULL, "could not convert %s to sid", scontext); return STATUS_ERR; } static inline int compute_sid_handle_invalid_context(context_struct_t * scontext, context_struct_t * tcontext, sepol_security_class_t tclass, context_struct_t * newcontext) { if (selinux_enforcing) { return -EACCES; } else { sepol_security_context_t s, t, n; size_t slen, tlen, nlen; context_to_string(NULL, policydb, scontext, &s, &slen); context_to_string(NULL, policydb, tcontext, &t, &tlen); context_to_string(NULL, policydb, newcontext, &n, &nlen); ERR(NULL, "invalid context %s for " "scontext=%s tcontext=%s tclass=%s", n, s, t, policydb->p_class_val_to_name[tclass - 1]); free(s); free(t); free(n); return 0; } } static int sepol_compute_sid(sepol_security_id_t ssid, sepol_security_id_t tsid, sepol_security_class_t tclass, uint32_t specified, sepol_security_id_t * out_sid) { struct class_datum *cladatum = NULL; context_struct_t *scontext = 0, *tcontext = 0, newcontext; struct role_trans *roletr = 0; avtab_key_t avkey; avtab_datum_t *avdatum; avtab_ptr_t node; int rc = 0; scontext = sepol_sidtab_search(sidtab, ssid); if (!scontext) { ERR(NULL, "unrecognized SID %d", ssid); return -EINVAL; } tcontext = sepol_sidtab_search(sidtab, tsid); if (!tcontext) { ERR(NULL, "unrecognized SID %d", tsid); return -EINVAL; } if (tclass && tclass <= policydb->p_classes.nprim) cladatum = policydb->class_val_to_struct[tclass - 1]; context_init(&newcontext); /* Set the user identity. */ switch (specified) { case AVTAB_TRANSITION: case AVTAB_CHANGE: if (cladatum && cladatum->default_user == DEFAULT_TARGET) { newcontext.user = tcontext->user; } else { /* notice this gets both DEFAULT_SOURCE and unset */ /* Use the process user identity. */ newcontext.user = scontext->user; } break; case AVTAB_MEMBER: /* Use the related object owner. */ newcontext.user = tcontext->user; break; } /* Set the role to default values. */ if (cladatum && cladatum->default_role == DEFAULT_SOURCE) { newcontext.role = scontext->role; } else if (cladatum && cladatum->default_role == DEFAULT_TARGET) { newcontext.role = tcontext->role; } else { if (tclass == policydb->process_class) newcontext.role = scontext->role; else newcontext.role = OBJECT_R_VAL; } /* Set the type to default values. */ if (cladatum && cladatum->default_type == DEFAULT_SOURCE) { newcontext.type = scontext->type; } else if (cladatum && cladatum->default_type == DEFAULT_TARGET) { newcontext.type = tcontext->type; } else { if (tclass == policydb->process_class) { /* Use the type of process. */ newcontext.type = scontext->type; } else { /* Use the type of the related object. */ newcontext.type = tcontext->type; } } /* Look for a type transition/member/change rule. */ avkey.source_type = scontext->type; avkey.target_type = tcontext->type; avkey.target_class = tclass; avkey.specified = specified; avdatum = avtab_search(&policydb->te_avtab, &avkey); /* If no permanent rule, also check for enabled conditional rules */ if (!avdatum) { node = avtab_search_node(&policydb->te_cond_avtab, &avkey); for (; node != NULL; node = avtab_search_node_next(node, specified)) { if (node->key.specified & AVTAB_ENABLED) { avdatum = &node->datum; break; } } } if (avdatum) { /* Use the type from the type transition/member/change rule. */ newcontext.type = avdatum->data; } /* Check for class-specific changes. */ if (specified & AVTAB_TRANSITION) { /* Look for a role transition rule. */ for (roletr = policydb->role_tr; roletr; roletr = roletr->next) { if (roletr->role == scontext->role && roletr->type == tcontext->type && roletr->tclass == tclass) { /* Use the role transition rule. */ newcontext.role = roletr->new_role; break; } } } /* Set the MLS attributes. This is done last because it may allocate memory. */ rc = mls_compute_sid(policydb, scontext, tcontext, tclass, specified, &newcontext); if (rc) goto out; /* Check the validity of the context. */ if (!policydb_context_isvalid(policydb, &newcontext)) { rc = compute_sid_handle_invalid_context(scontext, tcontext, tclass, &newcontext); if (rc) goto out; } /* Obtain the sid for the context. */ rc = sepol_sidtab_context_to_sid(sidtab, &newcontext, out_sid); out: context_destroy(&newcontext); return rc; } /* * Compute a SID to use for labeling a new object in the * class `tclass' based on a SID pair. */ int sepol_transition_sid(sepol_security_id_t ssid, sepol_security_id_t tsid, sepol_security_class_t tclass, sepol_security_id_t * out_sid) { return sepol_compute_sid(ssid, tsid, tclass, AVTAB_TRANSITION, out_sid); } /* * Compute a SID to use when selecting a member of a * polyinstantiated object of class `tclass' based on * a SID pair. */ int sepol_member_sid(sepol_security_id_t ssid, sepol_security_id_t tsid, sepol_security_class_t tclass, sepol_security_id_t * out_sid) { return sepol_compute_sid(ssid, tsid, tclass, AVTAB_MEMBER, out_sid); } /* * Compute a SID to use for relabeling an object in the * class `tclass' based on a SID pair. */ int sepol_change_sid(sepol_security_id_t ssid, sepol_security_id_t tsid, sepol_security_class_t tclass, sepol_security_id_t * out_sid) { return sepol_compute_sid(ssid, tsid, tclass, AVTAB_CHANGE, out_sid); } /* * Verify that each permission that is defined under the * existing policy is still defined with the same value * in the new policy. */ static int validate_perm(hashtab_key_t key, hashtab_datum_t datum, void *p) { hashtab_t h; perm_datum_t *perdatum, *perdatum2; h = (hashtab_t) p; perdatum = (perm_datum_t *) datum; perdatum2 = (perm_datum_t *) hashtab_search(h, key); if (!perdatum2) { ERR(NULL, "permission %s disappeared", key); return -1; } if (perdatum->s.value != perdatum2->s.value) { ERR(NULL, "the value of permissions %s changed", key); return -1; } return 0; } /* * Verify that each class that is defined under the * existing policy is still defined with the same * attributes in the new policy. */ static int validate_class(hashtab_key_t key, hashtab_datum_t datum, void *p) { policydb_t *newp; class_datum_t *cladatum, *cladatum2; newp = (policydb_t *) p; cladatum = (class_datum_t *) datum; cladatum2 = (class_datum_t *) hashtab_search(newp->p_classes.table, key); if (!cladatum2) { ERR(NULL, "class %s disappeared", key); return -1; } if (cladatum->s.value != cladatum2->s.value) { ERR(NULL, "the value of class %s changed", key); return -1; } if ((cladatum->comdatum && !cladatum2->comdatum) || (!cladatum->comdatum && cladatum2->comdatum)) { ERR(NULL, "the inherits clause for the access " "vector definition for class %s changed", key); return -1; } if (cladatum->comdatum) { if (hashtab_map (cladatum->comdatum->permissions.table, validate_perm, cladatum2->comdatum->permissions.table)) { ERR(NULL, " in the access vector definition " "for class %s", key); return -1; } } if (hashtab_map(cladatum->permissions.table, validate_perm, cladatum2->permissions.table)) { ERR(NULL, " in access vector definition for class %s", key); return -1; } return 0; } /* Clone the SID into the new SID table. */ static int clone_sid(sepol_security_id_t sid, context_struct_t * context, void *arg) { sidtab_t *s = arg; return sepol_sidtab_insert(s, sid, context); } static inline int convert_context_handle_invalid_context(context_struct_t * context) { if (selinux_enforcing) { return -EINVAL; } else { sepol_security_context_t s; size_t len; context_to_string(NULL, policydb, context, &s, &len); ERR(NULL, "context %s is invalid", s); free(s); return 0; } } typedef struct { policydb_t *oldp; policydb_t *newp; } convert_context_args_t; /* * Convert the values in the security context * structure `c' from the values specified * in the policy `p->oldp' to the values specified * in the policy `p->newp'. Verify that the * context is valid under the new policy. */ static int convert_context(sepol_security_id_t key __attribute__ ((unused)), context_struct_t * c, void *p) { convert_context_args_t *args; context_struct_t oldc; role_datum_t *role; type_datum_t *typdatum; user_datum_t *usrdatum; sepol_security_context_t s; size_t len; int rc = -EINVAL; args = (convert_context_args_t *) p; if (context_cpy(&oldc, c)) return -ENOMEM; /* Convert the user. */ usrdatum = (user_datum_t *) hashtab_search(args->newp->p_users.table, args->oldp-> p_user_val_to_name[c->user - 1]); if (!usrdatum) { goto bad; } c->user = usrdatum->s.value; /* Convert the role. */ role = (role_datum_t *) hashtab_search(args->newp->p_roles.table, args->oldp-> p_role_val_to_name[c->role - 1]); if (!role) { goto bad; } c->role = role->s.value; /* Convert the type. */ typdatum = (type_datum_t *) hashtab_search(args->newp->p_types.table, args->oldp->p_type_val_to_name[c->type - 1]); if (!typdatum) { goto bad; } c->type = typdatum->s.value; rc = mls_convert_context(args->oldp, args->newp, c); if (rc) goto bad; /* Check the validity of the new context. */ if (!policydb_context_isvalid(args->newp, c)) { rc = convert_context_handle_invalid_context(&oldc); if (rc) goto bad; } context_destroy(&oldc); return 0; bad: context_to_string(NULL, policydb, &oldc, &s, &len); context_destroy(&oldc); ERR(NULL, "invalidating context %s", s); free(s); return rc; } /* Reading from a policy "file". */ int next_entry(void *buf, struct policy_file *fp, size_t bytes) { size_t nread; switch (fp->type) { case PF_USE_STDIO: nread = fread(buf, bytes, 1, fp->fp); if (nread != 1) return -1; break; case PF_USE_MEMORY: if (bytes > fp->len) { errno = EOVERFLOW; return -1; } memcpy(buf, fp->data, bytes); fp->data += bytes; fp->len -= bytes; break; default: errno = EINVAL; return -1; } return 0; } size_t put_entry(const void *ptr, size_t size, size_t n, struct policy_file *fp) { size_t bytes; if (__builtin_mul_overflow(size, n, &bytes)) return 0; switch (fp->type) { case PF_USE_STDIO: return fwrite(ptr, size, n, fp->fp); case PF_USE_MEMORY: if (bytes > fp->len) { errno = ENOSPC; return 0; } memcpy(fp->data, ptr, bytes); fp->data += bytes; fp->len -= bytes; return n; case PF_LEN: fp->len += bytes; return n; default: return 0; } return 0; } /* * Reads a string and null terminates it from the policy file. * This is a port of str_read from the SE Linux kernel code. * * It returns: * 0 - Success * -1 - Failure with errno set */ int str_read(char **strp, struct policy_file *fp, size_t len) { int rc; char *str; if (zero_or_saturated(len) || exceeds_available_bytes(fp, len, sizeof(char))) { errno = EINVAL; return -1; } str = malloc(len + 1); if (!str) return -1; /* it's expected the caller should free the str */ *strp = str; /* next_entry sets errno */ rc = next_entry(str, fp, len); if (rc) return rc; str[len] = '\0'; return 0; } /* * Read a new set of configuration data from * a policy database binary representation file. * * Verify that each class that is defined under the * existing policy is still defined with the same * attributes in the new policy. * * Convert the context structures in the SID table to the * new representation and verify that all entries * in the SID table are valid under the new policy. * * Change the active policy database to use the new * configuration data. * * Reset the access vector cache. */ int sepol_load_policy(void *data, size_t len) { policydb_t oldpolicydb, newpolicydb; sidtab_t oldsidtab, newsidtab; convert_context_args_t args; int rc = 0; struct policy_file file, *fp; policy_file_init(&file); file.type = PF_USE_MEMORY; file.data = data; file.len = len; fp = &file; if (policydb_init(&newpolicydb)) return -ENOMEM; if (policydb_read(&newpolicydb, fp, 1)) { policydb_destroy(&mypolicydb); return -EINVAL; } sepol_sidtab_init(&newsidtab); /* Verify that the existing classes did not change. */ if (hashtab_map (policydb->p_classes.table, validate_class, &newpolicydb)) { ERR(NULL, "the definition of an existing class changed"); rc = -EINVAL; goto err; } /* Clone the SID table. */ sepol_sidtab_shutdown(sidtab); if (sepol_sidtab_map(sidtab, clone_sid, &newsidtab)) { rc = -ENOMEM; goto err; } /* Convert the internal representations of contexts in the new SID table and remove invalid SIDs. */ args.oldp = policydb; args.newp = &newpolicydb; sepol_sidtab_map_remove_on_error(&newsidtab, convert_context, &args); /* Save the old policydb and SID table to free later. */ memcpy(&oldpolicydb, policydb, sizeof *policydb); sepol_sidtab_set(&oldsidtab, sidtab); /* Install the new policydb and SID table. */ memcpy(policydb, &newpolicydb, sizeof *policydb); sepol_sidtab_set(sidtab, &newsidtab); /* Free the old policydb and SID table. */ policydb_destroy(&oldpolicydb); sepol_sidtab_destroy(&oldsidtab); return 0; err: sepol_sidtab_destroy(&newsidtab); policydb_destroy(&newpolicydb); return rc; } /* * Return the SIDs to use for an unlabeled file system * that is being mounted from the device with the * the kdevname `name'. The `fs_sid' SID is returned for * the file system and the `file_sid' SID is returned * for all files within that file system. */ int sepol_fs_sid(char *name, sepol_security_id_t * fs_sid, sepol_security_id_t * file_sid) { int rc = 0; ocontext_t *c; c = policydb->ocontexts[OCON_FS]; while (c) { if (strcmp(c->u.name, name) == 0) break; c = c->next; } if (c) { if (!c->sid[0] || !c->sid[1]) { rc = sepol_sidtab_context_to_sid(sidtab, &c->context[0], &c->sid[0]); if (rc) goto out; rc = sepol_sidtab_context_to_sid(sidtab, &c->context[1], &c->sid[1]); if (rc) goto out; } *fs_sid = c->sid[0]; *file_sid = c->sid[1]; } else { *fs_sid = SECINITSID_FS; *file_sid = SECINITSID_FILE; } out: return rc; } /* * Return the SID of the ibpkey specified by * `subnet prefix', and `pkey number'. */ int sepol_ibpkey_sid(uint64_t subnet_prefix, uint16_t pkey, sepol_security_id_t *out_sid) { ocontext_t *c; int rc = 0; c = policydb->ocontexts[OCON_IBPKEY]; while (c) { if (c->u.ibpkey.low_pkey <= pkey && c->u.ibpkey.high_pkey >= pkey && subnet_prefix == c->u.ibpkey.subnet_prefix) break; c = c->next; } if (c) { if (!c->sid[0]) { rc = sepol_sidtab_context_to_sid(sidtab, &c->context[0], &c->sid[0]); if (rc) goto out; } *out_sid = c->sid[0]; } else { *out_sid = SECINITSID_UNLABELED; } out: return rc; } /* * Return the SID of the subnet management interface specified by * `device name', and `port'. */ int sepol_ibendport_sid(char *dev_name, uint8_t port, sepol_security_id_t *out_sid) { ocontext_t *c; int rc = 0; c = policydb->ocontexts[OCON_IBENDPORT]; while (c) { if (c->u.ibendport.port == port && !strcmp(dev_name, c->u.ibendport.dev_name)) break; c = c->next; } if (c) { if (!c->sid[0]) { rc = sepol_sidtab_context_to_sid(sidtab, &c->context[0], &c->sid[0]); if (rc) goto out; } *out_sid = c->sid[0]; } else { *out_sid = SECINITSID_UNLABELED; } out: return rc; } /* * Return the SID of the port specified by * `domain', `type', `protocol', and `port'. */ int sepol_port_sid(uint16_t domain __attribute__ ((unused)), uint16_t type __attribute__ ((unused)), uint8_t protocol, uint16_t port, sepol_security_id_t * out_sid) { ocontext_t *c; int rc = 0; c = policydb->ocontexts[OCON_PORT]; while (c) { if (c->u.port.protocol == protocol && c->u.port.low_port <= port && c->u.port.high_port >= port) break; c = c->next; } if (c) { if (!c->sid[0]) { rc = sepol_sidtab_context_to_sid(sidtab, &c->context[0], &c->sid[0]); if (rc) goto out; } *out_sid = c->sid[0]; } else { *out_sid = SECINITSID_PORT; } out: return rc; } /* * Return the SIDs to use for a network interface * with the name `name'. The `if_sid' SID is returned for * the interface and the `msg_sid' SID is returned as * the default SID for messages received on the * interface. */ int sepol_netif_sid(char *name, sepol_security_id_t * if_sid, sepol_security_id_t * msg_sid) { int rc = 0; ocontext_t *c; c = policydb->ocontexts[OCON_NETIF]; while (c) { if (strcmp(name, c->u.name) == 0) break; c = c->next; } if (c) { if (!c->sid[0] || !c->sid[1]) { rc = sepol_sidtab_context_to_sid(sidtab, &c->context[0], &c->sid[0]); if (rc) goto out; rc = sepol_sidtab_context_to_sid(sidtab, &c->context[1], &c->sid[1]); if (rc) goto out; } *if_sid = c->sid[0]; *msg_sid = c->sid[1]; } else { *if_sid = SECINITSID_NETIF; *msg_sid = SECINITSID_NETMSG; } out: return rc; } static int match_ipv6_addrmask(uint32_t * input, uint32_t * addr, uint32_t * mask) { int i, fail = 0; for (i = 0; i < 4; i++) if (addr[i] != (input[i] & mask[i])) { fail = 1; break; } return !fail; } /* * Return the SID of the node specified by the address * `addrp' where `addrlen' is the length of the address * in bytes and `domain' is the communications domain or * address family in which the address should be interpreted. */ int sepol_node_sid(uint16_t domain, void *addrp, size_t addrlen, sepol_security_id_t * out_sid) { int rc = 0; ocontext_t *c; switch (domain) { case AF_INET:{ uint32_t addr; if (addrlen != sizeof(uint32_t)) { rc = -EINVAL; goto out; } addr = *((uint32_t *) addrp); c = policydb->ocontexts[OCON_NODE]; while (c) { if (c->u.node.addr == (addr & c->u.node.mask)) break; c = c->next; } break; } case AF_INET6: if (addrlen != sizeof(uint64_t) * 2) { rc = -EINVAL; goto out; } c = policydb->ocontexts[OCON_NODE6]; while (c) { if (match_ipv6_addrmask(addrp, c->u.node6.addr, c->u.node6.mask)) break; c = c->next; } break; default: *out_sid = SECINITSID_NODE; goto out; } if (c) { if (!c->sid[0]) { rc = sepol_sidtab_context_to_sid(sidtab, &c->context[0], &c->sid[0]); if (rc) goto out; } *out_sid = c->sid[0]; } else { *out_sid = SECINITSID_NODE; } out: return rc; } /* * Generate the set of SIDs for legal security contexts * for a given user that can be reached by `fromsid'. * Set `*sids' to point to a dynamically allocated * array containing the set of SIDs. Set `*nel' to the * number of elements in the array. */ #define SIDS_NEL 25 int sepol_get_user_sids(sepol_security_id_t fromsid, char *username, sepol_security_id_t ** sids, uint32_t * nel) { context_struct_t *fromcon, usercon; sepol_security_id_t *mysids, *mysids2, sid; uint32_t mynel = 0, maxnel = SIDS_NEL; user_datum_t *user; role_datum_t *role; struct sepol_av_decision avd; int rc = 0; unsigned int i, j, reason; ebitmap_node_t *rnode, *tnode; fromcon = sepol_sidtab_search(sidtab, fromsid); if (!fromcon) { rc = -EINVAL; goto out; } user = (user_datum_t *) hashtab_search(policydb->p_users.table, username); if (!user) { rc = -EINVAL; goto out; } usercon.user = user->s.value; mysids = calloc(maxnel, sizeof(sepol_security_id_t)); if (!mysids) { rc = -ENOMEM; goto out; } ebitmap_for_each_positive_bit(&user->roles.roles, rnode, i) { role = policydb->role_val_to_struct[i]; usercon.role = i + 1; ebitmap_for_each_positive_bit(&role->types.types, tnode, j) { usercon.type = j + 1; if (usercon.type == fromcon->type) continue; if (mls_setup_user_range (fromcon, user, &usercon, policydb->mls)) continue; rc = context_struct_compute_av(fromcon, &usercon, policydb->process_class, policydb->process_trans, &avd, &reason, NULL, 0); if (rc || !(avd.allowed & policydb->process_trans)) continue; rc = sepol_sidtab_context_to_sid(sidtab, &usercon, &sid); if (rc) { free(mysids); goto out; } if (mynel < maxnel) { mysids[mynel++] = sid; } else { maxnel += SIDS_NEL; mysids2 = calloc(maxnel, sizeof(sepol_security_id_t)); if (!mysids2) { rc = -ENOMEM; free(mysids); goto out; } memcpy(mysids2, mysids, mynel * sizeof(sepol_security_id_t)); free(mysids); mysids = mysids2; mysids[mynel++] = sid; } } } *sids = mysids; *nel = mynel; out: return rc; } /* * Return the SID to use for a file in a filesystem * that cannot support a persistent label mapping or use another * fixed labeling behavior like transition SIDs or task SIDs. */ int sepol_genfs_sid(const char *fstype, const char *path, sepol_security_class_t sclass, sepol_security_id_t * sid) { size_t len; genfs_t *genfs; ocontext_t *c; int rc = 0, cmp = 0; for (genfs = policydb->genfs; genfs; genfs = genfs->next) { cmp = strcmp(fstype, genfs->fstype); if (cmp <= 0) break; } if (!genfs || cmp) { *sid = SECINITSID_UNLABELED; rc = -ENOENT; goto out; } for (c = genfs->head; c; c = c->next) { len = strlen(c->u.name); if ((!c->v.sclass || sclass == c->v.sclass) && (strncmp(c->u.name, path, len) == 0)) break; } if (!c) { *sid = SECINITSID_UNLABELED; rc = -ENOENT; goto out; } if (!c->sid[0]) { rc = sepol_sidtab_context_to_sid(sidtab, &c->context[0], &c->sid[0]); if (rc) goto out; } *sid = c->sid[0]; out: return rc; } int sepol_fs_use(const char *fstype, unsigned int *behavior, sepol_security_id_t * sid) { int rc = 0; ocontext_t *c; c = policydb->ocontexts[OCON_FSUSE]; while (c) { if (strcmp(fstype, c->u.name) == 0) break; c = c->next; } if (c) { *behavior = c->v.behavior; if (!c->sid[0]) { rc = sepol_sidtab_context_to_sid(sidtab, &c->context[0], &c->sid[0]); if (rc) goto out; } *sid = c->sid[0]; } else { rc = sepol_genfs_sid(fstype, "/", policydb->dir_class, sid); if (rc) { *behavior = SECURITY_FS_USE_NONE; rc = 0; } else { *behavior = SECURITY_FS_USE_GENFS; } } out: return rc; } /* FLASK */ libsepol-3.8.1/src/sidtab.c000066400000000000000000000125541476211737200155560ustar00rootroot00000000000000 /* Author : Stephen Smalley, */ /* FLASK */ /* * Implementation of the SID table type. */ #include #include #include #include #include #include "flask.h" #include "private.h" #define SIDTAB_HASH(sid) \ (sid & SIDTAB_HASH_MASK) #define INIT_SIDTAB_LOCK(s) #define SIDTAB_LOCK(s) #define SIDTAB_UNLOCK(s) int sepol_sidtab_init(sidtab_t * s) { s->htable = calloc(SIDTAB_SIZE, sizeof(sidtab_ptr_t)); if (!s->htable) return -ENOMEM; s->nel = 0; s->next_sid = 1; s->shutdown = 0; INIT_SIDTAB_LOCK(s); return 0; } int sepol_sidtab_insert(sidtab_t * s, sepol_security_id_t sid, context_struct_t * context) { int hvalue; sidtab_node_t *prev, *cur, *newnode; if (!s || !s->htable) return -ENOMEM; hvalue = SIDTAB_HASH(sid); prev = NULL; cur = s->htable[hvalue]; while (cur != NULL && sid > cur->sid) { prev = cur; cur = cur->next; } if (cur && sid == cur->sid) { errno = EEXIST; return -EEXIST; } newnode = (sidtab_node_t *) malloc(sizeof(sidtab_node_t)); if (newnode == NULL) return -ENOMEM; newnode->sid = sid; if (context_cpy(&newnode->context, context)) { free(newnode); return -ENOMEM; } if (prev) { newnode->next = prev->next; prev->next = newnode; } else { newnode->next = s->htable[hvalue]; s->htable[hvalue] = newnode; } s->nel++; if (sid >= s->next_sid) s->next_sid = sid + 1; return 0; } context_struct_t *sepol_sidtab_search(sidtab_t * s, sepol_security_id_t sid) { int hvalue; sidtab_node_t *cur; if (!s || !s->htable) return NULL; hvalue = SIDTAB_HASH(sid); cur = s->htable[hvalue]; while (cur != NULL && sid > cur->sid) cur = cur->next; if (cur == NULL || sid != cur->sid) { /* Remap invalid SIDs to the unlabeled SID. */ sid = SECINITSID_UNLABELED; hvalue = SIDTAB_HASH(sid); cur = s->htable[hvalue]; while (cur != NULL && sid > cur->sid) cur = cur->next; if (!cur || sid != cur->sid) return NULL; } return &cur->context; } int sepol_sidtab_map(sidtab_t * s, int (*apply) (sepol_security_id_t sid, context_struct_t * context, void *args), void *args) { int i, ret; sidtab_node_t *cur; if (!s || !s->htable) return 0; for (i = 0; i < SIDTAB_SIZE; i++) { cur = s->htable[i]; while (cur != NULL) { ret = apply(cur->sid, &cur->context, args); if (ret) return ret; cur = cur->next; } } return 0; } void sepol_sidtab_map_remove_on_error(sidtab_t * s, int (*apply) (sepol_security_id_t sid, context_struct_t * context, void *args), void *args) { int i, ret; sidtab_node_t *last, *cur, *temp; if (!s || !s->htable) return; for (i = 0; i < SIDTAB_SIZE; i++) { last = NULL; cur = s->htable[i]; while (cur != NULL) { ret = apply(cur->sid, &cur->context, args); if (ret) { if (last) { last->next = cur->next; } else { s->htable[i] = cur->next; } temp = cur; cur = cur->next; context_destroy(&temp->context); free(temp); s->nel--; } else { last = cur; cur = cur->next; } } } return; } static inline sepol_security_id_t sepol_sidtab_search_context(sidtab_t * s, context_struct_t * context) { int i; sidtab_node_t *cur; for (i = 0; i < SIDTAB_SIZE; i++) { cur = s->htable[i]; while (cur != NULL) { if (context_cmp(&cur->context, context)) return cur->sid; cur = cur->next; } } return 0; } int sepol_sidtab_context_to_sid(sidtab_t * s, context_struct_t * context, sepol_security_id_t * out_sid) { sepol_security_id_t sid; int ret = 0; *out_sid = SEPOL_SECSID_NULL; sid = sepol_sidtab_search_context(s, context); if (!sid) { SIDTAB_LOCK(s); /* Rescan now that we hold the lock. */ sid = sepol_sidtab_search_context(s, context); if (sid) goto unlock_out; /* No SID exists for the context. Allocate a new one. */ if (s->next_sid == UINT_MAX || s->shutdown) { ret = -ENOMEM; goto unlock_out; } sid = s->next_sid++; ret = sepol_sidtab_insert(s, sid, context); if (ret) s->next_sid--; unlock_out: SIDTAB_UNLOCK(s); } if (ret) return ret; *out_sid = sid; return 0; } void sepol_sidtab_hash_eval(sidtab_t * h, char *tag) { int i, chain_len, slots_used, max_chain_len; sidtab_node_t *cur; slots_used = 0; max_chain_len = 0; for (i = 0; i < SIDTAB_SIZE; i++) { cur = h->htable[i]; if (cur) { slots_used++; chain_len = 0; while (cur) { chain_len++; cur = cur->next; } if (chain_len > max_chain_len) max_chain_len = chain_len; } } printf ("%s: %d entries and %d/%d buckets used, longest chain length %d\n", tag, h->nel, slots_used, SIDTAB_SIZE, max_chain_len); } void sepol_sidtab_destroy(sidtab_t * s) { int i; sidtab_ptr_t cur, temp; if (!s || !s->htable) return; for (i = 0; i < SIDTAB_SIZE; i++) { cur = s->htable[i]; while (cur != NULL) { temp = cur; cur = cur->next; context_destroy(&temp->context); free(temp); } s->htable[i] = NULL; } free(s->htable); s->htable = NULL; s->nel = 0; s->next_sid = 1; } void sepol_sidtab_set(sidtab_t * dst, sidtab_t * src) { SIDTAB_LOCK(src); dst->htable = src->htable; dst->nel = src->nel; dst->next_sid = src->next_sid; dst->shutdown = 0; SIDTAB_UNLOCK(src); } void sepol_sidtab_shutdown(sidtab_t * s) { SIDTAB_LOCK(s); s->shutdown = 1; SIDTAB_UNLOCK(s); } /* FLASK */ libsepol-3.8.1/src/symtab.c000066400000000000000000000016441476211737200156050ustar00rootroot00000000000000 /* Author : Stephen Smalley, */ /* FLASK */ /* * Implementation of the symbol table type. */ #include #include "private.h" #include #include ignore_unsigned_overflow_ static unsigned int symhash(hashtab_t h, const_hashtab_key_t key) { unsigned int hash = 5381; unsigned char c; while ((c = *(unsigned const char *)key++)) hash = ((hash << 5) + hash) ^ c; return hash & (h->size - 1); } static int symcmp(hashtab_t h __attribute__ ((unused)), const_hashtab_key_t key1, const_hashtab_key_t key2) { return strcmp(key1, key2); } int symtab_init(symtab_t * s, unsigned int size) { s->table = hashtab_create(symhash, symcmp, size); if (!s->table) return -1; s->nprim = 0; return 0; } void symtab_destroy(symtab_t * s) { if (!s) return; if (s->table) hashtab_destroy(s->table); return; } /* FLASK */ libsepol-3.8.1/src/user_internal.h000066400000000000000000000002011476211737200171510ustar00rootroot00000000000000#ifndef _SEPOL_USER_INTERNAL_H_ #define _SEPOL_USER_INTERNAL_H_ #include #include #endif libsepol-3.8.1/src/user_record.c000066400000000000000000000162161476211737200166230ustar00rootroot00000000000000#include #include #include #include "user_internal.h" #include "debug.h" #include "private.h" struct sepol_user { /* This user's name */ char *name; /* This user's mls level (only required for mls) */ char *mls_level; /* This user's mls range (only required for mls) */ char *mls_range; /* The role array */ char **roles; /* The number of roles */ unsigned int num_roles; }; struct sepol_user_key { /* This user's name */ char *name; }; int sepol_user_key_create(sepol_handle_t * handle, const char *name, sepol_user_key_t ** key_ptr) { sepol_user_key_t *tmp_key = (sepol_user_key_t *) malloc(sizeof(sepol_user_key_t)); if (!tmp_key) { ERR(handle, "out of memory, " "could not create selinux user key"); return STATUS_ERR; } tmp_key->name = strdup(name); if (!tmp_key->name) { ERR(handle, "out of memory, could not create selinux user key"); free(tmp_key); return STATUS_ERR; } *key_ptr = tmp_key; return STATUS_SUCCESS; } void sepol_user_key_unpack(const sepol_user_key_t * key, const char **name) { *name = key->name; } int sepol_user_key_extract(sepol_handle_t * handle, const sepol_user_t * user, sepol_user_key_t ** key_ptr) { if (sepol_user_key_create(handle, user->name, key_ptr) < 0) { ERR(handle, "could not extract key from user %s", user->name); return STATUS_ERR; } return STATUS_SUCCESS; } void sepol_user_key_free(sepol_user_key_t * key) { if (!key) return; free(key->name); free(key); } int sepol_user_compare(const sepol_user_t * user, const sepol_user_key_t * key) { return strcmp(user->name, key->name); } int sepol_user_compare2(const sepol_user_t * user, const sepol_user_t * user2) { return strcmp(user->name, user2->name); } /* Name */ const char *sepol_user_get_name(const sepol_user_t * user) { return user->name; } int sepol_user_set_name(sepol_handle_t * handle, sepol_user_t * user, const char *name) { char *tmp_name = strdup(name); if (!tmp_name) { ERR(handle, "out of memory, could not set name"); return STATUS_ERR; } free(user->name); user->name = tmp_name; return STATUS_SUCCESS; } /* MLS */ const char *sepol_user_get_mlslevel(const sepol_user_t * user) { return user->mls_level; } int sepol_user_set_mlslevel(sepol_handle_t * handle, sepol_user_t * user, const char *mls_level) { char *tmp_mls_level = strdup(mls_level); if (!tmp_mls_level) { ERR(handle, "out of memory, " "could not set MLS default level"); return STATUS_ERR; } free(user->mls_level); user->mls_level = tmp_mls_level; return STATUS_SUCCESS; } const char *sepol_user_get_mlsrange(const sepol_user_t * user) { return user->mls_range; } int sepol_user_set_mlsrange(sepol_handle_t * handle, sepol_user_t * user, const char *mls_range) { char *tmp_mls_range = strdup(mls_range); if (!tmp_mls_range) { ERR(handle, "out of memory, " "could not set MLS allowed range"); return STATUS_ERR; } free(user->mls_range); user->mls_range = tmp_mls_range; return STATUS_SUCCESS; } /* Roles */ int sepol_user_get_num_roles(const sepol_user_t * user) { return user->num_roles; } int sepol_user_add_role(sepol_handle_t * handle, sepol_user_t * user, const char *role) { char *role_cp; char **roles_realloc = NULL; if (sepol_user_has_role(user, role)) return STATUS_SUCCESS; role_cp = strdup(role); if (!role_cp) goto omem; roles_realloc = reallocarray(user->roles, user->num_roles + 1, sizeof(char *)); if (!roles_realloc) goto omem; user->num_roles++; user->roles = roles_realloc; user->roles[user->num_roles - 1] = role_cp; return STATUS_SUCCESS; omem: ERR(handle, "out of memory, could not add role %s", role); free(role_cp); free(roles_realloc); return STATUS_ERR; } int sepol_user_has_role(const sepol_user_t * user, const char *role) { unsigned int i; for (i = 0; i < user->num_roles; i++) if (!strcmp(user->roles[i], role)) return 1; return 0; } int sepol_user_set_roles(sepol_handle_t * handle, sepol_user_t * user, const char **roles_arr, unsigned int num_roles) { unsigned int i; char **tmp_roles = NULL; if (num_roles > 0) { /* First, make a copy */ tmp_roles = (char **)calloc(1, sizeof(char *) * num_roles); if (!tmp_roles) goto omem; for (i = 0; i < num_roles; i++) { tmp_roles[i] = strdup(roles_arr[i]); if (!tmp_roles[i]) goto omem; } } /* Apply other changes */ for (i = 0; i < user->num_roles; i++) free(user->roles[i]); free(user->roles); user->roles = tmp_roles; user->num_roles = num_roles; return STATUS_SUCCESS; omem: ERR(handle, "out of memory, could not allocate roles array for" "user %s", user->name); if (tmp_roles) { for (i = 0; i < num_roles; i++) { if (!tmp_roles[i]) break; free(tmp_roles[i]); } } free(tmp_roles); return STATUS_ERR; } int sepol_user_get_roles(sepol_handle_t * handle, const sepol_user_t * user, const char ***roles_arr, unsigned int *num_roles) { unsigned int i; const char **tmp_roles = (const char **)calloc(user->num_roles, sizeof(char *)); if (!tmp_roles) goto omem; for (i = 0; i < user->num_roles; i++) tmp_roles[i] = user->roles[i]; *roles_arr = tmp_roles; *num_roles = user->num_roles; return STATUS_SUCCESS; omem: ERR(handle, "out of memory, could not " "allocate roles array for user %s", user->name); free(tmp_roles); return STATUS_ERR; } void sepol_user_del_role(sepol_user_t * user, const char *role) { unsigned int i; for (i = 0; i < user->num_roles; i++) { if (!strcmp(user->roles[i], role)) { free(user->roles[i]); user->roles[i] = NULL; user->roles[i] = user->roles[user->num_roles - 1]; user->num_roles--; } } } /* Create */ int sepol_user_create(sepol_handle_t * handle, sepol_user_t ** user_ptr) { sepol_user_t *user = (sepol_user_t *) malloc(sizeof(sepol_user_t)); if (!user) { ERR(handle, "out of memory, " "could not create selinux user record"); return STATUS_ERR; } user->roles = NULL; user->num_roles = 0; user->name = NULL; user->mls_level = NULL; user->mls_range = NULL; *user_ptr = user; return STATUS_SUCCESS; } /* Deep copy clone */ int sepol_user_clone(sepol_handle_t * handle, const sepol_user_t * user, sepol_user_t ** user_ptr) { sepol_user_t *new_user = NULL; unsigned int i; if (sepol_user_create(handle, &new_user) < 0) goto err; if (sepol_user_set_name(handle, new_user, user->name) < 0) goto err; for (i = 0; i < user->num_roles; i++) { if (sepol_user_add_role(handle, new_user, user->roles[i]) < 0) goto err; } if (user->mls_level && (sepol_user_set_mlslevel(handle, new_user, user->mls_level) < 0)) goto err; if (user->mls_range && (sepol_user_set_mlsrange(handle, new_user, user->mls_range) < 0)) goto err; *user_ptr = new_user; return STATUS_SUCCESS; err: ERR(handle, "could not clone selinux user record"); sepol_user_free(new_user); return STATUS_ERR; } /* Destroy */ void sepol_user_free(sepol_user_t * user) { unsigned int i; if (!user) return; free(user->name); for (i = 0; i < user->num_roles; i++) free(user->roles[i]); free(user->roles); free(user->mls_level); free(user->mls_range); free(user); } libsepol-3.8.1/src/users.c000066400000000000000000000211011476211737200154350ustar00rootroot00000000000000#include #include #include #include "private.h" #include "debug.h" #include "handle.h" #include #include #include #include "user_internal.h" #include "mls.h" static int user_to_record(sepol_handle_t * handle, const policydb_t * policydb, int user_idx, sepol_user_t ** record) { const char *name = policydb->p_user_val_to_name[user_idx]; user_datum_t *usrdatum = policydb->user_val_to_struct[user_idx]; ebitmap_t *roles; ebitmap_node_t *rnode; unsigned bit; sepol_user_t *tmp_record = NULL; if (!usrdatum) goto err; roles = &(usrdatum->roles.roles); if (sepol_user_create(handle, &tmp_record) < 0) goto err; if (sepol_user_set_name(handle, tmp_record, name) < 0) goto err; /* Extract roles */ ebitmap_for_each_positive_bit(roles, rnode, bit) { char *role = policydb->p_role_val_to_name[bit]; if (sepol_user_add_role(handle, tmp_record, role) < 0) goto err; } /* Extract MLS info */ if (policydb->mls) { context_struct_t context; char *str; context_init(&context); if (mls_level_cpy(&context.range.level[0], &usrdatum->exp_dfltlevel) < 0) { ERR(handle, "could not copy MLS level"); context_destroy(&context); goto err; } if (mls_level_cpy(&context.range.level[1], &usrdatum->exp_dfltlevel) < 0) { ERR(handle, "could not copy MLS level"); context_destroy(&context); goto err; } if (mls_to_string(handle, policydb, &context, &str) < 0) { context_destroy(&context); goto err; } context_destroy(&context); if (sepol_user_set_mlslevel(handle, tmp_record, str) < 0) { free(str); goto err; } free(str); context_init(&context); if (mls_range_cpy(&context.range, &usrdatum->exp_range) < 0) { ERR(handle, "could not copy MLS range"); context_destroy(&context); goto err; } if (mls_to_string(handle, policydb, &context, &str) < 0) { context_destroy(&context); goto err; } context_destroy(&context); if (sepol_user_set_mlsrange(handle, tmp_record, str) < 0) { free(str); goto err; } free(str); } *record = tmp_record; return STATUS_SUCCESS; err: /* FIXME: handle error */ sepol_user_free(tmp_record); return STATUS_ERR; } int sepol_user_modify(sepol_handle_t * handle, sepol_policydb_t * p, const sepol_user_key_t * key, const sepol_user_t * user) { policydb_t *policydb = &p->p; /* For user data */ const char *cname, *cmls_level, *cmls_range; char *name = NULL; const char **roles = NULL; unsigned int num_roles = 0; /* Low-level representation */ user_datum_t *usrdatum = NULL; role_datum_t *roldatum; unsigned int i; context_struct_t context; unsigned bit; int new = 0; ebitmap_node_t *rnode; /* First, extract all the data */ sepol_user_key_unpack(key, &cname); cmls_level = sepol_user_get_mlslevel(user); cmls_range = sepol_user_get_mlsrange(user); /* Make sure that worked properly */ if (sepol_user_get_roles(handle, user, &roles, &num_roles) < 0) goto err; /* Now, see if a user exists */ usrdatum = hashtab_search(policydb->p_users.table, cname); /* If it does, we will modify it */ if (usrdatum) { int value_cp = usrdatum->s.value; user_datum_destroy(usrdatum); user_datum_init(usrdatum); usrdatum->s.value = value_cp; /* Otherwise, create a new one */ } else { usrdatum = (user_datum_t *) malloc(sizeof(user_datum_t)); if (!usrdatum) goto omem; user_datum_init(usrdatum); new = 1; } /* For every role */ for (i = 0; i < num_roles; i++) { /* Search for the role */ roldatum = hashtab_search(policydb->p_roles.table, roles[i]); if (!roldatum) { ERR(handle, "undefined role %s for user %s", roles[i], cname); goto err; } /* Set the role and every role it dominates */ ebitmap_for_each_positive_bit(&roldatum->dominates, rnode, bit) { if (ebitmap_set_bit(&(usrdatum->roles.roles), bit, 1)) goto omem; } } /* For MLS systems */ if (policydb->mls) { /* MLS level */ if (cmls_level == NULL) { ERR(handle, "MLS is enabled, but no MLS " "default level was defined for user %s", cname); goto err; } context_init(&context); if (mls_from_string(handle, policydb, cmls_level, &context) < 0) { context_destroy(&context); goto err; } if (mls_level_cpy(&usrdatum->exp_dfltlevel, &context.range.level[0]) < 0) { ERR(handle, "could not copy MLS level %s", cmls_level); context_destroy(&context); goto err; } context_destroy(&context); /* MLS range */ if (cmls_range == NULL) { ERR(handle, "MLS is enabled, but no MLS" "range was defined for user %s", cname); goto err; } context_init(&context); if (mls_from_string(handle, policydb, cmls_range, &context) < 0) { context_destroy(&context); goto err; } if (mls_range_cpy(&usrdatum->exp_range, &context.range) < 0) { ERR(handle, "could not copy MLS range %s", cmls_range); context_destroy(&context); goto err; } context_destroy(&context); } else if (cmls_level != NULL || cmls_range != NULL) { ERR(handle, "MLS is disabled, but MLS level/range " "was found for user %s", cname); goto err; } /* If there are no errors, and this is a new user, add the user to policy */ if (new) { void *tmp_ptr; /* Ensure reverse lookup array has enough space */ tmp_ptr = reallocarray(policydb->user_val_to_struct, policydb->p_users.nprim + 1, sizeof(user_datum_t *)); if (!tmp_ptr) goto omem; policydb->user_val_to_struct = tmp_ptr; policydb->user_val_to_struct[policydb->p_users.nprim] = NULL; tmp_ptr = reallocarray(policydb->sym_val_to_name[SYM_USERS], policydb->p_users.nprim + 1, sizeof(char *)); if (!tmp_ptr) goto omem; policydb->sym_val_to_name[SYM_USERS] = tmp_ptr; policydb->p_user_val_to_name[policydb->p_users.nprim] = NULL; /* Need to copy the user name */ name = strdup(cname); if (!name) goto omem; /* Store user */ usrdatum->s.value = ++policydb->p_users.nprim; if (hashtab_insert(policydb->p_users.table, name, (hashtab_datum_t) usrdatum) < 0) goto omem; /* Set up reverse entry */ policydb->p_user_val_to_name[usrdatum->s.value - 1] = name; policydb->user_val_to_struct[usrdatum->s.value - 1] = usrdatum; name = NULL; /* Expand roles */ if (role_set_expand(&usrdatum->roles, &usrdatum->cache, policydb, NULL, NULL)) { ERR(handle, "unable to expand role set"); goto err; } } free(roles); return STATUS_SUCCESS; omem: ERR(handle, "out of memory"); err: ERR(handle, "could not load %s into policy", name); free(name); free(roles); if (new && usrdatum) { role_set_destroy(&usrdatum->roles); free(usrdatum); } return STATUS_ERR; } int sepol_user_exists(sepol_handle_t * handle __attribute__ ((unused)), const sepol_policydb_t * p, const sepol_user_key_t * key, int *response) { const policydb_t *policydb = &p->p; const char *cname; sepol_user_key_unpack(key, &cname); *response = (hashtab_search(policydb->p_users.table, cname) != NULL); return STATUS_SUCCESS; } int sepol_user_count(sepol_handle_t * handle __attribute__ ((unused)), const sepol_policydb_t * p, unsigned int *response) { const policydb_t *policydb = &p->p; *response = policydb->p_users.nprim; return STATUS_SUCCESS; } int sepol_user_query(sepol_handle_t * handle, const sepol_policydb_t * p, const sepol_user_key_t * key, sepol_user_t ** response) { const policydb_t *policydb = &p->p; user_datum_t *usrdatum = NULL; const char *cname; sepol_user_key_unpack(key, &cname); usrdatum = hashtab_search(policydb->p_users.table, cname); if (!usrdatum) { *response = NULL; return STATUS_SUCCESS; } if (user_to_record(handle, policydb, usrdatum->s.value - 1, response) < 0) goto err; return STATUS_SUCCESS; err: ERR(handle, "could not query user %s", cname); return STATUS_ERR; } int sepol_user_iterate(sepol_handle_t * handle, const sepol_policydb_t * p, int (*fn) (const sepol_user_t * user, void *fn_arg), void *arg) { const policydb_t *policydb = &p->p; unsigned int nusers = policydb->p_users.nprim; sepol_user_t *user = NULL; unsigned int i; /* For each user */ for (i = 0; i < nusers; i++) { int status; if (user_to_record(handle, policydb, i, &user) < 0) goto err; /* Invoke handler */ status = fn(user, arg); if (status < 0) goto err; sepol_user_free(user); user = NULL; /* Handler requested exit */ if (status > 0) break; } return STATUS_SUCCESS; err: ERR(handle, "could not iterate over users"); sepol_user_free(user); return STATUS_ERR; } libsepol-3.8.1/src/util.c000066400000000000000000000173741476211737200152720ustar00rootroot00000000000000/* Authors: Joshua Brindle * Jason Tang * * Copyright (C) 2005-2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include "private.h" struct val_to_name { unsigned int val; const char *name; }; /* Add an unsigned integer to a dynamically reallocated array. *cnt * is a reference pointer to the number of values already within array * *a; it will be incremented upon successfully appending i. If *a is * NULL then this function will create a new array (*cnt is reset to * 0). Return 0 on success, -1 on out of memory. */ int add_i_to_a(uint32_t i, uint32_t * cnt, uint32_t ** a) { uint32_t *new; if (cnt == NULL || *cnt == UINT32_MAX || a == NULL) return -1; /* FIX ME: This is not very elegant! We use an array that we * grow as new uint32_t are added to an array. But rather * than be smart about it, for now we realloc() the array each * time a new uint32_t is added! */ if (*a != NULL) new = (uint32_t *) reallocarray(*a, *cnt + 1, sizeof(uint32_t)); else { /* empty list */ *cnt = 0; new = (uint32_t *) malloc(sizeof(uint32_t)); } if (new == NULL) { return -1; } new[*cnt] = i; (*cnt)++; *a = new; return 0; } static int perm_name(hashtab_key_t key, hashtab_datum_t datum, void *data) { struct val_to_name *v = data; perm_datum_t *perdatum; perdatum = (perm_datum_t *) datum; if (v->val == perdatum->s.value) { v->name = key; return 1; } return 0; } char *sepol_av_to_string(const policydb_t *policydbp, sepol_security_class_t tclass, sepol_access_vector_t av) { struct val_to_name v; const class_datum_t *cladatum = policydbp->class_val_to_struct[tclass - 1]; uint32_t i; int rc; char *buffer = NULL, *p; int len; size_t remaining, size = 64; retry: if (__builtin_mul_overflow(size, 2, &size)) goto err; p = realloc(buffer, size); if (!p) goto err; *p = '\0'; /* Just in case there are no permissions */ buffer = p; remaining = size; for (i = 0; i < cladatum->permissions.nprim; i++) { if (av & (UINT32_C(1) << i)) { v.val = i + 1; rc = hashtab_map(cladatum->permissions.table, perm_name, &v); if (!rc && cladatum->comdatum) { rc = hashtab_map(cladatum->comdatum-> permissions.table, perm_name, &v); } if (rc == 1) { len = snprintf(p, remaining, " %s", v.name); if (len < 0) goto err; if ((size_t) len >= remaining) goto retry; p += len; remaining -= len; } } } return buffer; err: free(buffer); return NULL; } #define next_bit_in_range(i, p) (((i) + 1 < sizeof(p)*8) && xperm_test(((i) + 1), p)) char *sepol_extended_perms_to_string(const avtab_extended_perms_t *xperms) { uint16_t value; uint16_t low_bit; uint16_t low_value; unsigned int bit; unsigned int in_range; char *buffer = NULL, *p; int len; size_t remaining, size = 128; if ((xperms->specified != AVTAB_XPERMS_IOCTLFUNCTION) && (xperms->specified != AVTAB_XPERMS_IOCTLDRIVER) && (xperms->specified != AVTAB_XPERMS_NLMSG)) return NULL; retry: if (__builtin_mul_overflow(size, 2, &size)) goto err; p = realloc(buffer, size); if (!p) goto err; buffer = p; remaining = size; if ((xperms->specified == AVTAB_XPERMS_IOCTLFUNCTION) || (xperms->specified == AVTAB_XPERMS_IOCTLDRIVER)) { len = snprintf(p, remaining, "ioctl { "); } else { len = snprintf(p, remaining, "nlmsg { "); } if (len < 0 || (size_t)len >= remaining) goto err; p += len; remaining -= len; in_range = 0; for (bit = 0; bit < sizeof(xperms->perms)*8; bit++) { if (!xperm_test(bit, xperms->perms)) continue; if (in_range && next_bit_in_range(bit, xperms->perms)) { /* continue until high value found */ continue; } else if (next_bit_in_range(bit, xperms->perms)) { /* low value */ low_bit = bit; in_range = 1; continue; } if (xperms->specified == AVTAB_XPERMS_IOCTLFUNCTION || xperms->specified == AVTAB_XPERMS_NLMSG) { value = xperms->driver<<8 | bit; if (in_range) { low_value = xperms->driver<<8 | low_bit; len = snprintf(p, remaining, "0x%hx-0x%hx ", low_value, value); } else { len = snprintf(p, remaining, "0x%hx ", value); } } else if (xperms->specified == AVTAB_XPERMS_IOCTLDRIVER) { value = bit << 8; if (in_range) { low_value = low_bit << 8; len = snprintf(p, remaining, "0x%hx-0x%hx ", low_value, (uint16_t) (value|0xff)); } else { len = snprintf(p, remaining, "0x%hx-0x%hx ", value, (uint16_t) (value|0xff)); } } if (len < 0) goto err; if ((size_t) len >= remaining) goto retry; p += len; remaining -= len; if (in_range) in_range = 0; } len = snprintf(p, remaining, "}"); if (len < 0) goto err; if ((size_t) len >= remaining) goto retry; return buffer; err: free(buffer); return NULL; } /* * The tokenize and tokenize_str functions may be used to * replace sscanf to read tokens from buffers. */ /* Read a token from a buffer */ static inline int tokenize_str(char delim, char **str, const char **ptr, size_t *len) { const char *tmp_buf = *ptr; *str = NULL; while (**ptr != '\0') { if (isspace(delim) && isspace(**ptr)) { (*ptr)++; break; } else if (!isspace(delim) && **ptr == delim) { (*ptr)++; break; } (*ptr)++; } *len = *ptr - tmp_buf; /* If the end of the string has not been reached, this will ensure the * delimiter is not included when returning the token. */ if (**ptr != '\0') { (*len)--; } *str = strndup(tmp_buf, *len); if (!*str) { return -1; } /* Squash spaces if the delimiter is a whitespace character */ while (**ptr != '\0' && isspace(delim) && isspace(**ptr)) { (*ptr)++; } return 0; } /* * line_buf - Buffer containing string to tokenize. * delim - The delimiter used to tokenize line_buf. A whitespace delimiter will * be tokenized using isspace(). * num_args - The number of parameter entries to process. * ... - A 'char **' for each parameter. * returns - The number of items processed. * * This function calls tokenize_str() to do the actual string processing. The * caller is responsible for calling free() on each additional argument. The * function will not tokenize more than num_args and the last argument will * contain the remaining content of line_buf. If the delimiter is any whitespace * character, then all whitespace will be squashed. */ int tokenize(const char *line_buf, char delim, int num_args, ...) { char **arg; const char *buf_p; int rc, items; size_t arg_len = 0; va_list ap; buf_p = line_buf; /* Process the arguments */ va_start(ap, num_args); for (items = 0; items < num_args && *buf_p != '\0'; items++) { arg = va_arg(ap, char **); /* Save the remainder of the string in arg */ if (items == num_args - 1) { *arg = strdup(buf_p); if (*arg == NULL) { goto exit; } continue; } rc = tokenize_str(delim, arg, &buf_p, &arg_len); if (rc < 0) { goto exit; } } exit: va_end(ap); return items; } libsepol-3.8.1/src/write.c000066400000000000000000001771511476211737200154470ustar00rootroot00000000000000 /* Author : Stephen Smalley, */ /* * Updated: Trusted Computer Solutions, Inc. * * Support for enhanced MLS infrastructure. * * Updated: Frank Mayer and Karl MacMillan * * Added conditional policy language extensions * * Updated: Joshua Brindle and Jason Tang * * Module writing support * * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. * Copyright (C) 2003-2005 Tresys Technology, LLC * Copyright (C) 2017 Mellanox Technologies Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include "debug.h" #include "private.h" #include "mls.h" #define glblub_version ((p->policy_type == POLICY_KERN && \ p->policyvers >= POLICYDB_VERSION_GLBLUB) || \ (p->policy_type == POLICY_BASE && \ p->policyvers >= MOD_POLICYDB_VERSION_GLBLUB)) struct policy_data { struct policy_file *fp; struct policydb *p; }; static int avrule_write_list(policydb_t *p, avrule_t * avrules, struct policy_file *fp, unsigned conditional); static int ebitmap_write(ebitmap_t * e, struct policy_file *fp) { ebitmap_node_t *n; uint32_t buf[32], bit, count; uint64_t map; size_t items; buf[0] = cpu_to_le32(MAPSIZE); buf[1] = cpu_to_le32(e->highbit); count = 0; for (n = e->node; n; n = n->next) count++; buf[2] = cpu_to_le32(count); items = put_entry(buf, sizeof(uint32_t), 3, fp); if (items != 3) return POLICYDB_ERROR; for (n = e->node; n; n = n->next) { bit = cpu_to_le32(n->startbit); items = put_entry(&bit, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; map = cpu_to_le64(n->map); items = put_entry(&map, sizeof(uint64_t), 1, fp); if (items != 1) return POLICYDB_ERROR; } return POLICYDB_SUCCESS; } /* Ordering of datums in the original avtab format in the policy file. */ static uint16_t spec_order[] = { AVTAB_ALLOWED, AVTAB_AUDITDENY, AVTAB_AUDITALLOW, AVTAB_TRANSITION, AVTAB_CHANGE, AVTAB_MEMBER }; static int avtab_write_item(policydb_t * p, avtab_ptr_t cur, struct policy_file *fp, unsigned merge, unsigned commit, unsigned conditional, uint32_t * nel) { avtab_ptr_t node; uint8_t buf8; uint16_t buf16[4]; uint32_t buf32[10], lookup, val; size_t items, items2; unsigned set; unsigned int oldvers = (p->policy_type == POLICY_KERN && p->policyvers < POLICYDB_VERSION_AVTAB); unsigned int i; if (oldvers) { /* Generate the old avtab format. Requires merging similar entries if uncond avtab. */ if (merge) { if (cur->merged) return POLICYDB_SUCCESS; /* already merged by prior merge */ } items = 1; /* item 0 is used for the item count */ val = cur->key.source_type; buf32[items++] = cpu_to_le32(val); val = cur->key.target_type; buf32[items++] = cpu_to_le32(val); val = cur->key.target_class; buf32[items++] = cpu_to_le32(val); val = cur->key.specified & ~AVTAB_ENABLED; if (cur->key.specified & AVTAB_ENABLED) val |= AVTAB_ENABLED_OLD; set = 1; if (merge) { /* Merge specifier values for all similar (av or type) entries that have the same key. */ if (val & AVTAB_AV) lookup = AVTAB_AV; else if (val & AVTAB_TYPE) lookup = AVTAB_TYPE; else return POLICYDB_ERROR; for (node = avtab_search_node_next(cur, lookup); node; node = avtab_search_node_next(node, lookup)) { val |= (node->key.specified & ~AVTAB_ENABLED); set++; if (node->key.specified & AVTAB_ENABLED) val |= AVTAB_ENABLED_OLD; } } if (!(val & (AVTAB_AV | AVTAB_TYPE))) { ERR(fp->handle, "null entry"); return POLICYDB_ERROR; } if ((val & AVTAB_AV) && (val & AVTAB_TYPE)) { ERR(fp->handle, "entry has both access " "vectors and types"); return POLICYDB_ERROR; } buf32[items++] = cpu_to_le32(val); if (merge) { /* Include datums for all similar (av or type) entries that have the same key. */ for (i = 0; i < (sizeof(spec_order) / sizeof(spec_order[0])); i++) { if (val & spec_order[i]) { if (cur->key.specified & spec_order[i]) node = cur; else { node = avtab_search_node_next(cur, spec_order [i]); if (nel) (*nel)--; /* one less node */ } if (!node) { ERR(fp->handle, "missing node"); return POLICYDB_ERROR; } buf32[items++] = cpu_to_le32(node->datum.data); set--; node->merged = 1; } } } else { buf32[items++] = cpu_to_le32(cur->datum.data); cur->merged = 1; set--; } if (set) { ERR(fp->handle, "data count wrong"); return POLICYDB_ERROR; } buf32[0] = cpu_to_le32(items - 1); if (commit) { /* Commit this item to the policy file. */ items2 = put_entry(buf32, sizeof(uint32_t), items, fp); if (items != items2) return POLICYDB_ERROR; } return POLICYDB_SUCCESS; } /* Generate the new avtab format. */ buf16[0] = cpu_to_le16(cur->key.source_type); buf16[1] = cpu_to_le16(cur->key.target_type); buf16[2] = cpu_to_le16(cur->key.target_class); buf16[3] = cpu_to_le16(cur->key.specified); items = put_entry(buf16, sizeof(uint16_t), 4, fp); if (items != 4) return POLICYDB_ERROR; if ((p->policyvers < POLICYDB_VERSION_XPERMS_IOCTL) && (cur->key.specified & AVTAB_XPERMS)) { ERR(fp->handle, "policy version %u does not support extended " "permissions rules and one was specified", p->policyvers); return POLICYDB_ERROR; } if (!policydb_has_cond_xperms_feature(p) && (cur->key.specified & AVTAB_XPERMS) && conditional) { ERR(fp->handle, "policy version %u does not support extended " "permissions rules in conditional policies and one was specified", p->policyvers); return POLICYDB_ERROR; } if (p->target_platform != SEPOL_TARGET_SELINUX && (cur->key.specified & AVTAB_XPERMS)) { ERR(fp->handle, "Target platform %s does not support " "extended permissions rules and one was specified", policydb_target_strings[p->target_platform]); return POLICYDB_ERROR; } if (cur->key.specified & AVTAB_XPERMS) { buf8 = cur->datum.xperms->specified; items = put_entry(&buf8, sizeof(uint8_t),1,fp); if (items != 1) return POLICYDB_ERROR; buf8 = cur->datum.xperms->driver; items = put_entry(&buf8, sizeof(uint8_t),1,fp); if (items != 1) return POLICYDB_ERROR; for (i = 0; i < ARRAY_SIZE(cur->datum.xperms->perms); i++) buf32[i] = cpu_to_le32(cur->datum.xperms->perms[i]); items = put_entry(buf32, sizeof(uint32_t),8,fp); if (items != 8) return POLICYDB_ERROR; } else { buf32[0] = cpu_to_le32(cur->datum.data); items = put_entry(buf32, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; } return POLICYDB_SUCCESS; } static inline void avtab_reset_merged(avtab_t * a) { unsigned int i; avtab_ptr_t cur; for (i = 0; i < a->nslot; i++) { for (cur = a->htable[i]; cur; cur = cur->next) cur->merged = 0; } } static int avtab_write(struct policydb *p, avtab_t * a, struct policy_file *fp) { unsigned int i; int rc; avtab_t expa; avtab_ptr_t cur; uint32_t nel; size_t items; unsigned int oldvers = (p->policy_type == POLICY_KERN && p->policyvers < POLICYDB_VERSION_AVTAB); if (oldvers) { /* Old avtab format. First, we need to expand attributes. Then, we need to merge similar entries, so we need to track merged nodes and compute the final nel. */ if (avtab_init(&expa)) return POLICYDB_ERROR; if (expand_avtab(p, a, &expa)) { rc = -1; goto out; } a = &expa; avtab_reset_merged(a); nel = a->nel; } else { /* New avtab format. nel is good to go. */ nel = cpu_to_le32(a->nel); items = put_entry(&nel, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; } for (i = 0; i < a->nslot; i++) { for (cur = a->htable[i]; cur; cur = cur->next) { /* If old format, compute final nel. If new format, write out the items. */ if (avtab_write_item(p, cur, fp, 1, !oldvers, 0, &nel)) { rc = -1; goto out; } } } if (oldvers) { /* Old avtab format. Write the computed nel value, then write the items. */ nel = cpu_to_le32(nel); items = put_entry(&nel, sizeof(uint32_t), 1, fp); if (items != 1) { rc = -1; goto out; } avtab_reset_merged(a); for (i = 0; i < a->nslot; i++) { for (cur = a->htable[i]; cur; cur = cur->next) { if (avtab_write_item(p, cur, fp, 1, 1, 0, NULL)) { rc = -1; goto out; } } } } rc = 0; out: if (oldvers) avtab_destroy(&expa); return rc; } /* * Write a semantic MLS level structure to a policydb binary * representation file. */ static int mls_write_semantic_level_helper(mls_semantic_level_t * l, struct policy_file *fp) { uint32_t buf[2], ncat = 0; size_t items; mls_semantic_cat_t *cat; for (cat = l->cat; cat; cat = cat->next) ncat++; buf[0] = cpu_to_le32(l->sens); buf[1] = cpu_to_le32(ncat); items = put_entry(buf, sizeof(uint32_t), 2, fp); if (items != 2) return POLICYDB_ERROR; for (cat = l->cat; cat; cat = cat->next) { buf[0] = cpu_to_le32(cat->low); buf[1] = cpu_to_le32(cat->high); items = put_entry(buf, sizeof(uint32_t), 2, fp); if (items != 2) return POLICYDB_ERROR; } return POLICYDB_SUCCESS; } /* * Read a semantic MLS range structure to a policydb binary * representation file. */ static int mls_write_semantic_range_helper(mls_semantic_range_t * r, struct policy_file *fp) { int rc; rc = mls_write_semantic_level_helper(&r->level[0], fp); if (rc) return rc; rc = mls_write_semantic_level_helper(&r->level[1], fp); return rc; } /* * Write a MLS level structure to a policydb binary * representation file. */ static int mls_write_level(mls_level_t * l, struct policy_file *fp) { uint32_t sens; size_t items; sens = cpu_to_le32(l->sens); items = put_entry(&sens, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; if (ebitmap_write(&l->cat, fp)) return POLICYDB_ERROR; return POLICYDB_SUCCESS; } /* * Write a MLS range structure to a policydb binary * representation file. */ static int mls_write_range_helper(mls_range_t * r, struct policy_file *fp) { uint32_t buf[3]; size_t items, items2; int eq; eq = mls_level_eq(&r->level[1], &r->level[0]); items = 1; /* item 0 is used for the item count */ buf[items++] = cpu_to_le32(r->level[0].sens); if (!eq) buf[items++] = cpu_to_le32(r->level[1].sens); buf[0] = cpu_to_le32(items - 1); items2 = put_entry(buf, sizeof(uint32_t), items, fp); if (items2 != items) return POLICYDB_ERROR; if (ebitmap_write(&r->level[0].cat, fp)) return POLICYDB_ERROR; if (!eq) if (ebitmap_write(&r->level[1].cat, fp)) return POLICYDB_ERROR; return POLICYDB_SUCCESS; } static int sens_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr) { level_datum_t *levdatum; uint32_t buf[32]; size_t items, items2, len; struct policy_data *pd = ptr; struct policy_file *fp = pd->fp; levdatum = (level_datum_t *) datum; len = strlen(key); items = 0; buf[items++] = cpu_to_le32(len); buf[items++] = cpu_to_le32(levdatum->isalias); items2 = put_entry(buf, sizeof(uint32_t), items, fp); if (items != items2) return POLICYDB_ERROR; items = put_entry(key, 1, len, fp); if (items != len) return POLICYDB_ERROR; if (mls_write_level(levdatum->level, fp)) return POLICYDB_ERROR; return POLICYDB_SUCCESS; } static int cat_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr) { cat_datum_t *catdatum; uint32_t buf[32]; size_t items, items2, len; struct policy_data *pd = ptr; struct policy_file *fp = pd->fp; catdatum = (cat_datum_t *) datum; len = strlen(key); items = 0; buf[items++] = cpu_to_le32(len); buf[items++] = cpu_to_le32(catdatum->s.value); buf[items++] = cpu_to_le32(catdatum->isalias); items2 = put_entry(buf, sizeof(uint32_t), items, fp); if (items != items2) return POLICYDB_ERROR; items = put_entry(key, 1, len, fp); if (items != len) return POLICYDB_ERROR; return POLICYDB_SUCCESS; } static int role_trans_write(policydb_t *p, struct policy_file *fp) { role_trans_t *r = p->role_tr; role_trans_t *tr; uint32_t buf[3]; size_t nel, items; int new_roletr = (p->policy_type == POLICY_KERN && p->policyvers >= POLICYDB_VERSION_ROLETRANS); int warning_issued = 0; nel = 0; for (tr = r; tr; tr = tr->next) if(new_roletr || tr->tclass == p->process_class) nel++; buf[0] = cpu_to_le32(nel); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; for (tr = r; tr; tr = tr->next) { if (!new_roletr && tr->tclass != p->process_class) { if (!warning_issued) WARN(fp->handle, "Discarding role_transition " "rules for security classes other than " "\"process\""); warning_issued = 1; continue; } buf[0] = cpu_to_le32(tr->role); buf[1] = cpu_to_le32(tr->type); buf[2] = cpu_to_le32(tr->new_role); items = put_entry(buf, sizeof(uint32_t), 3, fp); if (items != 3) return POLICYDB_ERROR; if (new_roletr) { buf[0] = cpu_to_le32(tr->tclass); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; } } return POLICYDB_SUCCESS; } static int role_allow_write(role_allow_t * r, struct policy_file *fp) { role_allow_t *ra; uint32_t buf[2]; size_t nel, items; nel = 0; for (ra = r; ra; ra = ra->next) nel++; buf[0] = cpu_to_le32(nel); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; for (ra = r; ra; ra = ra->next) { buf[0] = cpu_to_le32(ra->role); buf[1] = cpu_to_le32(ra->new_role); items = put_entry(buf, sizeof(uint32_t), 2, fp); if (items != 2) return POLICYDB_ERROR; } return POLICYDB_SUCCESS; } static int filename_write_one_compat(hashtab_key_t key, void *data, void *ptr) { uint32_t bit, buf[4]; size_t items, len; filename_trans_key_t *ft = (filename_trans_key_t *)key; filename_trans_datum_t *datum = data; ebitmap_node_t *node; void *fp = ptr; len = strlen(ft->name); do { ebitmap_for_each_positive_bit(&datum->stypes, node, bit) { buf[0] = cpu_to_le32(len); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; items = put_entry(ft->name, sizeof(char), len, fp); if (items != len) return POLICYDB_ERROR; buf[0] = cpu_to_le32(bit + 1); buf[1] = cpu_to_le32(ft->ttype); buf[2] = cpu_to_le32(ft->tclass); buf[3] = cpu_to_le32(datum->otype); items = put_entry(buf, sizeof(uint32_t), 4, fp); if (items != 4) return POLICYDB_ERROR; } datum = datum->next; } while (datum); return 0; } static int filename_write_one(hashtab_key_t key, void *data, void *ptr) { uint32_t buf[3]; size_t items, len, ndatum; filename_trans_key_t *ft = (filename_trans_key_t *)key; filename_trans_datum_t *datum; void *fp = ptr; len = strlen(ft->name); buf[0] = cpu_to_le32(len); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; items = put_entry(ft->name, sizeof(char), len, fp); if (items != len) return POLICYDB_ERROR; ndatum = 0; datum = data; do { ndatum++; datum = datum->next; } while (datum); buf[0] = cpu_to_le32(ft->ttype); buf[1] = cpu_to_le32(ft->tclass); buf[2] = cpu_to_le32(ndatum); items = put_entry(buf, sizeof(uint32_t), 3, fp); if (items != 3) return POLICYDB_ERROR; datum = data; do { if (ebitmap_write(&datum->stypes, fp)) return POLICYDB_ERROR; buf[0] = cpu_to_le32(datum->otype); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; datum = datum->next; } while (datum); return 0; } static int filename_trans_write(struct policydb *p, void *fp) { size_t items; uint32_t buf[1]; int rc; if (p->policyvers < POLICYDB_VERSION_FILENAME_TRANS) return 0; if (p->policyvers < POLICYDB_VERSION_COMP_FTRANS) { buf[0] = cpu_to_le32(p->filename_trans_count); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; rc = hashtab_map(p->filename_trans, filename_write_one_compat, fp); } else { buf[0] = cpu_to_le32(p->filename_trans->nel); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; rc = hashtab_map(p->filename_trans, filename_write_one, fp); } return rc; } static int role_set_write(role_set_t * x, struct policy_file *fp) { size_t items; uint32_t buf[1]; if (ebitmap_write(&x->roles, fp)) return POLICYDB_ERROR; buf[0] = cpu_to_le32(x->flags); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; return POLICYDB_SUCCESS; } static int type_set_write(type_set_t * x, struct policy_file *fp) { size_t items; uint32_t buf[1]; if (ebitmap_write(&x->types, fp)) return POLICYDB_ERROR; if (ebitmap_write(&x->negset, fp)) return POLICYDB_ERROR; buf[0] = cpu_to_le32(x->flags); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; return POLICYDB_SUCCESS; } static int cond_write_bool(hashtab_key_t key, hashtab_datum_t datum, void *ptr) { cond_bool_datum_t *booldatum; uint32_t buf[3], len; unsigned int items, items2; struct policy_data *pd = ptr; struct policy_file *fp = pd->fp; struct policydb *p = pd->p; booldatum = (cond_bool_datum_t *) datum; len = strlen(key); items = 0; buf[items++] = cpu_to_le32(booldatum->s.value); buf[items++] = cpu_to_le32(booldatum->state); buf[items++] = cpu_to_le32(len); items2 = put_entry(buf, sizeof(uint32_t), items, fp); if (items != items2) return POLICYDB_ERROR; items = put_entry(key, 1, len, fp); if (items != len) return POLICYDB_ERROR; if (p->policy_type != POLICY_KERN && p->policyvers >= MOD_POLICYDB_VERSION_TUNABLE_SEP) { buf[0] = cpu_to_le32(booldatum->flags); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; } return POLICYDB_SUCCESS; } /* * cond_write_cond_av_list doesn't write out the av_list nodes. * Instead it writes out the key/value pairs from the avtab. This * is necessary because there is no way to uniquely identifying rules * in the avtab so it is not possible to associate individual rules * in the avtab with a conditional without saving them as part of * the conditional. This means that the avtab with the conditional * rules will not be saved but will be rebuilt on policy load. */ static int cond_write_av_list(policydb_t * p, cond_av_list_t * list, struct policy_file *fp) { uint32_t buf[4]; cond_av_list_t *cur_list, *new_list = NULL; avtab_t expa; uint32_t len, items; unsigned int oldvers = (p->policy_type == POLICY_KERN && p->policyvers < POLICYDB_VERSION_AVTAB); int rc = -1; if (oldvers) { if (avtab_init(&expa)) return POLICYDB_ERROR; if (expand_cond_av_list(p, list, &new_list, &expa)) goto out; list = new_list; } len = 0; for (cur_list = list; cur_list != NULL; cur_list = cur_list->next) { if (cur_list->node->parse_context) len++; } buf[0] = cpu_to_le32(len); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) goto out; if (len == 0) { rc = 0; goto out; } for (cur_list = list; cur_list != NULL; cur_list = cur_list->next) { if (cur_list->node->parse_context) if (avtab_write_item(p, cur_list->node, fp, 0, 1, 1, NULL)) goto out; } rc = 0; out: if (oldvers) { cond_av_list_destroy(new_list); avtab_destroy(&expa); } return rc; } static int cond_write_node(policydb_t * p, cond_node_t * node, struct policy_file *fp) { cond_expr_t *cur_expr; uint32_t buf[2]; uint32_t items, items2, len; buf[0] = cpu_to_le32(node->cur_state); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; /* expr */ len = 0; for (cur_expr = node->expr; cur_expr != NULL; cur_expr = cur_expr->next) len++; buf[0] = cpu_to_le32(len); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; for (cur_expr = node->expr; cur_expr != NULL; cur_expr = cur_expr->next) { items = 0; buf[items++] = cpu_to_le32(cur_expr->expr_type); buf[items++] = cpu_to_le32(cur_expr->boolean); items2 = put_entry(buf, sizeof(uint32_t), items, fp); if (items2 != items) return POLICYDB_ERROR; } if (p->policy_type == POLICY_KERN) { if (cond_write_av_list(p, node->true_list, fp) != 0) return POLICYDB_ERROR; if (cond_write_av_list(p, node->false_list, fp) != 0) return POLICYDB_ERROR; } else { if (avrule_write_list(p, node->avtrue_list, fp, 1)) return POLICYDB_ERROR; if (avrule_write_list(p, node->avfalse_list, fp, 1)) return POLICYDB_ERROR; } if (p->policy_type != POLICY_KERN && p->policyvers >= MOD_POLICYDB_VERSION_TUNABLE_SEP) { buf[0] = cpu_to_le32(node->flags); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; } return POLICYDB_SUCCESS; } static int cond_write_list(policydb_t * p, cond_list_t * list, struct policy_file *fp) { cond_node_t *cur; uint32_t len, items; uint32_t buf[1]; len = 0; for (cur = list; cur != NULL; cur = cur->next) len++; buf[0] = cpu_to_le32(len); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; for (cur = list; cur != NULL; cur = cur->next) { if (cond_write_node(p, cur, fp) != 0) return POLICYDB_ERROR; } return POLICYDB_SUCCESS; } /* * Write a security context structure * to a policydb binary representation file. */ static int context_write(struct policydb *p, context_struct_t * c, struct policy_file *fp) { uint32_t buf[32]; size_t items, items2; items = 0; buf[items++] = cpu_to_le32(c->user); buf[items++] = cpu_to_le32(c->role); buf[items++] = cpu_to_le32(c->type); items2 = put_entry(buf, sizeof(uint32_t), items, fp); if (items2 != items) return POLICYDB_ERROR; if ((p->policyvers >= POLICYDB_VERSION_MLS && p->policy_type == POLICY_KERN) || (p->policyvers >= MOD_POLICYDB_VERSION_MLS && p->policy_type == POLICY_BASE)) if (mls_write_range_helper(&c->range, fp)) return POLICYDB_ERROR; return POLICYDB_SUCCESS; } /* * The following *_write functions are used to * write the symbol data to a policy database * binary representation file. */ static int perm_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr) { perm_datum_t *perdatum; uint32_t buf[32]; size_t items, items2, len; struct policy_data *pd = ptr; struct policy_file *fp = pd->fp; perdatum = (perm_datum_t *) datum; len = strlen(key); items = 0; buf[items++] = cpu_to_le32(len); buf[items++] = cpu_to_le32(perdatum->s.value); items2 = put_entry(buf, sizeof(uint32_t), items, fp); if (items != items2) return POLICYDB_ERROR; items = put_entry(key, 1, len, fp); if (items != len) return POLICYDB_ERROR; return POLICYDB_SUCCESS; } static int common_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr) { common_datum_t *comdatum; uint32_t buf[32]; size_t items, items2, len; struct policy_data *pd = ptr; struct policy_file *fp = pd->fp; comdatum = (common_datum_t *) datum; len = strlen(key); items = 0; buf[items++] = cpu_to_le32(len); buf[items++] = cpu_to_le32(comdatum->s.value); buf[items++] = cpu_to_le32(comdatum->permissions.nprim); buf[items++] = cpu_to_le32(comdatum->permissions.table->nel); items2 = put_entry(buf, sizeof(uint32_t), items, fp); if (items != items2) return POLICYDB_ERROR; items = put_entry(key, 1, len, fp); if (items != len) return POLICYDB_ERROR; if (hashtab_map(comdatum->permissions.table, perm_write, pd)) return POLICYDB_ERROR; return POLICYDB_SUCCESS; } static int write_cons_helper(policydb_t * p, constraint_node_t * node, int allowxtarget, struct policy_file *fp) { constraint_node_t *c; constraint_expr_t *e; uint32_t buf[3], nexpr; int items; for (c = node; c; c = c->next) { nexpr = 0; for (e = c->expr; e; e = e->next) { nexpr++; } buf[0] = cpu_to_le32(c->permissions); buf[1] = cpu_to_le32(nexpr); items = put_entry(buf, sizeof(uint32_t), 2, fp); if (items != 2) return POLICYDB_ERROR; for (e = c->expr; e; e = e->next) { buf[0] = cpu_to_le32(e->expr_type); buf[1] = cpu_to_le32(e->attr); buf[2] = cpu_to_le32(e->op); items = put_entry(buf, sizeof(uint32_t), 3, fp); if (items != 3) return POLICYDB_ERROR; switch (e->expr_type) { case CEXPR_NAMES: if (!allowxtarget && (e->attr & CEXPR_XTARGET)) return POLICYDB_ERROR; if (ebitmap_write(&e->names, fp)) { return POLICYDB_ERROR; } if ((p->policy_type != POLICY_KERN && type_set_write(e->type_names, fp)) || (p->policy_type == POLICY_KERN && (p->policyvers >= POLICYDB_VERSION_CONSTRAINT_NAMES) && type_set_write(e->type_names, fp))) { return POLICYDB_ERROR; } break; default: break; } } } return POLICYDB_SUCCESS; } static int class_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr) { class_datum_t *cladatum; constraint_node_t *c; uint32_t buf[32], ncons; size_t items, items2, len, len2; struct policy_data *pd = ptr; struct policy_file *fp = pd->fp; struct policydb *p = pd->p; cladatum = (class_datum_t *) datum; len = strlen(key); if (cladatum->comkey) len2 = strlen(cladatum->comkey); else len2 = 0; ncons = 0; for (c = cladatum->constraints; c; c = c->next) { ncons++; } items = 0; buf[items++] = cpu_to_le32(len); buf[items++] = cpu_to_le32(len2); buf[items++] = cpu_to_le32(cladatum->s.value); buf[items++] = cpu_to_le32(cladatum->permissions.nprim); if (cladatum->permissions.table) buf[items++] = cpu_to_le32(cladatum->permissions.table->nel); else buf[items++] = 0; buf[items++] = cpu_to_le32(ncons); items2 = put_entry(buf, sizeof(uint32_t), items, fp); if (items != items2) return POLICYDB_ERROR; items = put_entry(key, 1, len, fp); if (items != len) return POLICYDB_ERROR; if (cladatum->comkey) { items = put_entry(cladatum->comkey, 1, len2, fp); if (items != len2) return POLICYDB_ERROR; } if (hashtab_map(cladatum->permissions.table, perm_write, pd)) return POLICYDB_ERROR; if (write_cons_helper(p, cladatum->constraints, 0, fp)) return POLICYDB_ERROR; if ((p->policy_type == POLICY_KERN && p->policyvers >= POLICYDB_VERSION_VALIDATETRANS) || (p->policy_type == POLICY_BASE && p->policyvers >= MOD_POLICYDB_VERSION_VALIDATETRANS)) { /* write out the validatetrans rule */ ncons = 0; for (c = cladatum->validatetrans; c; c = c->next) { ncons++; } buf[0] = cpu_to_le32(ncons); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; if (write_cons_helper(p, cladatum->validatetrans, 1, fp)) return POLICYDB_ERROR; } if ((p->policy_type == POLICY_KERN && p->policyvers >= POLICYDB_VERSION_NEW_OBJECT_DEFAULTS) || (p->policy_type == POLICY_BASE && p->policyvers >= MOD_POLICYDB_VERSION_NEW_OBJECT_DEFAULTS)) { char default_range = cladatum->default_range; buf[0] = cpu_to_le32(cladatum->default_user); buf[1] = cpu_to_le32(cladatum->default_role); if (!glblub_version && default_range == DEFAULT_GLBLUB) { WARN(fp->handle, "class %s default_range set to GLBLUB but %spolicy version is %d (%d required), discarding", p->p_class_val_to_name[cladatum->s.value - 1], p->policy_type == POLICY_KERN ? "" : "module ", p->policyvers, p->policy_type == POLICY_KERN? POLICYDB_VERSION_GLBLUB:MOD_POLICYDB_VERSION_GLBLUB); default_range = 0; } buf[2] = cpu_to_le32(default_range); items = put_entry(buf, sizeof(uint32_t), 3, fp); if (items != 3) return POLICYDB_ERROR; } if ((p->policy_type == POLICY_KERN && p->policyvers >= POLICYDB_VERSION_DEFAULT_TYPE) || (p->policy_type == POLICY_BASE && p->policyvers >= MOD_POLICYDB_VERSION_DEFAULT_TYPE)) { buf[0] = cpu_to_le32(cladatum->default_type); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; } return POLICYDB_SUCCESS; } static int role_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr) { role_datum_t *role; uint32_t buf[32]; size_t items, items2, len; struct policy_data *pd = ptr; struct policy_file *fp = pd->fp; struct policydb *p = pd->p; role = (role_datum_t *) datum; /* * Role attributes are redundant for policy.X, skip them * when writing the roles symbol table. They are also skipped * when pp is downgraded. * * Their numbers would be deducted in policydb_write(). */ if ((role->flavor == ROLE_ATTRIB) && ((p->policy_type == POLICY_KERN) || (p->policy_type != POLICY_KERN && p->policyvers < MOD_POLICYDB_VERSION_ROLEATTRIB))) return POLICYDB_SUCCESS; len = strlen(key); items = 0; buf[items++] = cpu_to_le32(len); buf[items++] = cpu_to_le32(role->s.value); if (policydb_has_boundary_feature(p)) buf[items++] = cpu_to_le32(role->bounds); items2 = put_entry(buf, sizeof(uint32_t), items, fp); if (items != items2) return POLICYDB_ERROR; items = put_entry(key, 1, len, fp); if (items != len) return POLICYDB_ERROR; if (ebitmap_write(&role->dominates, fp)) return POLICYDB_ERROR; if (p->policy_type == POLICY_KERN) { if (role->s.value == OBJECT_R_VAL) { /* * CIL populates object_r's types map * rather than handling it as a special case. * However, this creates an inconsistency with * the kernel policy read from /sys/fs/selinux/policy * because the kernel ignores everything except for * object_r's value from the policy file. * Make them consistent by writing an empty * ebitmap instead. */ ebitmap_t empty; ebitmap_init(&empty); if (ebitmap_write(&empty, fp)) return POLICYDB_ERROR; } else { if (ebitmap_write(&role->types.types, fp)) return POLICYDB_ERROR; } } else { if (type_set_write(&role->types, fp)) return POLICYDB_ERROR; } if (p->policy_type != POLICY_KERN && p->policyvers >= MOD_POLICYDB_VERSION_ROLEATTRIB) { buf[0] = cpu_to_le32(role->flavor); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; if (ebitmap_write(&role->roles, fp)) return POLICYDB_ERROR; } return POLICYDB_SUCCESS; } static int type_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr) { type_datum_t *typdatum; uint32_t buf[32]; size_t items, items2, len; struct policy_data *pd = ptr; struct policy_file *fp = pd->fp; struct policydb *p = pd->p; typdatum = (type_datum_t *) datum; /* * The kernel policy version less than 24 (= POLICYDB_VERSION_BOUNDARY) * does not support to load entries of attribute, so we skip to write it. */ if (p->policy_type == POLICY_KERN && p->policyvers < POLICYDB_VERSION_BOUNDARY && typdatum->flavor == TYPE_ATTRIB) return POLICYDB_SUCCESS; len = strlen(key); items = 0; buf[items++] = cpu_to_le32(len); buf[items++] = cpu_to_le32(typdatum->s.value); if (policydb_has_boundary_feature(p)) { uint32_t properties = 0; if (p->policy_type != POLICY_KERN && p->policyvers >= MOD_POLICYDB_VERSION_BOUNDARY_ALIAS) { buf[items++] = cpu_to_le32(typdatum->primary); } if (typdatum->primary) properties |= TYPEDATUM_PROPERTY_PRIMARY; if (typdatum->flavor == TYPE_ATTRIB) { properties |= TYPEDATUM_PROPERTY_ATTRIBUTE; } else if (typdatum->flavor == TYPE_ALIAS && p->policy_type != POLICY_KERN) properties |= TYPEDATUM_PROPERTY_ALIAS; if (typdatum->flags & TYPE_FLAGS_PERMISSIVE && p->policy_type != POLICY_KERN) properties |= TYPEDATUM_PROPERTY_PERMISSIVE; buf[items++] = cpu_to_le32(properties); buf[items++] = cpu_to_le32(typdatum->bounds); } else { buf[items++] = cpu_to_le32(typdatum->primary); if (p->policy_type != POLICY_KERN) { buf[items++] = cpu_to_le32(typdatum->flavor); if (p->policyvers >= MOD_POLICYDB_VERSION_PERMISSIVE) buf[items++] = cpu_to_le32(typdatum->flags); else if (typdatum->flags & TYPE_FLAGS_PERMISSIVE) WARN(fp->handle, "Warning! Module policy " "version %d cannot support permissive " "types, but one was defined", p->policyvers); } } items2 = put_entry(buf, sizeof(uint32_t), items, fp); if (items != items2) return POLICYDB_ERROR; if (p->policy_type != POLICY_KERN) { if (ebitmap_write(&typdatum->types, fp)) return POLICYDB_ERROR; } items = put_entry(key, 1, len, fp); if (items != len) return POLICYDB_ERROR; return POLICYDB_SUCCESS; } static int user_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr) { user_datum_t *usrdatum; uint32_t buf[32]; size_t items, items2, len; struct policy_data *pd = ptr; struct policy_file *fp = pd->fp; struct policydb *p = pd->p; usrdatum = (user_datum_t *) datum; len = strlen(key); items = 0; buf[items++] = cpu_to_le32(len); buf[items++] = cpu_to_le32(usrdatum->s.value); if (policydb_has_boundary_feature(p)) buf[items++] = cpu_to_le32(usrdatum->bounds); items2 = put_entry(buf, sizeof(uint32_t), items, fp); if (items != items2) return POLICYDB_ERROR; items = put_entry(key, 1, len, fp); if (items != len) return POLICYDB_ERROR; if (p->policy_type == POLICY_KERN) { if (ebitmap_write(&usrdatum->roles.roles, fp)) return POLICYDB_ERROR; } else { if (role_set_write(&usrdatum->roles, fp)) return POLICYDB_ERROR; } if ((p->policyvers >= POLICYDB_VERSION_MLS && p->policy_type == POLICY_KERN) || (p->policyvers >= MOD_POLICYDB_VERSION_MLS && p->policyvers < MOD_POLICYDB_VERSION_MLS_USERS && p->policy_type == POLICY_MOD) || (p->policyvers >= MOD_POLICYDB_VERSION_MLS && p->policyvers < MOD_POLICYDB_VERSION_MLS_USERS && p->policy_type == POLICY_BASE)) { if (mls_write_range_helper(&usrdatum->exp_range, fp)) return POLICYDB_ERROR; if (mls_write_level(&usrdatum->exp_dfltlevel, fp)) return POLICYDB_ERROR; } else if ((p->policyvers >= MOD_POLICYDB_VERSION_MLS_USERS && p->policy_type == POLICY_MOD) || (p->policyvers >= MOD_POLICYDB_VERSION_MLS_USERS && p->policy_type == POLICY_BASE)) { if (mls_write_semantic_range_helper(&usrdatum->range, fp)) return -1; if (mls_write_semantic_level_helper(&usrdatum->dfltlevel, fp)) return -1; } return POLICYDB_SUCCESS; } static int (*const write_f[SYM_NUM]) (hashtab_key_t key, hashtab_datum_t datum, void *datap) = { common_write, class_write, role_write, type_write, user_write, cond_write_bool, sens_write, cat_write,}; static int ocontext_write_xen(const struct policydb_compat_info *info, policydb_t *p, struct policy_file *fp) { unsigned int i, j; size_t nel, items, len; uint32_t buf[32]; ocontext_t *c; for (i = 0; i < info->ocon_num; i++) { nel = 0; for (c = p->ocontexts[i]; c; c = c->next) { if (i == OCON_XEN_ISID && !c->context[0].user) { INFO(fp->handle, "No context assigned to SID %s, omitting from policy", c->u.name); continue; } nel++; } buf[0] = cpu_to_le32(nel); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; for (c = p->ocontexts[i]; c; c = c->next) { switch (i) { case OCON_XEN_ISID: if (!c->context[0].user) break; buf[0] = cpu_to_le32(c->sid[0]); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; if (context_write(p, &c->context[0], fp)) return POLICYDB_ERROR; break; case OCON_XEN_PIRQ: buf[0] = cpu_to_le32(c->u.pirq); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; if (context_write(p, &c->context[0], fp)) return POLICYDB_ERROR; break; case OCON_XEN_IOPORT: buf[0] = c->u.ioport.low_ioport; buf[1] = c->u.ioport.high_ioport; for (j = 0; j < 2; j++) buf[j] = cpu_to_le32(buf[j]); items = put_entry(buf, sizeof(uint32_t), 2, fp); if (items != 2) return POLICYDB_ERROR; if (context_write(p, &c->context[0], fp)) return POLICYDB_ERROR; break; case OCON_XEN_IOMEM: if (p->policyvers >= POLICYDB_VERSION_XEN_DEVICETREE) { uint64_t b64[2]; b64[0] = c->u.iomem.low_iomem; b64[1] = c->u.iomem.high_iomem; for (j = 0; j < 2; j++) b64[j] = cpu_to_le64(b64[j]); items = put_entry(b64, sizeof(uint64_t), 2, fp); if (items != 2) return POLICYDB_ERROR; } else { if (c->u.iomem.high_iomem > 0xFFFFFFFFULL) { ERR(fp->handle, "policy version %d" " cannot represent IOMEM addresses over 16TB", p->policyvers); return POLICYDB_ERROR; } buf[0] = c->u.iomem.low_iomem; buf[1] = c->u.iomem.high_iomem; for (j = 0; j < 2; j++) buf[j] = cpu_to_le32(buf[j]); items = put_entry(buf, sizeof(uint32_t), 2, fp); if (items != 2) return POLICYDB_ERROR; } if (context_write(p, &c->context[0], fp)) return POLICYDB_ERROR; break; case OCON_XEN_PCIDEVICE: buf[0] = cpu_to_le32(c->u.device); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; if (context_write(p, &c->context[0], fp)) return POLICYDB_ERROR; break; case OCON_XEN_DEVICETREE: len = strlen(c->u.name); buf[0] = cpu_to_le32(len); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; items = put_entry(c->u.name, 1, len, fp); if (items != len) return POLICYDB_ERROR; if (context_write(p, &c->context[0], fp)) return POLICYDB_ERROR; break; } } } return POLICYDB_SUCCESS; } static int ocontext_write_selinux(const struct policydb_compat_info *info, policydb_t *p, struct policy_file *fp) { unsigned int i, j; size_t nel, items, len; uint32_t buf[32]; ocontext_t *c; for (i = 0; i < info->ocon_num; i++) { nel = 0; for (c = p->ocontexts[i]; c; c = c->next) { if (i == OCON_ISID && !c->context[0].user) { INFO(fp->handle, "No context assigned to SID %s, omitting from policy", c->u.name); continue; } nel++; } buf[0] = cpu_to_le32(nel); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; for (c = p->ocontexts[i]; c; c = c->next) { switch (i) { case OCON_ISID: if (!c->context[0].user) break; buf[0] = cpu_to_le32(c->sid[0]); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; if (context_write(p, &c->context[0], fp)) return POLICYDB_ERROR; break; case OCON_FS: case OCON_NETIF: len = strlen(c->u.name); buf[0] = cpu_to_le32(len); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; items = put_entry(c->u.name, 1, len, fp); if (items != len) return POLICYDB_ERROR; if (context_write(p, &c->context[0], fp)) return POLICYDB_ERROR; if (context_write(p, &c->context[1], fp)) return POLICYDB_ERROR; break; case OCON_IBPKEY: /* The subnet prefix is in network order */ memcpy(buf, &c->u.ibpkey.subnet_prefix, sizeof(c->u.ibpkey.subnet_prefix)); buf[2] = cpu_to_le32(c->u.ibpkey.low_pkey); buf[3] = cpu_to_le32(c->u.ibpkey.high_pkey); items = put_entry(buf, sizeof(uint32_t), 4, fp); if (items != 4) return POLICYDB_ERROR; if (context_write(p, &c->context[0], fp)) return POLICYDB_ERROR; break; case OCON_IBENDPORT: len = strlen(c->u.ibendport.dev_name); buf[0] = cpu_to_le32(len); buf[1] = cpu_to_le32(c->u.ibendport.port); items = put_entry(buf, sizeof(uint32_t), 2, fp); if (items != 2) return POLICYDB_ERROR; items = put_entry(c->u.ibendport.dev_name, 1, len, fp); if (items != len) return POLICYDB_ERROR; if (context_write(p, &c->context[0], fp)) return POLICYDB_ERROR; break; case OCON_PORT: buf[0] = c->u.port.protocol; buf[1] = c->u.port.low_port; buf[2] = c->u.port.high_port; for (j = 0; j < 3; j++) { buf[j] = cpu_to_le32(buf[j]); } items = put_entry(buf, sizeof(uint32_t), 3, fp); if (items != 3) return POLICYDB_ERROR; if (context_write(p, &c->context[0], fp)) return POLICYDB_ERROR; break; case OCON_NODE: buf[0] = c->u.node.addr; /* network order */ buf[1] = c->u.node.mask; /* network order */ items = put_entry(buf, sizeof(uint32_t), 2, fp); if (items != 2) return POLICYDB_ERROR; if (context_write(p, &c->context[0], fp)) return POLICYDB_ERROR; break; case OCON_FSUSE: buf[0] = cpu_to_le32(c->v.behavior); len = strlen(c->u.name); buf[1] = cpu_to_le32(len); items = put_entry(buf, sizeof(uint32_t), 2, fp); if (items != 2) return POLICYDB_ERROR; items = put_entry(c->u.name, 1, len, fp); if (items != len) return POLICYDB_ERROR; if (context_write(p, &c->context[0], fp)) return POLICYDB_ERROR; break; case OCON_NODE6: for (j = 0; j < 4; j++) buf[j] = c->u.node6.addr[j]; /* network order */ for (j = 0; j < 4; j++) buf[j + 4] = c->u.node6.mask[j]; /* network order */ items = put_entry(buf, sizeof(uint32_t), 8, fp); if (items != 8) return POLICYDB_ERROR; if (context_write(p, &c->context[0], fp)) return POLICYDB_ERROR; break; } } } return POLICYDB_SUCCESS; } static int ocontext_write(const struct policydb_compat_info *info, policydb_t * p, struct policy_file *fp) { int rc = POLICYDB_ERROR; switch (p->target_platform) { case SEPOL_TARGET_SELINUX: rc = ocontext_write_selinux(info, p, fp); break; case SEPOL_TARGET_XEN: rc = ocontext_write_xen(info, p, fp); break; } return rc; } static int genfs_write(policydb_t * p, struct policy_file *fp) { genfs_t *genfs; ocontext_t *c; size_t nel = 0, items, len; uint32_t buf[32]; for (genfs = p->genfs; genfs; genfs = genfs->next) nel++; buf[0] = cpu_to_le32(nel); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; for (genfs = p->genfs; genfs; genfs = genfs->next) { len = strlen(genfs->fstype); buf[0] = cpu_to_le32(len); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; items = put_entry(genfs->fstype, 1, len, fp); if (items != len) return POLICYDB_ERROR; nel = 0; for (c = genfs->head; c; c = c->next) nel++; buf[0] = cpu_to_le32(nel); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; for (c = genfs->head; c; c = c->next) { len = strlen(c->u.name); buf[0] = cpu_to_le32(len); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; items = put_entry(c->u.name, 1, len, fp); if (items != len) return POLICYDB_ERROR; buf[0] = cpu_to_le32(c->v.sclass); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; if (context_write(p, &c->context[0], fp)) return POLICYDB_ERROR; } } return POLICYDB_SUCCESS; } struct rangetrans_write_args { size_t nel; int new_rangetr; struct policy_file *fp; struct policydb *p; }; static int rangetrans_count(hashtab_key_t key, void *data __attribute__ ((unused)), void *ptr) { struct range_trans *rt = (struct range_trans *)key; struct rangetrans_write_args *args = ptr; struct policydb *p = args->p; /* all range_transitions are written for the new format, only process related range_transitions are written for the old format, so count accordingly */ if (args->new_rangetr || rt->target_class == p->process_class) args->nel++; return 0; } static int range_write_helper(hashtab_key_t key, void *data, void *ptr) { uint32_t buf[2]; struct range_trans *rt = (struct range_trans *)key; struct mls_range *r = data; struct rangetrans_write_args *args = ptr; struct policy_file *fp = args->fp; struct policydb *p = args->p; int new_rangetr = args->new_rangetr; size_t items; static int warning_issued = 0; int rc; if (!new_rangetr && rt->target_class != p->process_class) { if (!warning_issued) WARN(fp->handle, "Discarding range_transition " "rules for security classes other than " "\"process\""); warning_issued = 1; return 0; } buf[0] = cpu_to_le32(rt->source_type); buf[1] = cpu_to_le32(rt->target_type); items = put_entry(buf, sizeof(uint32_t), 2, fp); if (items != 2) return POLICYDB_ERROR; if (new_rangetr) { buf[0] = cpu_to_le32(rt->target_class); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; } rc = mls_write_range_helper(r, fp); if (rc) return rc; return 0; } static int range_write(policydb_t * p, struct policy_file *fp) { size_t items; uint32_t buf[2]; int new_rangetr = (p->policy_type == POLICY_KERN && p->policyvers >= POLICYDB_VERSION_RANGETRANS); struct rangetrans_write_args args; int rc; args.nel = 0; args.new_rangetr = new_rangetr; args.fp = fp; args.p = p; rc = hashtab_map(p->range_tr, rangetrans_count, &args); if (rc) return rc; buf[0] = cpu_to_le32(args.nel); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; return hashtab_map(p->range_tr, range_write_helper, &args); } /************** module writing functions below **************/ static int avrule_write(policydb_t *p, avrule_t * avrule, struct policy_file *fp, unsigned conditional) { size_t items, items2; uint32_t buf[32], len; class_perm_node_t *cur; if (p->policyvers < MOD_POLICYDB_VERSION_SELF_TYPETRANS && (avrule->specified & AVRULE_TYPE) && (avrule->flags & RULE_SELF)) { ERR(fp->handle, "Module contains a self rule not supported by the target module policy version"); return POLICYDB_ERROR; } items = 0; buf[items++] = cpu_to_le32(avrule->specified); buf[items++] = cpu_to_le32(avrule->flags); items2 = put_entry(buf, sizeof(uint32_t), items, fp); if (items2 != items) return POLICYDB_ERROR; if (type_set_write(&avrule->stypes, fp)) return POLICYDB_ERROR; if (type_set_write(&avrule->ttypes, fp)) return POLICYDB_ERROR; cur = avrule->perms; len = 0; while (cur) { len++; cur = cur->next; } items = 0; buf[items++] = cpu_to_le32(len); items2 = put_entry(buf, sizeof(uint32_t), items, fp); if (items2 != items) return POLICYDB_ERROR; cur = avrule->perms; while (cur) { items = 0; buf[items++] = cpu_to_le32(cur->tclass); buf[items++] = cpu_to_le32(cur->data); items2 = put_entry(buf, sizeof(uint32_t), items, fp); if (items2 != items) return POLICYDB_ERROR; cur = cur->next; } if (avrule->specified & AVRULE_XPERMS) { size_t nel = ARRAY_SIZE(avrule->xperms->perms); uint32_t buf32[nel]; uint8_t buf8; unsigned int i; if (p->policyvers < MOD_POLICYDB_VERSION_XPERMS_IOCTL) { ERR(fp->handle, "module policy version %u does not support" " extended permissions rules and one was specified", p->policyvers); return POLICYDB_ERROR; } if (conditional && !policydb_has_cond_xperms_feature(p)) { ERR(fp->handle, "module policy version %u does not support" " extended permissions rules in conditional policies and one was specified", p->policyvers); return POLICYDB_ERROR; } if (p->target_platform != SEPOL_TARGET_SELINUX) { ERR(fp->handle, "Target platform %s does not support" " extended permissions rules and one was specified", policydb_target_strings[p->target_platform]); return POLICYDB_ERROR; } buf8 = avrule->xperms->specified; items = put_entry(&buf8, sizeof(uint8_t),1,fp); if (items != 1) return POLICYDB_ERROR; buf8 = avrule->xperms->driver; items = put_entry(&buf8, sizeof(uint8_t),1,fp); if (items != 1) return POLICYDB_ERROR; for (i = 0; i < nel; i++) buf32[i] = cpu_to_le32(avrule->xperms->perms[i]); items = put_entry(buf32, sizeof(uint32_t), nel, fp); if (items != nel) return POLICYDB_ERROR; } return POLICYDB_SUCCESS; } static int avrule_write_list(policydb_t *p, avrule_t * avrules, struct policy_file *fp, unsigned conditional) { uint32_t buf[32], len; avrule_t *avrule; avrule = avrules; len = 0; while (avrule) { len++; avrule = avrule->next; } buf[0] = cpu_to_le32(len); if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1) return POLICYDB_ERROR; avrule = avrules; while (avrule) { if (avrule_write(p, avrule, fp, conditional)) return POLICYDB_ERROR; avrule = avrule->next; } return POLICYDB_SUCCESS; } static int only_process(ebitmap_t *in, struct policydb *p) { unsigned int i, value; ebitmap_node_t *node; if (!p->process_class) return 0; value = p->process_class - 1; ebitmap_for_each_positive_bit(in, node, i) { if (i != value) return 0; } return 1; } static int role_trans_rule_write(policydb_t *p, role_trans_rule_t * t, struct policy_file *fp) { int nel = 0; size_t items; uint32_t buf[1]; role_trans_rule_t *tr; int warned = 0; int new_role = p->policyvers >= MOD_POLICYDB_VERSION_ROLETRANS; for (tr = t; tr; tr = tr->next) if (new_role || only_process(&tr->classes, p)) nel++; buf[0] = cpu_to_le32(nel); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; for (tr = t; tr; tr = tr->next) { if (!new_role && !only_process(&tr->classes, p)) { if (!warned) WARN(fp->handle, "Discarding role_transition " "rules for security classes other than " "\"process\""); warned = 1; continue; } if (role_set_write(&tr->roles, fp)) return POLICYDB_ERROR; if (type_set_write(&tr->types, fp)) return POLICYDB_ERROR; if (new_role) if (ebitmap_write(&tr->classes, fp)) return POLICYDB_ERROR; buf[0] = cpu_to_le32(tr->new_role); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; } return POLICYDB_SUCCESS; } static int role_allow_rule_write(role_allow_rule_t * r, struct policy_file *fp) { int nel = 0; size_t items; uint32_t buf[1]; role_allow_rule_t *ra; for (ra = r; ra; ra = ra->next) nel++; buf[0] = cpu_to_le32(nel); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; for (ra = r; ra; ra = ra->next) { if (role_set_write(&ra->roles, fp)) return POLICYDB_ERROR; if (role_set_write(&ra->new_roles, fp)) return POLICYDB_ERROR; } return POLICYDB_SUCCESS; } static int filename_trans_rule_write(policydb_t *p, filename_trans_rule_t *t, struct policy_file *fp) { int nel = 0; size_t items, entries; uint32_t buf[3], len; filename_trans_rule_t *ftr; for (ftr = t; ftr; ftr = ftr->next) nel++; buf[0] = cpu_to_le32(nel); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; for (ftr = t; ftr; ftr = ftr->next) { len = strlen(ftr->name); buf[0] = cpu_to_le32(len); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; items = put_entry(ftr->name, sizeof(char), len, fp); if (items != len) return POLICYDB_ERROR; if (type_set_write(&ftr->stypes, fp)) return POLICYDB_ERROR; if (type_set_write(&ftr->ttypes, fp)) return POLICYDB_ERROR; buf[0] = cpu_to_le32(ftr->tclass); buf[1] = cpu_to_le32(ftr->otype); buf[2] = cpu_to_le32(ftr->flags); if (p->policyvers >= MOD_POLICYDB_VERSION_SELF_TYPETRANS) { entries = 3; } else if (!(ftr->flags & RULE_SELF)) { entries = 2; } else { ERR(fp->handle, "Module contains a self rule not supported by the target module policy version"); return POLICYDB_ERROR; } items = put_entry(buf, sizeof(uint32_t), entries, fp); if (items != entries) return POLICYDB_ERROR; } return POLICYDB_SUCCESS; } static int range_trans_rule_write(range_trans_rule_t * t, struct policy_file *fp) { int nel = 0; size_t items; uint32_t buf[1]; range_trans_rule_t *rt; for (rt = t; rt; rt = rt->next) nel++; buf[0] = cpu_to_le32(nel); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; for (rt = t; rt; rt = rt->next) { if (type_set_write(&rt->stypes, fp)) return POLICYDB_ERROR; if (type_set_write(&rt->ttypes, fp)) return POLICYDB_ERROR; if (ebitmap_write(&rt->tclasses, fp)) return POLICYDB_ERROR; if (mls_write_semantic_range_helper(&rt->trange, fp)) return POLICYDB_ERROR; } return POLICYDB_SUCCESS; } static int scope_index_write(scope_index_t * scope_index, unsigned int num_scope_syms, struct policy_file *fp) { unsigned int i; uint32_t buf[1]; for (i = 0; i < num_scope_syms; i++) { if (ebitmap_write(scope_index->scope + i, fp) == -1) { return POLICYDB_ERROR; } } buf[0] = cpu_to_le32(scope_index->class_perms_len); if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1) { return POLICYDB_ERROR; } for (i = 0; i < scope_index->class_perms_len; i++) { if (ebitmap_write(scope_index->class_perms_map + i, fp) == -1) { return POLICYDB_ERROR; } } return POLICYDB_SUCCESS; } static int avrule_decl_write(avrule_decl_t * decl, int num_scope_syms, policydb_t * p, struct policy_file *fp) { struct policy_data pd; uint32_t buf[2]; int i; buf[0] = cpu_to_le32(decl->decl_id); buf[1] = cpu_to_le32(decl->enabled); if (put_entry(buf, sizeof(uint32_t), 2, fp) != 2) { return POLICYDB_ERROR; } if (cond_write_list(p, decl->cond_list, fp) == -1 || avrule_write_list(p, decl->avrules, fp, 0) == -1 || role_trans_rule_write(p, decl->role_tr_rules, fp) == -1 || role_allow_rule_write(decl->role_allow_rules, fp) == -1) { return POLICYDB_ERROR; } if (p->policyvers >= MOD_POLICYDB_VERSION_FILENAME_TRANS && filename_trans_rule_write(p, decl->filename_trans_rules, fp)) return POLICYDB_ERROR; if (p->policyvers >= MOD_POLICYDB_VERSION_RANGETRANS && range_trans_rule_write(decl->range_tr_rules, fp) == -1) { return POLICYDB_ERROR; } if (scope_index_write(&decl->required, num_scope_syms, fp) == -1 || scope_index_write(&decl->declared, num_scope_syms, fp) == -1) { return POLICYDB_ERROR; } pd.fp = fp; pd.p = p; for (i = 0; i < num_scope_syms; i++) { buf[0] = cpu_to_le32(decl->symtab[i].nprim); buf[1] = cpu_to_le32(decl->symtab[i].table->nel); if (put_entry(buf, sizeof(uint32_t), 2, fp) != 2) { return POLICYDB_ERROR; } if (hashtab_map(decl->symtab[i].table, write_f[i], &pd)) { return POLICYDB_ERROR; } } return POLICYDB_SUCCESS; } static int avrule_block_write(avrule_block_t * block, int num_scope_syms, policydb_t * p, struct policy_file *fp) { /* first write a count of the total number of blocks */ uint32_t buf[1], num_blocks = 0; avrule_block_t *cur; for (cur = block; cur != NULL; cur = cur->next) { num_blocks++; } buf[0] = cpu_to_le32(num_blocks); if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1) { return POLICYDB_ERROR; } /* now write each block */ for (cur = block; cur != NULL; cur = cur->next) { uint32_t num_decls = 0; avrule_decl_t *decl; /* write a count of number of branches */ for (decl = cur->branch_list; decl != NULL; decl = decl->next) { num_decls++; } buf[0] = cpu_to_le32(num_decls); if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1) { return POLICYDB_ERROR; } for (decl = cur->branch_list; decl != NULL; decl = decl->next) { if (avrule_decl_write(decl, num_scope_syms, p, fp) == -1) { return POLICYDB_ERROR; } } } return POLICYDB_SUCCESS; } static int scope_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr) { scope_datum_t *scope = (scope_datum_t *) datum; struct policy_data *pd = ptr; struct policy_file *fp = pd->fp; uint32_t static_buf[32], *dyn_buf = NULL, *buf; size_t key_len = strlen(key); unsigned int items = 2 + scope->decl_ids_len, i; int rc; buf = static_buf; if (items >= (sizeof(static_buf) / 4)) { /* too many things required, so dynamically create a * buffer. this would have been easier with C99's * dynamic arrays... */ rc = POLICYDB_ERROR; dyn_buf = calloc(items, sizeof(*dyn_buf)); if (!dyn_buf) goto err; buf = dyn_buf; } buf[0] = cpu_to_le32(key_len); rc = POLICYDB_ERROR; if (put_entry(buf, sizeof(*buf), 1, fp) != 1 || put_entry(key, 1, key_len, fp) != key_len) goto err; buf[0] = cpu_to_le32(scope->scope); buf[1] = cpu_to_le32(scope->decl_ids_len); for (i = 0; i < scope->decl_ids_len; i++) buf[2 + i] = cpu_to_le32(scope->decl_ids[i]); rc = POLICYDB_ERROR; if (put_entry(buf, sizeof(*buf), items, fp) != items) goto err; rc = POLICYDB_SUCCESS; err: free(dyn_buf); return rc; } static int type_attr_uncount(hashtab_key_t key __attribute__ ((unused)), hashtab_datum_t datum, void *args) { type_datum_t *typdatum = datum; uint32_t *p_nel = args; if (typdatum->flavor == TYPE_ATTRIB) { /* uncount attribute from total number of types */ (*p_nel)--; } return 0; } static int role_attr_uncount(hashtab_key_t key __attribute__ ((unused)), hashtab_datum_t datum, void *args) { role_datum_t *role = datum; uint32_t *p_nel = args; if (role->flavor == ROLE_ATTRIB) { /* uncount attribute from total number of roles */ (*p_nel)--; } return 0; } /* * Write the configuration data in a policy database * structure to a policy database binary representation * file. */ int policydb_write(policydb_t * p, struct policy_file *fp) { unsigned int i, num_syms; uint32_t buf[32], config; size_t items, items2, len; const struct policydb_compat_info *info; struct policy_data pd; const char *policydb_str; if (p->unsupported_format) return POLICYDB_UNSUPPORTED; pd.fp = fp; pd.p = p; config = 0; if (p->mls) { if ((p->policyvers < POLICYDB_VERSION_MLS && p->policy_type == POLICY_KERN) || (p->policyvers < MOD_POLICYDB_VERSION_MLS && p->policy_type == POLICY_BASE) || (p->policyvers < MOD_POLICYDB_VERSION_MLS && p->policy_type == POLICY_MOD)) { ERR(fp->handle, "%spolicy version %d cannot support MLS", p->policy_type == POLICY_KERN ? "" : "module ", p->policyvers); return POLICYDB_ERROR; } config |= POLICYDB_CONFIG_MLS; } config |= (POLICYDB_CONFIG_UNKNOWN_MASK & p->handle_unknown); /* Write the magic number and string identifiers. */ items = 0; if (p->policy_type == POLICY_KERN) { buf[items++] = cpu_to_le32(POLICYDB_MAGIC); len = strlen(policydb_target_strings[p->target_platform]); policydb_str = policydb_target_strings[p->target_platform]; } else { buf[items++] = cpu_to_le32(POLICYDB_MOD_MAGIC); len = strlen(POLICYDB_MOD_STRING); policydb_str = POLICYDB_MOD_STRING; } buf[items++] = cpu_to_le32(len); items2 = put_entry(buf, sizeof(uint32_t), items, fp); if (items != items2) return POLICYDB_ERROR; items = put_entry(policydb_str, 1, len, fp); if (items != len) return POLICYDB_ERROR; /* Write the version, config, and table sizes. */ items = 0; info = policydb_lookup_compat(p->policyvers, p->policy_type, p->target_platform); if (!info) { ERR(fp->handle, "compatibility lookup failed for %s%s policy version %d", p->target_platform == SEPOL_TARGET_SELINUX ? "selinux" : "xen", p->policy_type == POLICY_KERN ? "" : " module", p->policyvers); return POLICYDB_ERROR; } if (p->policy_type != POLICY_KERN) { buf[items++] = cpu_to_le32(p->policy_type); } buf[items++] = cpu_to_le32(p->policyvers); buf[items++] = cpu_to_le32(config); buf[items++] = cpu_to_le32(info->sym_num); buf[items++] = cpu_to_le32(info->ocon_num); items2 = put_entry(buf, sizeof(uint32_t), items, fp); if (items != items2) return POLICYDB_ERROR; if (p->policy_type == POLICY_MOD) { /* Write module name and version */ len = strlen(p->name); buf[0] = cpu_to_le32(len); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; items = put_entry(p->name, 1, len, fp); if (items != len) return POLICYDB_ERROR; len = strlen(p->version); buf[0] = cpu_to_le32(len); items = put_entry(buf, sizeof(uint32_t), 1, fp); if (items != 1) return POLICYDB_ERROR; items = put_entry(p->version, 1, len, fp); if (items != len) return POLICYDB_ERROR; } if ((p->policyvers >= POLICYDB_VERSION_POLCAP && p->policy_type == POLICY_KERN) || (p->policyvers >= MOD_POLICYDB_VERSION_POLCAP && p->policy_type == POLICY_BASE) || (p->policyvers >= MOD_POLICYDB_VERSION_POLCAP && p->policy_type == POLICY_MOD)) { if (ebitmap_write(&p->policycaps, fp) == -1) return POLICYDB_ERROR; } if (p->policyvers < POLICYDB_VERSION_PERMISSIVE && p->policy_type == POLICY_KERN) { ebitmap_node_t *tnode; ebitmap_for_each_positive_bit(&p->permissive_map, tnode, i) { WARN(fp->handle, "Warning! Policy version %d cannot " "support permissive types, but some were defined", p->policyvers); break; } } if (p->policyvers >= POLICYDB_VERSION_PERMISSIVE && p->policy_type == POLICY_KERN) { if (ebitmap_write(&p->permissive_map, fp) == -1) return POLICYDB_ERROR; } num_syms = info->sym_num; for (i = 0; i < num_syms; i++) { buf[0] = cpu_to_le32(p->symtab[i].nprim); buf[1] = p->symtab[i].table->nel; /* * A special case when writing type/attribute symbol table. * The kernel policy version less than 24 does not support * to load entries of attribute, so we have to re-calculate * the actual number of types except for attributes. */ if (i == SYM_TYPES && p->policyvers < POLICYDB_VERSION_BOUNDARY && p->policy_type == POLICY_KERN) { hashtab_map(p->symtab[i].table, type_attr_uncount, &buf[1]); } /* * Another special case when writing role/attribute symbol * table, role attributes are redundant for policy.X, or * when the pp's version is not big enough. So deduct * their numbers from p_roles.table->nel. */ if ((i == SYM_ROLES) && ((p->policy_type == POLICY_KERN) || (p->policy_type != POLICY_KERN && p->policyvers < MOD_POLICYDB_VERSION_ROLEATTRIB))) (void)hashtab_map(p->symtab[i].table, role_attr_uncount, &buf[1]); buf[1] = cpu_to_le32(buf[1]); items = put_entry(buf, sizeof(uint32_t), 2, fp); if (items != 2) return POLICYDB_ERROR; if (hashtab_map(p->symtab[i].table, write_f[i], &pd)) return POLICYDB_ERROR; } if (p->policy_type == POLICY_KERN) { if (avtab_write(p, &p->te_avtab, fp)) return POLICYDB_ERROR; if (p->policyvers < POLICYDB_VERSION_BOOL) { if (p->p_bools.nprim) WARN(fp->handle, "Discarding " "booleans and conditional rules"); } else { if (cond_write_list(p, p->cond_list, fp)) return POLICYDB_ERROR; } if (role_trans_write(p, fp)) return POLICYDB_ERROR; if (role_allow_write(p->role_allow, fp)) return POLICYDB_ERROR; if (p->policyvers >= POLICYDB_VERSION_FILENAME_TRANS) { if (filename_trans_write(p, fp)) return POLICYDB_ERROR; } else { if (p->filename_trans) WARN(fp->handle, "Discarding filename type transition rules"); } } else { if (avrule_block_write(p->global, num_syms, p, fp) == -1) { return POLICYDB_ERROR; } for (i = 0; i < num_syms; i++) { buf[0] = cpu_to_le32(p->scope[i].table->nel); if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1) { return POLICYDB_ERROR; } if (hashtab_map(p->scope[i].table, scope_write, &pd)) return POLICYDB_ERROR; } } if (ocontext_write(info, p, fp) == -1 || genfs_write(p, fp) == -1) { return POLICYDB_ERROR; } if ((p->policyvers >= POLICYDB_VERSION_MLS && p->policy_type == POLICY_KERN) || (p->policyvers >= MOD_POLICYDB_VERSION_MLS && p->policyvers < MOD_POLICYDB_VERSION_RANGETRANS && p->policy_type == POLICY_BASE)) { if (range_write(p, fp)) { return POLICYDB_ERROR; } } if (p->policy_type == POLICY_KERN && p->policyvers >= POLICYDB_VERSION_AVTAB) { for (i = 0; i < p->p_types.nprim; i++) { if (ebitmap_write(&p->type_attr_map[i], fp) == -1) return POLICYDB_ERROR; } } return POLICYDB_SUCCESS; } libsepol-3.8.1/tests/000077500000000000000000000000001476211737200145105ustar00rootroot00000000000000libsepol-3.8.1/tests/.gitignore000066400000000000000000000000171476211737200164760ustar00rootroot00000000000000libsepol-tests libsepol-3.8.1/tests/Makefile000066400000000000000000000043761476211737200161620ustar00rootroot00000000000000ENV ?= env M4 ?= m4 -E -E MKDIR ?= mkdir EXE ?= libsepol-tests CFLAGS += -g3 -gdwarf-2 -O0 \ -Werror -Wall -Wextra \ -Wfloat-equal \ -Wformat=2 \ -Winit-self \ -Wmissing-format-attribute \ -Wmissing-noreturn \ -Wmissing-prototypes \ -Wnull-dereference \ -Wpointer-arith \ -Wshadow \ -Wstrict-prototypes \ -Wundef \ -Wunused \ -Wwrite-strings \ -fno-common # Statically link libsepol on the assumption that we are going to # be testing internal functions. LIBSEPOL := ../src/libsepol.a # In order to load source policies we need to link in the checkpolicy/checkmodule parser and util code. # This is less than ideal, but it makes the tests easier to maintain by allowing source policies # to be loaded directly. CHECKPOLICY := ../../checkpolicy/ override CPPFLAGS += -I../include/ -I$(CHECKPOLICY) # test program object files objs := $(patsubst %.c,%.o,$(sort $(wildcard *.c))) parserobjs := $(CHECKPOLICY)queue.o $(CHECKPOLICY)y.tab.o \ $(CHECKPOLICY)parse_util.o $(CHECKPOLICY)lex.yy.o \ $(CHECKPOLICY)policy_define.o $(CHECKPOLICY)module_compiler.o # test policy pieces m4support := $(wildcard policies/support/*.spt) testsuites := $(wildcard policies/test-*) policysrc := $(foreach path,$(testsuites),$(wildcard $(path)/*.conf)) stdpol := $(addsuffix .std,$(policysrc)) mlspol := $(addsuffix .mls,$(policysrc)) policies := $(stdpol) $(mlspol) all: $(EXE) $(policies) policies: $(policies) $(EXE): $(objs) $(parserobjs) $(LIBSEPOL) $(CC) $(LDFLAGS) $(objs) $(parserobjs) -lcunit $(LIBSEPOL) -o $@ %.conf.std: $(m4support) %.conf $(M4) $(M4PARAMS) $^ > $@ %.conf.mls: $(m4support) %.conf $(M4) $(M4PARAMS) -D enable_mls $^ > $@ clean: rm -f $(objs) $(EXE) rm -f $(policies) rm -f policies/test-downgrade/policy.hi policies/test-downgrade/policy.lo # mkdir is run in a clean environment created by env -i to avoid failing under ASan with: # # ASan runtime does not come first in initial library list; # you should either link runtime to your application or manually preload it with LD_PRELOAD # # when the source code is built with ASan test: $(EXE) $(policies) $(ENV) -i $(MKDIR) -p policies/test-downgrade ../../checkpolicy/checkpolicy -M policies/test-cond/refpolicy-base.conf -o policies/test-downgrade/policy.hi ./$(EXE) .PHONY: all policies clean test libsepol-3.8.1/tests/debug.c000066400000000000000000000034461476211737200157510ustar00rootroot00000000000000/* * Author: Joshua Brindle * * Copyright (C) 2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* This includes functions used to debug tests (display bitmaps, conditional expressions, etc */ #include "debug.h" #include void print_ebitmap(ebitmap_t * bitmap, FILE * fp) { uint32_t i; for (i = 0; i < bitmap->highbit; i++) { fprintf(fp, "%d", ebitmap_get_bit(bitmap, i)); } fprintf(fp, "\n"); } /* stolen from dispol.c */ void display_expr(policydb_t * p, cond_expr_t * exp, FILE * fp) { cond_expr_t *cur; for (cur = exp; cur != NULL; cur = cur->next) { switch (cur->expr_type) { case COND_BOOL: fprintf(fp, "%s ", p->p_bool_val_to_name[cur->boolean - 1]); break; case COND_NOT: fprintf(fp, "! "); break; case COND_OR: fprintf(fp, "|| "); break; case COND_AND: fprintf(fp, "&& "); break; case COND_XOR: fprintf(fp, "^ "); break; case COND_EQ: fprintf(fp, "== "); break; case COND_NEQ: fprintf(fp, "!= "); break; default: fprintf(fp, "error! (%d)", cur->expr_type); break; } } } libsepol-3.8.1/tests/debug.h000066400000000000000000000022111476211737200157430ustar00rootroot00000000000000/* * Author: Joshua Brindle * * Copyright (C) 2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* This includes functions used to debug tests (display bitmaps, conditional expressions, etc */ #include #include extern void print_ebitmap(ebitmap_t * bitmap, FILE * fp); extern void display_expr(policydb_t * p, cond_expr_t * exp, FILE * fp); libsepol-3.8.1/tests/helpers.c000066400000000000000000000042761476211737200163270ustar00rootroot00000000000000/* * Author: Joshua Brindle * Chad Sellers * * Copyright (C) 2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* This has helper functions that are common between tests */ #include "helpers.h" #include "parse_util.h" #include #include #include #include #include int test_load_policy(policydb_t * p, int policy_type, int mls, const char *test_name, const char *policy_name) { char filename[PATH_MAX]; if (mls) { if (snprintf(filename, PATH_MAX, "policies/%s/%s.mls", test_name, policy_name) < 0) { return -1; } } else { if (snprintf(filename, PATH_MAX, "policies/%s/%s.std", test_name, policy_name) < 0) { return -1; } } if (policydb_init(p)) { fprintf(stderr, "Out of memory"); return -1; } p->policy_type = policy_type; p->mls = mls; p->policyvers = MOD_POLICYDB_VERSION_MAX; if (read_source_policy(p, filename, test_name)) { fprintf(stderr, "failed to read policy %s\n", filename); policydb_destroy(p); return -1; } return 0; } avrule_decl_t *test_find_decl_by_sym(policydb_t * p, int symtab, const char *sym) { scope_datum_t *scope = (scope_datum_t *) hashtab_search(p->scope[symtab].table, sym); if (scope == NULL) { return NULL; } if (scope->scope != SCOPE_DECL) { return NULL; } if (scope->decl_ids_len != 1) { return NULL; } return p->decl_val_to_struct[scope->decl_ids[0] - 1]; } libsepol-3.8.1/tests/helpers.h000066400000000000000000000055721476211737200163340ustar00rootroot00000000000000/* * Author: Joshua Brindle * Chad Sellers * * Copyright (C) 2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __COMMON_H__ #define __COMMON_H__ #include #include #include /* helper functions */ /* Override CU_*_FATAL() in order to help static analyzers by really asserting that an assertion holds */ #ifdef __CHECKER__ #include #undef CU_ASSERT_FATAL #define CU_ASSERT_FATAL(value) do { \ int _value = (value); \ CU_ASSERT(_value); \ assert(_value); \ } while (0) #undef CU_FAIL_FATAL #define CU_FAIL_FATAL(msg) do { \ CU_FAIL(msg); \ assert(0); \ } while (0) #undef CU_ASSERT_PTR_NOT_NULL_FATAL #define CU_ASSERT_PTR_NOT_NULL_FATAL(value) do { \ const void *_value = (value); \ CU_ASSERT_PTR_NOT_NULL(_value); \ assert(_value != NULL); \ } while (0) #endif /* __CHECKER__ */ /* Load a source policy into p. policydb_init will called within this function. * * Example: test_load_policy(p, POLICY_BASE, 1, "foo", "base.conf") will load the * policy "policies/foo/mls/base.conf" into p. * * Arguments: * p policydb_t into which the policy will be read. This should be * malloc'd but not passed to policydb_init. * policy_type Type of policy expected - POLICY_BASE or POLICY_MOD. * mls Boolean value indicating whether an mls policy is expected. * test_name Name of the test which will be the name of the directory in * which the policies are stored. * policy_name Name of the policy in the directory. * * Returns: * 0 success * -1 error - the policydb will be destroyed but not freed. */ extern int test_load_policy(policydb_t * p, int policy_type, int mls, const char *test_name, const char *policy_name); /* Find an avrule_decl_t by a unique symbol. If the symbol is declared in more * than one decl an error is returned. * * Returns: * decl success * NULL error (including more than one declaration) */ extern avrule_decl_t *test_find_decl_by_sym(policydb_t * p, int symtab, const char *sym); #endif libsepol-3.8.1/tests/libsepol-tests.c000066400000000000000000000056671476211737200176430ustar00rootroot00000000000000/* * Author: Karl MacMillan * * Copyright (C) 2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "test-cond.h" #include "test-ebitmap.h" #include "test-linker.h" #include "test-expander.h" #include "test-deps.h" #include "test-downgrade.h" #include "test-neverallow.h" #include #include #include #include #include #include #include int mls; #define DECLARE_SUITE(name) \ do { \ suite = CU_add_suite(#name, name##_test_init, name##_test_cleanup); \ if (NULL == suite) { \ CU_cleanup_registry(); \ return CU_get_error(); \ } \ if (name##_add_tests(suite)) { \ CU_cleanup_registry(); \ return CU_get_error(); \ } \ } while (0) static void usage(char *progname) { printf("usage: %s [options]\n", progname); printf("options:\n"); printf("\t-v, --verbose\t\t\tverbose output\n"); printf("\t-i, --interactive\t\tinteractive console\n"); } static bool do_tests(int interactive, int verbose) { CU_pSuite suite = NULL; unsigned int num_failures; if (CUE_SUCCESS != CU_initialize_registry()) return CU_get_error(); DECLARE_SUITE(ebitmap); DECLARE_SUITE(cond); DECLARE_SUITE(linker); DECLARE_SUITE(expander); DECLARE_SUITE(deps); DECLARE_SUITE(downgrade); DECLARE_SUITE(neverallow); if (verbose) CU_basic_set_mode(CU_BRM_VERBOSE); else CU_basic_set_mode(CU_BRM_NORMAL); if (interactive) CU_console_run_tests(); else CU_basic_run_tests(); num_failures = CU_get_number_of_tests_failed(); CU_cleanup_registry(); return CU_get_error() == CUE_SUCCESS && num_failures == 0; } int main(int argc, char **argv) { int i, verbose = 1, interactive = 0; struct option opts[] = { {"verbose", 0, NULL, 'v'}, {"interactive", 0, NULL, 'i'}, {NULL, 0, NULL, 0} }; while ((i = getopt_long(argc, argv, "vi", opts, NULL)) != -1) { switch (i) { case 'v': verbose = 1; break; case 'i': interactive = 1; break; case 'h': default:{ usage(argv[0]); exit(1); } } } /* first do the non-mls tests */ mls = 0; if (!do_tests(interactive, verbose)) return -1; /* then with mls */ mls = 1; if (!do_tests(interactive, verbose)) return -1; return 0; } libsepol-3.8.1/tests/policies/000077500000000000000000000000001476211737200163175ustar00rootroot00000000000000libsepol-3.8.1/tests/policies/.gitignore000066400000000000000000000000521476211737200203040ustar00rootroot00000000000000test-downgrade/ test-*/*.mls test-*/*.std libsepol-3.8.1/tests/policies/support/000077500000000000000000000000001476211737200200335ustar00rootroot00000000000000libsepol-3.8.1/tests/policies/support/misc_macros.spt000066400000000000000000000011751476211737200230660ustar00rootroot00000000000000 ######################################## # # Helper macros # ######################################## # # gen_user(username, prefix, role_set, mls_defaultlevel, mls_range, [mcs_categories]) # define(`gen_user',`dnl ifdef(`users_extra',`dnl ifelse(`$2',,,`user $1 prefix $2;') ',`dnl user $1 roles { $3 }`'ifdef(`enable_mls', ` level $4 range $5')`'ifdef(`enable_mcs',` level s0 range s0`'ifelse(`$6',,,` - s0:$6')'); ')dnl ') ######################################## # # gen_context(context,mls_sensitivity,[mcs_categories]) # define(`gen_context',`$1`'ifdef(`enable_mls',`:$2')`'ifdef(`enable_mcs',`:s0`'ifelse(`$3',,,`:$3')')') dnl libsepol-3.8.1/tests/policies/test-cond/000077500000000000000000000000001476211737200202175ustar00rootroot00000000000000libsepol-3.8.1/tests/policies/test-cond/refpolicy-base.conf000066400000000000000000002061161476211737200240000ustar00rootroot00000000000000class security class process class system class capability class filesystem class file class dir class fd class lnk_file class chr_file class blk_file class sock_file class fifo_file class socket class tcp_socket class udp_socket class rawip_socket class node class netif class netlink_socket class packet_socket class key_socket class unix_stream_socket class unix_dgram_socket class sem class msg class msgq class shm class ipc class passwd # userspace class drawable # userspace class window # userspace class gc # userspace class font # userspace class colormap # userspace class property # userspace class cursor # userspace class xclient # userspace class xinput # userspace class xserver # userspace class xextension # userspace class pax class netlink_route_socket class netlink_firewall_socket class netlink_tcpdiag_socket class netlink_nflog_socket class netlink_xfrm_socket class netlink_selinux_socket class netlink_audit_socket class netlink_ip6fw_socket class netlink_dnrt_socket class dbus # userspace class nscd # userspace class association class netlink_kobject_uevent_socket sid kernel sid security sid unlabeled sid fs sid file sid file_labels sid init sid any_socket sid port sid netif sid netmsg sid node sid igmp_packet sid icmp_socket sid tcp_socket sid sysctl_modprobe sid sysctl sid sysctl_fs sid sysctl_kernel sid sysctl_net sid sysctl_net_unix sid sysctl_vm sid sysctl_dev sid kmod sid policy sid scmp_packet sid devnull common file { ioctl read write create getattr setattr lock relabelfrom relabelto append unlink link rename execute swapon quotaon mounton } common socket { ioctl read write create getattr setattr lock relabelfrom relabelto append bind connect listen accept getopt setopt shutdown recvfrom sendto recv_msg send_msg name_bind } common ipc { create destroy getattr setattr read write associate unix_read unix_write } class filesystem { mount remount unmount getattr relabelfrom relabelto transition associate quotamod quotaget } class dir inherits file { add_name remove_name reparent search rmdir } class file inherits file { execute_no_trans entrypoint execmod } class lnk_file inherits file class chr_file inherits file { execute_no_trans entrypoint execmod } class blk_file inherits file class sock_file inherits file class fifo_file inherits file class fd { use } class socket inherits socket class tcp_socket inherits socket { connectto newconn acceptfrom node_bind name_connect } class udp_socket inherits socket { node_bind } class rawip_socket inherits socket { node_bind } class node { tcp_recv tcp_send udp_recv udp_send rawip_recv rawip_send enforce_dest } class netif { tcp_recv tcp_send udp_recv udp_send rawip_recv rawip_send } class netlink_socket inherits socket class packet_socket inherits socket class key_socket inherits socket class unix_stream_socket inherits socket { connectto newconn acceptfrom } class unix_dgram_socket inherits socket class process { fork transition sigchld # commonly granted from child to parent sigkill # cannot be caught or ignored sigstop # cannot be caught or ignored signull # for kill(pid, 0) signal # all other signals ptrace getsched setsched getsession getpgid setpgid getcap setcap share getattr setexec setfscreate noatsecure siginh setrlimit rlimitinh dyntransition setcurrent execmem execstack execheap } class ipc inherits ipc class sem inherits ipc class msgq inherits ipc { enqueue } class msg { send receive } class shm inherits ipc { lock } class security { compute_av compute_create compute_member check_context load_policy compute_relabel compute_user setenforce # was avc_toggle in system class setbool setsecparam setcheckreqprot } class system { ipc_info syslog_read syslog_mod syslog_console } class capability { chown dac_override dac_read_search fowner fsetid kill setgid setuid setpcap linux_immutable net_bind_service net_broadcast net_admin net_raw ipc_lock ipc_owner sys_module sys_rawio sys_chroot sys_ptrace sys_pacct sys_admin sys_boot sys_nice sys_resource sys_time sys_tty_config mknod lease audit_write audit_control } class passwd { passwd # change another user passwd chfn # change another user finger info chsh # change another user shell rootok # pam_rootok check (skip auth) crontab # crontab on another user } class drawable { create destroy draw copy getattr } class gc { create free getattr setattr } class window { addchild create destroy map unmap chstack chproplist chprop listprop getattr setattr setfocus move chselection chparent ctrllife enumerate transparent mousemotion clientcomevent inputevent drawevent windowchangeevent windowchangerequest serverchangeevent extensionevent } class font { load free getattr use } class colormap { create free install uninstall list read store getattr setattr } class property { create free read write } class cursor { create createglyph free assign setattr } class xclient { kill } class xinput { lookup getattr setattr setfocus warppointer activegrab passivegrab ungrab bell mousemotion relabelinput } class xserver { screensaver gethostlist sethostlist getfontpath setfontpath getattr grab ungrab } class xextension { query use } class pax { pageexec # Paging based non-executable pages emutramp # Emulate trampolines mprotect # Restrict mprotect() randmmap # Randomize mmap() base randexec # Randomize ET_EXEC base segmexec # Segmentation based non-executable pages } class netlink_route_socket inherits socket { nlmsg_read nlmsg_write } class netlink_firewall_socket inherits socket { nlmsg_read nlmsg_write } class netlink_tcpdiag_socket inherits socket { nlmsg_read nlmsg_write } class netlink_nflog_socket inherits socket class netlink_xfrm_socket inherits socket { nlmsg_read nlmsg_write } class netlink_selinux_socket inherits socket class netlink_audit_socket inherits socket { nlmsg_read nlmsg_write nlmsg_relay nlmsg_readpriv } class netlink_ip6fw_socket inherits socket { nlmsg_read nlmsg_write } class netlink_dnrt_socket inherits socket class dbus { acquire_svc send_msg } class nscd { getpwd getgrp gethost getstat admin shmempwd shmemgrp shmemhost } class association { sendto recvfrom setcontext } class netlink_kobject_uevent_socket inherits socket sensitivity s0; dominance { s0 } category c0; category c1; category c2; category c3; category c4; category c5; category c6; category c7; category c8; category c9; category c10; category c11; category c12; category c13; category c14; category c15; category c16; category c17; category c18; category c19; category c20; category c21; category c22; category c23; category c24; category c25; category c26; category c27; category c28; category c29; category c30; category c31; category c32; category c33; category c34; category c35; category c36; category c37; category c38; category c39; category c40; category c41; category c42; category c43; category c44; category c45; category c46; category c47; category c48; category c49; category c50; category c51; category c52; category c53; category c54; category c55; category c56; category c57; category c58; category c59; category c60; category c61; category c62; category c63; category c64; category c65; category c66; category c67; category c68; category c69; category c70; category c71; category c72; category c73; category c74; category c75; category c76; category c77; category c78; category c79; category c80; category c81; category c82; category c83; category c84; category c85; category c86; category c87; category c88; category c89; category c90; category c91; category c92; category c93; category c94; category c95; category c96; category c97; category c98; category c99; category c100; category c101; category c102; category c103; category c104; category c105; category c106; category c107; category c108; category c109; category c110; category c111; category c112; category c113; category c114; category c115; category c116; category c117; category c118; category c119; category c120; category c121; category c122; category c123; category c124; category c125; category c126; category c127; category c128; category c129; category c130; category c131; category c132; category c133; category c134; category c135; category c136; category c137; category c138; category c139; category c140; category c141; category c142; category c143; category c144; category c145; category c146; category c147; category c148; category c149; category c150; category c151; category c152; category c153; category c154; category c155; category c156; category c157; category c158; category c159; category c160; category c161; category c162; category c163; category c164; category c165; category c166; category c167; category c168; category c169; category c170; category c171; category c172; category c173; category c174; category c175; category c176; category c177; category c178; category c179; category c180; category c181; category c182; category c183; category c184; category c185; category c186; category c187; category c188; category c189; category c190; category c191; category c192; category c193; category c194; category c195; category c196; category c197; category c198; category c199; category c200; category c201; category c202; category c203; category c204; category c205; category c206; category c207; category c208; category c209; category c210; category c211; category c212; category c213; category c214; category c215; category c216; category c217; category c218; category c219; category c220; category c221; category c222; category c223; category c224; category c225; category c226; category c227; category c228; category c229; category c230; category c231; category c232; category c233; category c234; category c235; category c236; category c237; category c238; category c239; category c240; category c241; category c242; category c243; category c244; category c245; category c246; category c247; category c248; category c249; category c250; category c251; category c252; category c253; category c254; category c255; level s0:c0.c255; mlsconstrain file { write setattr append unlink link rename ioctl lock execute relabelfrom } (h1 dom h2); mlsconstrain file { create relabelto } ((h1 dom h2) and (l2 eq h2)); mlsconstrain file { read } ((h1 dom h2) or ( t2 == domain ) or ( t1 == mlsfileread )); mlsconstrain { dir lnk_file chr_file blk_file sock_file fifo_file } { relabelfrom } ( h1 dom h2 ); mlsconstrain { dir lnk_file chr_file blk_file sock_file fifo_file } { create relabelto } (( h1 dom h2 ) and ( l2 eq h2 )); mlsconstrain process { ptrace } ( h1 dom h2 ); mlsconstrain process { sigkill sigstop } ( h1 dom h2 ) or ( t1 == mcskillall ); mlsconstrain xextension query ( t1 == mlsfileread ); attribute netif_type; attribute node_type; attribute port_type; attribute reserved_port_type; attribute device_node; attribute memory_raw_read; attribute memory_raw_write; attribute domain; attribute unconfined_domain_type; attribute set_curr_context; attribute entry_type; attribute privfd; attribute can_change_process_identity; attribute can_change_process_role; attribute can_change_object_identity; attribute can_system_change; attribute process_user_target; attribute cron_source_domain; attribute cron_job_domain; attribute process_uncond_exempt; # add userhelperdomain to this one attribute file_type; attribute lockfile; attribute mountpoint; attribute pidfile; attribute polydir; attribute usercanread; attribute polyparent; attribute polymember; attribute security_file_type; attribute tmpfile; attribute tmpfsfile; attribute filesystem_type; attribute noxattrfs; attribute can_load_kernmodule; attribute can_receive_kernel_messages; attribute kern_unconfined; attribute proc_type; attribute sysctl_type; attribute mcskillall; attribute mlsfileread; attribute mlsfilereadtoclr; attribute mlsfilewrite; attribute mlsfilewritetoclr; attribute mlsfileupgrade; attribute mlsfiledowngrade; attribute mlsnetread; attribute mlsnetreadtoclr; attribute mlsnetwrite; attribute mlsnetwritetoclr; attribute mlsnetupgrade; attribute mlsnetdowngrade; attribute mlsnetrecvall; attribute mlsipcread; attribute mlsipcreadtoclr; attribute mlsipcwrite; attribute mlsipcwritetoclr; attribute mlsprocread; attribute mlsprocreadtoclr; attribute mlsprocwrite; attribute mlsprocwritetoclr; attribute mlsprocsetsl; attribute mlsxwinread; attribute mlsxwinreadtoclr; attribute mlsxwinwrite; attribute mlsxwinwritetoclr; attribute mlsxwinreadproperty; attribute mlsxwinwriteproperty; attribute mlsxwinreadcolormap; attribute mlsxwinwritecolormap; attribute mlsxwinwritexinput; attribute mlstrustedobject; attribute privrangetrans; attribute mlsrangetrans; attribute can_load_policy; attribute can_setenforce; attribute can_setsecparam; attribute ttynode; attribute ptynode; attribute server_ptynode; attribute serial_device; type bin_t; type sbin_t; type ls_exec_t; type shell_exec_t; type chroot_exec_t; type ppp_device_t; type tun_tap_device_t; type port_t, port_type; type reserved_port_t, port_type, reserved_port_type; type afs_bos_port_t, port_type; type afs_fs_port_t, port_type; type afs_ka_port_t, port_type; type afs_pt_port_t, port_type; type afs_vl_port_t, port_type; type amanda_port_t, port_type; type amavisd_recv_port_t, port_type; type amavisd_send_port_t, port_type; type asterisk_port_t, port_type; type auth_port_t, port_type; type bgp_port_t, port_type; type biff_port_t, port_type, reserved_port_type; type clamd_port_t, port_type; type clockspeed_port_t, port_type; type comsat_port_t, port_type; type cvs_port_t, port_type; type dcc_port_t, port_type; type dbskkd_port_t, port_type; type dhcpc_port_t, port_type; type dhcpd_port_t, port_type; type dict_port_t, port_type; type distccd_port_t, port_type; type dns_port_t, port_type; type fingerd_port_t, port_type; type ftp_data_port_t, port_type; type ftp_port_t, port_type; type gatekeeper_port_t, port_type; type giftd_port_t, port_type; type gopher_port_t, port_type; type http_cache_port_t, port_type; type http_port_t, port_type; type howl_port_t, port_type; type hplip_port_t, port_type; type i18n_input_port_t, port_type; type imaze_port_t, port_type; type inetd_child_port_t, port_type; type innd_port_t, port_type; type ipp_port_t, port_type; type ircd_port_t, port_type; type isakmp_port_t, port_type; type jabber_client_port_t, port_type; type jabber_interserver_port_t, port_type; type kerberos_admin_port_t, port_type; type kerberos_master_port_t, port_type; type kerberos_port_t, port_type; type ktalkd_port_t, port_type; type ldap_port_t, port_type; type lrrd_port_t, port_type; type mail_port_t, port_type; type monopd_port_t, port_type; type mysqld_port_t, port_type; type nessus_port_t, port_type; type nmbd_port_t, port_type; type ntp_port_t, port_type; type openvpn_port_t, port_type; type pegasus_http_port_t, port_type; type pegasus_https_port_t, port_type; type pop_port_t, port_type; type portmap_port_t, port_type; type postgresql_port_t, port_type; type postgrey_port_t, port_type; type printer_port_t, port_type; type ptal_port_t, port_type; type pxe_port_t, port_type; type pyzor_port_t, port_type; type radacct_port_t, port_type; type radius_port_t, port_type; type razor_port_t, port_type; type rlogind_port_t, port_type; type rndc_port_t, port_type; type router_port_t, port_type; type rsh_port_t, port_type; type rsync_port_t, port_type; type smbd_port_t, port_type; type smtp_port_t, port_type; type snmp_port_t, port_type; type spamd_port_t, port_type; type ssh_port_t, port_type; type soundd_port_t, port_type; type socks_port_t, port_type; type stunnel_port_t, port_type; type swat_port_t, port_type; type syslogd_port_t, port_type; type telnetd_port_t, port_type; type tftp_port_t, port_type; type transproxy_port_t, port_type; type utcpserver_port_t, port_type; type uucpd_port_t, port_type; type vnc_port_t, port_type; type xserver_port_t, port_type; type xen_port_t, port_type; type zebra_port_t, port_type; type zope_port_t, port_type; type node_t, node_type; type compat_ipv4_node_t alias node_compat_ipv4_t, node_type; type inaddr_any_node_t alias node_inaddr_any_t, node_type; type node_internal_t, node_type; type link_local_node_t alias node_link_local_t, node_type; type lo_node_t alias node_lo_t, node_type; type mapped_ipv4_node_t alias node_mapped_ipv4_t, node_type; type multicast_node_t alias node_multicast_t, node_type; type site_local_node_t alias node_site_local_t, node_type; type unspec_node_t alias node_unspec_t, node_type; type netif_t, netif_type; type device_t; type agp_device_t; type apm_bios_t; type cardmgr_dev_t; type clock_device_t; type cpu_device_t; type crypt_device_t; type dri_device_t; type event_device_t; type framebuf_device_t; type lvm_control_t; type memory_device_t; type misc_device_t; type mouse_device_t; type mtrr_device_t; type null_device_t; type power_device_t; type printer_device_t; type random_device_t; type scanner_device_t; type sound_device_t; type sysfs_t; type urandom_device_t; type usbfs_t alias usbdevfs_t; type usb_device_t; type v4l_device_t; type xserver_misc_device_t; type zero_device_t; type xconsole_device_t; type devfs_control_t; type boot_t; type default_t, file_type, mountpoint; type etc_t, file_type; type etc_runtime_t, file_type; type file_t, file_type, mountpoint; type home_root_t, file_type, mountpoint; type lost_found_t, file_type; type mnt_t, file_type, mountpoint; type modules_object_t; type no_access_t, file_type; type poly_t, file_type; type readable_t, file_type; type root_t, file_type, mountpoint; type src_t, file_type, mountpoint; type system_map_t; type tmp_t, mountpoint; #, polydir type usr_t, file_type, mountpoint; type var_t, file_type, mountpoint; type var_lib_t, file_type, mountpoint; type var_lock_t, file_type, lockfile; type var_run_t, file_type, pidfile; type var_spool_t; type fs_t; type bdev_t; type binfmt_misc_fs_t; type capifs_t; type configfs_t; type eventpollfs_t; type futexfs_t; type hugetlbfs_t; type inotifyfs_t; type nfsd_fs_t; type ramfs_t; type romfs_t; type rpc_pipefs_t; type tmpfs_t; type autofs_t, noxattrfs; type cifs_t alias sambafs_t, noxattrfs; type dosfs_t, noxattrfs; type iso9660_t, filesystem_type, noxattrfs; type removable_t, noxattrfs; type nfs_t, filesystem_type, noxattrfs; type kernel_t, can_load_kernmodule; type debugfs_t; type proc_t, proc_type; type proc_kmsg_t, proc_type; type proc_kcore_t, proc_type; type proc_mdstat_t, proc_type; type proc_net_t, proc_type; type proc_xen_t, proc_type; type sysctl_t, sysctl_type; type sysctl_irq_t, sysctl_type; type sysctl_rpc_t, sysctl_type; type sysctl_fs_t, sysctl_type; type sysctl_kernel_t, sysctl_type; type sysctl_modprobe_t, sysctl_type; type sysctl_hotplug_t, sysctl_type; type sysctl_net_t, sysctl_type; type sysctl_net_unix_t, sysctl_type; type sysctl_vm_t, sysctl_type; type sysctl_dev_t, sysctl_type; type unlabeled_t; type auditd_exec_t; type crond_exec_t; type cupsd_exec_t; type getty_t; type init_t; type init_exec_t; type initrc_t; type initrc_exec_t; type login_exec_t; type sshd_exec_t; type su_exec_t; type udev_exec_t; type unconfined_t; type xdm_exec_t; type lvm_exec_t; type security_t; type bsdpty_device_t; type console_device_t; type devpts_t; type devtty_t; type ptmx_t; type tty_device_t, serial_device; type usbtty_device_t, serial_device; bool secure_mode false; bool secure_mode_insmod false; bool secure_mode_policyload false; bool allow_cvs_read_shadow false; bool allow_execheap false; bool allow_execmem true; bool allow_execmod false; bool allow_execstack true; bool allow_ftpd_anon_write false; bool allow_gssd_read_tmp true; bool allow_httpd_anon_write false; bool allow_java_execstack false; bool allow_kerberos true; bool allow_rsync_anon_write false; bool allow_saslauthd_read_shadow false; bool allow_smbd_anon_write false; bool allow_ptrace false; bool allow_ypbind false; bool fcron_crond false; bool ftp_home_dir false; bool ftpd_is_daemon true; bool httpd_builtin_scripting true; bool httpd_can_network_connect false; bool httpd_can_network_connect_db false; bool httpd_can_network_relay false; bool httpd_enable_cgi true; bool httpd_enable_ftp_server false; bool httpd_enable_homedirs true; bool httpd_ssi_exec true; bool httpd_tty_comm false; bool httpd_unified true; bool named_write_master_zones false; bool nfs_export_all_rw true; bool nfs_export_all_ro true; bool pppd_can_insmod false; bool read_default_t true; bool run_ssh_inetd false; bool samba_enable_home_dirs false; bool spamassasin_can_network false; bool squid_connect_any false; bool ssh_sysadm_login false; bool stunnel_is_daemon false; bool use_nfs_home_dirs false; bool use_samba_home_dirs false; bool user_ping true; bool spamd_enable_home_dirs true; allow bin_t fs_t:filesystem associate; allow bin_t noxattrfs:filesystem associate; typeattribute bin_t file_type; allow sbin_t fs_t:filesystem associate; allow sbin_t noxattrfs:filesystem associate; typeattribute sbin_t file_type; allow ls_exec_t fs_t:filesystem associate; allow ls_exec_t noxattrfs:filesystem associate; typeattribute ls_exec_t file_type; typeattribute ls_exec_t entry_type; allow shell_exec_t fs_t:filesystem associate; allow shell_exec_t noxattrfs:filesystem associate; typeattribute shell_exec_t file_type; allow chroot_exec_t fs_t:filesystem associate; allow chroot_exec_t noxattrfs:filesystem associate; typeattribute chroot_exec_t file_type; typeattribute ppp_device_t device_node; allow ppp_device_t fs_t:filesystem associate; allow ppp_device_t tmpfs_t:filesystem associate; allow ppp_device_t tmp_t:filesystem associate; typeattribute tun_tap_device_t device_node; allow tun_tap_device_t fs_t:filesystem associate; allow tun_tap_device_t tmpfs_t:filesystem associate; allow tun_tap_device_t tmp_t:filesystem associate; typeattribute auth_port_t reserved_port_type; typeattribute bgp_port_t reserved_port_type; typeattribute bgp_port_t reserved_port_type; typeattribute comsat_port_t reserved_port_type; typeattribute dhcpc_port_t reserved_port_type; typeattribute dhcpd_port_t reserved_port_type; typeattribute dhcpd_port_t reserved_port_type; typeattribute dhcpd_port_t reserved_port_type; typeattribute dhcpd_port_t reserved_port_type; typeattribute dhcpd_port_t reserved_port_type; typeattribute dns_port_t reserved_port_type; typeattribute dns_port_t reserved_port_type; typeattribute fingerd_port_t reserved_port_type; typeattribute ftp_data_port_t reserved_port_type; typeattribute ftp_port_t reserved_port_type; typeattribute gopher_port_t reserved_port_type; typeattribute gopher_port_t reserved_port_type; typeattribute http_port_t reserved_port_type; typeattribute http_port_t reserved_port_type; typeattribute http_port_t reserved_port_type; typeattribute inetd_child_port_t reserved_port_type; typeattribute inetd_child_port_t reserved_port_type; typeattribute inetd_child_port_t reserved_port_type; typeattribute inetd_child_port_t reserved_port_type; typeattribute inetd_child_port_t reserved_port_type; typeattribute inetd_child_port_t reserved_port_type; typeattribute inetd_child_port_t reserved_port_type; typeattribute inetd_child_port_t reserved_port_type; typeattribute inetd_child_port_t reserved_port_type; typeattribute inetd_child_port_t reserved_port_type; typeattribute inetd_child_port_t reserved_port_type; typeattribute inetd_child_port_t reserved_port_type; typeattribute inetd_child_port_t reserved_port_type; typeattribute inetd_child_port_t reserved_port_type; typeattribute inetd_child_port_t reserved_port_type; typeattribute inetd_child_port_t reserved_port_type; typeattribute inetd_child_port_t reserved_port_type; typeattribute innd_port_t reserved_port_type; typeattribute ipp_port_t reserved_port_type; typeattribute ipp_port_t reserved_port_type; typeattribute isakmp_port_t reserved_port_type; typeattribute kerberos_admin_port_t reserved_port_type; typeattribute kerberos_admin_port_t reserved_port_type; typeattribute kerberos_admin_port_t reserved_port_type; typeattribute kerberos_port_t reserved_port_type; typeattribute kerberos_port_t reserved_port_type; typeattribute kerberos_port_t reserved_port_type; typeattribute kerberos_port_t reserved_port_type; typeattribute ktalkd_port_t reserved_port_type; typeattribute ktalkd_port_t reserved_port_type; typeattribute ldap_port_t reserved_port_type; typeattribute ldap_port_t reserved_port_type; typeattribute ldap_port_t reserved_port_type; typeattribute ldap_port_t reserved_port_type; typeattribute nmbd_port_t reserved_port_type; typeattribute nmbd_port_t reserved_port_type; typeattribute nmbd_port_t reserved_port_type; typeattribute ntp_port_t reserved_port_type; typeattribute pop_port_t reserved_port_type; typeattribute pop_port_t reserved_port_type; typeattribute pop_port_t reserved_port_type; typeattribute pop_port_t reserved_port_type; typeattribute pop_port_t reserved_port_type; typeattribute pop_port_t reserved_port_type; typeattribute pop_port_t reserved_port_type; typeattribute portmap_port_t reserved_port_type; typeattribute portmap_port_t reserved_port_type; typeattribute printer_port_t reserved_port_type; typeattribute rlogind_port_t reserved_port_type; typeattribute rndc_port_t reserved_port_type; typeattribute router_port_t reserved_port_type; typeattribute rsh_port_t reserved_port_type; typeattribute rsync_port_t reserved_port_type; typeattribute rsync_port_t reserved_port_type; typeattribute smbd_port_t reserved_port_type; typeattribute smbd_port_t reserved_port_type; typeattribute smtp_port_t reserved_port_type; typeattribute smtp_port_t reserved_port_type; typeattribute smtp_port_t reserved_port_type; typeattribute snmp_port_t reserved_port_type; typeattribute snmp_port_t reserved_port_type; typeattribute snmp_port_t reserved_port_type; typeattribute spamd_port_t reserved_port_type; typeattribute ssh_port_t reserved_port_type; typeattribute swat_port_t reserved_port_type; typeattribute syslogd_port_t reserved_port_type; typeattribute telnetd_port_t reserved_port_type; typeattribute tftp_port_t reserved_port_type; typeattribute uucpd_port_t reserved_port_type; allow device_t tmpfs_t:filesystem associate; allow device_t fs_t:filesystem associate; allow device_t noxattrfs:filesystem associate; typeattribute device_t file_type; allow device_t fs_t:filesystem associate; allow device_t noxattrfs:filesystem associate; typeattribute device_t file_type; typeattribute device_t mountpoint; allow device_t tmp_t:filesystem associate; typeattribute agp_device_t device_node; allow agp_device_t fs_t:filesystem associate; allow agp_device_t tmpfs_t:filesystem associate; allow agp_device_t tmp_t:filesystem associate; typeattribute apm_bios_t device_node; allow apm_bios_t fs_t:filesystem associate; allow apm_bios_t tmpfs_t:filesystem associate; allow apm_bios_t tmp_t:filesystem associate; typeattribute cardmgr_dev_t device_node; allow cardmgr_dev_t fs_t:filesystem associate; allow cardmgr_dev_t tmpfs_t:filesystem associate; allow cardmgr_dev_t tmp_t:filesystem associate; allow cardmgr_dev_t fs_t:filesystem associate; allow cardmgr_dev_t noxattrfs:filesystem associate; typeattribute cardmgr_dev_t file_type; allow cardmgr_dev_t fs_t:filesystem associate; allow cardmgr_dev_t noxattrfs:filesystem associate; typeattribute cardmgr_dev_t file_type; typeattribute cardmgr_dev_t polymember; allow cardmgr_dev_t tmpfs_t:filesystem associate; typeattribute cardmgr_dev_t tmpfile; allow cardmgr_dev_t tmp_t:filesystem associate; typeattribute clock_device_t device_node; allow clock_device_t fs_t:filesystem associate; allow clock_device_t tmpfs_t:filesystem associate; allow clock_device_t tmp_t:filesystem associate; typeattribute cpu_device_t device_node; allow cpu_device_t fs_t:filesystem associate; allow cpu_device_t tmpfs_t:filesystem associate; allow cpu_device_t tmp_t:filesystem associate; typeattribute crypt_device_t device_node; allow crypt_device_t fs_t:filesystem associate; allow crypt_device_t tmpfs_t:filesystem associate; allow crypt_device_t tmp_t:filesystem associate; typeattribute dri_device_t device_node; allow dri_device_t fs_t:filesystem associate; allow dri_device_t tmpfs_t:filesystem associate; allow dri_device_t tmp_t:filesystem associate; typeattribute event_device_t device_node; allow event_device_t fs_t:filesystem associate; allow event_device_t tmpfs_t:filesystem associate; allow event_device_t tmp_t:filesystem associate; typeattribute framebuf_device_t device_node; allow framebuf_device_t fs_t:filesystem associate; allow framebuf_device_t tmpfs_t:filesystem associate; allow framebuf_device_t tmp_t:filesystem associate; typeattribute lvm_control_t device_node; allow lvm_control_t fs_t:filesystem associate; allow lvm_control_t tmpfs_t:filesystem associate; allow lvm_control_t tmp_t:filesystem associate; typeattribute memory_device_t device_node; allow memory_device_t fs_t:filesystem associate; allow memory_device_t tmpfs_t:filesystem associate; allow memory_device_t tmp_t:filesystem associate; neverallow ~memory_raw_read memory_device_t:{ chr_file blk_file } read; neverallow ~memory_raw_write memory_device_t:{ chr_file blk_file } { append write }; typeattribute misc_device_t device_node; allow misc_device_t fs_t:filesystem associate; allow misc_device_t tmpfs_t:filesystem associate; allow misc_device_t tmp_t:filesystem associate; typeattribute mouse_device_t device_node; allow mouse_device_t fs_t:filesystem associate; allow mouse_device_t tmpfs_t:filesystem associate; allow mouse_device_t tmp_t:filesystem associate; typeattribute mtrr_device_t device_node; allow mtrr_device_t fs_t:filesystem associate; allow mtrr_device_t tmpfs_t:filesystem associate; allow mtrr_device_t tmp_t:filesystem associate; typeattribute null_device_t device_node; allow null_device_t fs_t:filesystem associate; allow null_device_t tmpfs_t:filesystem associate; allow null_device_t tmp_t:filesystem associate; typeattribute null_device_t mlstrustedobject; typeattribute power_device_t device_node; allow power_device_t fs_t:filesystem associate; allow power_device_t tmpfs_t:filesystem associate; allow power_device_t tmp_t:filesystem associate; typeattribute printer_device_t device_node; allow printer_device_t fs_t:filesystem associate; allow printer_device_t tmpfs_t:filesystem associate; allow printer_device_t tmp_t:filesystem associate; typeattribute random_device_t device_node; allow random_device_t fs_t:filesystem associate; allow random_device_t tmpfs_t:filesystem associate; allow random_device_t tmp_t:filesystem associate; typeattribute scanner_device_t device_node; allow scanner_device_t fs_t:filesystem associate; allow scanner_device_t tmpfs_t:filesystem associate; allow scanner_device_t tmp_t:filesystem associate; typeattribute sound_device_t device_node; allow sound_device_t fs_t:filesystem associate; allow sound_device_t tmpfs_t:filesystem associate; allow sound_device_t tmp_t:filesystem associate; allow sysfs_t fs_t:filesystem associate; allow sysfs_t noxattrfs:filesystem associate; typeattribute sysfs_t file_type; typeattribute sysfs_t mountpoint; typeattribute sysfs_t filesystem_type; allow sysfs_t self:filesystem associate; typeattribute urandom_device_t device_node; allow urandom_device_t fs_t:filesystem associate; allow urandom_device_t tmpfs_t:filesystem associate; allow urandom_device_t tmp_t:filesystem associate; allow usbfs_t fs_t:filesystem associate; allow usbfs_t noxattrfs:filesystem associate; typeattribute usbfs_t file_type; typeattribute usbfs_t mountpoint; typeattribute usbfs_t filesystem_type; allow usbfs_t self:filesystem associate; typeattribute usbfs_t noxattrfs; typeattribute usb_device_t device_node; allow usb_device_t fs_t:filesystem associate; allow usb_device_t tmpfs_t:filesystem associate; allow usb_device_t tmp_t:filesystem associate; typeattribute v4l_device_t device_node; allow v4l_device_t fs_t:filesystem associate; allow v4l_device_t tmpfs_t:filesystem associate; allow v4l_device_t tmp_t:filesystem associate; typeattribute xserver_misc_device_t device_node; allow xserver_misc_device_t fs_t:filesystem associate; allow xserver_misc_device_t tmpfs_t:filesystem associate; allow xserver_misc_device_t tmp_t:filesystem associate; typeattribute zero_device_t device_node; allow zero_device_t fs_t:filesystem associate; allow zero_device_t tmpfs_t:filesystem associate; allow zero_device_t tmp_t:filesystem associate; typeattribute zero_device_t mlstrustedobject; allow xconsole_device_t fs_t:filesystem associate; allow xconsole_device_t noxattrfs:filesystem associate; typeattribute xconsole_device_t file_type; allow xconsole_device_t tmpfs_t:filesystem associate; allow xconsole_device_t tmp_t:filesystem associate; typeattribute devfs_control_t device_node; allow devfs_control_t fs_t:filesystem associate; allow devfs_control_t tmpfs_t:filesystem associate; allow devfs_control_t tmp_t:filesystem associate; neverallow domain ~domain:process { transition dyntransition }; neverallow { domain -set_curr_context } self:process setcurrent; neverallow { domain unlabeled_t } ~{ domain unlabeled_t }:process *; neverallow ~{ domain unlabeled_t } *:process *; allow file_type self:filesystem associate; allow boot_t fs_t:filesystem associate; allow boot_t noxattrfs:filesystem associate; typeattribute boot_t file_type; allow boot_t fs_t:filesystem associate; allow boot_t noxattrfs:filesystem associate; typeattribute boot_t file_type; typeattribute boot_t mountpoint; allow default_t fs_t:filesystem associate; allow default_t noxattrfs:filesystem associate; allow etc_t fs_t:filesystem associate; allow etc_t noxattrfs:filesystem associate; allow etc_runtime_t fs_t:filesystem associate; allow etc_runtime_t noxattrfs:filesystem associate; allow file_t fs_t:filesystem associate; allow file_t noxattrfs:filesystem associate; allow kernel_t file_t:dir mounton; allow home_root_t fs_t:filesystem associate; allow home_root_t noxattrfs:filesystem associate; allow home_root_t fs_t:filesystem associate; allow home_root_t noxattrfs:filesystem associate; typeattribute home_root_t file_type; typeattribute home_root_t polyparent; allow lost_found_t fs_t:filesystem associate; allow lost_found_t noxattrfs:filesystem associate; allow mnt_t fs_t:filesystem associate; allow mnt_t noxattrfs:filesystem associate; allow modules_object_t fs_t:filesystem associate; allow modules_object_t noxattrfs:filesystem associate; typeattribute modules_object_t file_type; allow no_access_t fs_t:filesystem associate; allow no_access_t noxattrfs:filesystem associate; allow poly_t fs_t:filesystem associate; allow poly_t noxattrfs:filesystem associate; allow readable_t fs_t:filesystem associate; allow readable_t noxattrfs:filesystem associate; allow root_t fs_t:filesystem associate; allow root_t noxattrfs:filesystem associate; allow root_t fs_t:filesystem associate; allow root_t noxattrfs:filesystem associate; typeattribute root_t file_type; typeattribute root_t polyparent; allow kernel_t root_t:dir mounton; allow src_t fs_t:filesystem associate; allow src_t noxattrfs:filesystem associate; allow system_map_t fs_t:filesystem associate; allow system_map_t noxattrfs:filesystem associate; typeattribute system_map_t file_type; allow tmp_t fs_t:filesystem associate; allow tmp_t noxattrfs:filesystem associate; typeattribute tmp_t file_type; allow tmp_t fs_t:filesystem associate; allow tmp_t noxattrfs:filesystem associate; typeattribute tmp_t file_type; typeattribute tmp_t polymember; allow tmp_t tmpfs_t:filesystem associate; typeattribute tmp_t tmpfile; allow tmp_t tmp_t:filesystem associate; allow tmp_t fs_t:filesystem associate; allow tmp_t noxattrfs:filesystem associate; typeattribute tmp_t file_type; typeattribute tmp_t polyparent; allow usr_t fs_t:filesystem associate; allow usr_t noxattrfs:filesystem associate; allow var_t fs_t:filesystem associate; allow var_t noxattrfs:filesystem associate; allow var_lib_t fs_t:filesystem associate; allow var_lib_t noxattrfs:filesystem associate; allow var_lock_t fs_t:filesystem associate; allow var_lock_t noxattrfs:filesystem associate; allow var_run_t fs_t:filesystem associate; allow var_run_t noxattrfs:filesystem associate; allow var_spool_t fs_t:filesystem associate; allow var_spool_t noxattrfs:filesystem associate; typeattribute var_spool_t file_type; allow var_spool_t fs_t:filesystem associate; allow var_spool_t noxattrfs:filesystem associate; typeattribute var_spool_t file_type; typeattribute var_spool_t polymember; allow var_spool_t tmpfs_t:filesystem associate; typeattribute var_spool_t tmpfile; allow var_spool_t tmp_t:filesystem associate; typeattribute fs_t filesystem_type; allow fs_t self:filesystem associate; typeattribute bdev_t filesystem_type; allow bdev_t self:filesystem associate; typeattribute binfmt_misc_fs_t filesystem_type; allow binfmt_misc_fs_t self:filesystem associate; allow binfmt_misc_fs_t fs_t:filesystem associate; allow binfmt_misc_fs_t noxattrfs:filesystem associate; typeattribute binfmt_misc_fs_t file_type; typeattribute binfmt_misc_fs_t mountpoint; typeattribute capifs_t filesystem_type; allow capifs_t self:filesystem associate; typeattribute configfs_t filesystem_type; allow configfs_t self:filesystem associate; typeattribute eventpollfs_t filesystem_type; allow eventpollfs_t self:filesystem associate; typeattribute futexfs_t filesystem_type; allow futexfs_t self:filesystem associate; typeattribute hugetlbfs_t filesystem_type; allow hugetlbfs_t self:filesystem associate; allow hugetlbfs_t fs_t:filesystem associate; allow hugetlbfs_t noxattrfs:filesystem associate; typeattribute hugetlbfs_t file_type; typeattribute hugetlbfs_t mountpoint; typeattribute inotifyfs_t filesystem_type; allow inotifyfs_t self:filesystem associate; typeattribute nfsd_fs_t filesystem_type; allow nfsd_fs_t self:filesystem associate; typeattribute ramfs_t filesystem_type; allow ramfs_t self:filesystem associate; typeattribute romfs_t filesystem_type; allow romfs_t self:filesystem associate; typeattribute rpc_pipefs_t filesystem_type; allow rpc_pipefs_t self:filesystem associate; typeattribute tmpfs_t filesystem_type; allow tmpfs_t self:filesystem associate; allow tmpfs_t fs_t:filesystem associate; allow tmpfs_t noxattrfs:filesystem associate; typeattribute tmpfs_t file_type; allow tmpfs_t fs_t:filesystem associate; allow tmpfs_t noxattrfs:filesystem associate; typeattribute tmpfs_t file_type; typeattribute tmpfs_t mountpoint; allow tmpfs_t noxattrfs:filesystem associate; typeattribute autofs_t filesystem_type; allow autofs_t self:filesystem associate; allow autofs_t fs_t:filesystem associate; allow autofs_t noxattrfs:filesystem associate; typeattribute autofs_t file_type; typeattribute autofs_t mountpoint; typeattribute cifs_t filesystem_type; allow cifs_t self:filesystem associate; typeattribute dosfs_t filesystem_type; allow dosfs_t self:filesystem associate; allow dosfs_t fs_t:filesystem associate; typeattribute iso9660_t filesystem_type; allow iso9660_t self:filesystem associate; allow removable_t noxattrfs:filesystem associate; typeattribute removable_t filesystem_type; allow removable_t self:filesystem associate; allow removable_t fs_t:filesystem associate; allow removable_t noxattrfs:filesystem associate; typeattribute removable_t file_type; typeattribute removable_t usercanread; typeattribute nfs_t filesystem_type; allow nfs_t self:filesystem associate; allow nfs_t fs_t:filesystem associate; allow nfs_t noxattrfs:filesystem associate; typeattribute nfs_t file_type; typeattribute nfs_t mountpoint; neverallow ~can_load_kernmodule self:capability sys_module; role system_r; role sysadm_r; role staff_r; role user_r; role secadm_r; typeattribute kernel_t domain; allow kernel_t self:dir { read getattr lock search ioctl }; allow kernel_t self:lnk_file { read getattr lock ioctl }; allow kernel_t self:file { getattr read write append ioctl lock }; allow kernel_t self:process { fork sigchld }; role secadm_r types kernel_t; role sysadm_r types kernel_t; role user_r types kernel_t; role staff_r types kernel_t; typeattribute kernel_t privrangetrans; role system_r types kernel_t; typeattribute debugfs_t filesystem_type; allow debugfs_t self:filesystem associate; allow debugfs_t self:filesystem associate; allow proc_t fs_t:filesystem associate; allow proc_t noxattrfs:filesystem associate; typeattribute proc_t file_type; typeattribute proc_t mountpoint; typeattribute proc_t filesystem_type; allow proc_t self:filesystem associate; neverallow ~can_receive_kernel_messages proc_kmsg_t:file ~getattr; neverallow { domain -kern_unconfined } proc_kcore_t:file ~getattr; allow sysctl_t fs_t:filesystem associate; allow sysctl_t noxattrfs:filesystem associate; typeattribute sysctl_t file_type; typeattribute sysctl_t mountpoint; allow sysctl_fs_t fs_t:filesystem associate; allow sysctl_fs_t noxattrfs:filesystem associate; typeattribute sysctl_fs_t file_type; typeattribute sysctl_fs_t mountpoint; allow kernel_t self:capability *; allow kernel_t unlabeled_t:dir mounton; allow kernel_t self:process ~{ ptrace setcurrent setexec setfscreate setrlimit execmem execstack execheap }; allow kernel_t self:shm { associate getattr setattr create destroy read write lock unix_read unix_write }; allow kernel_t self:sem { associate getattr setattr create destroy read write unix_read unix_write }; allow kernel_t self:msg { send receive }; allow kernel_t self:msgq { associate getattr setattr create destroy read write enqueue unix_read unix_write }; allow kernel_t self:unix_dgram_socket { create { ioctl read getattr write setattr append bind connect getopt setopt shutdown } }; allow kernel_t self:unix_stream_socket { { create { ioctl read getattr write setattr append bind connect getopt setopt shutdown } } listen accept }; allow kernel_t self:unix_dgram_socket sendto; allow kernel_t self:unix_stream_socket connectto; allow kernel_t self:fifo_file { getattr read write append ioctl lock }; allow kernel_t self:sock_file { read getattr lock ioctl }; allow kernel_t self:fd use; allow kernel_t proc_t:dir { read getattr lock search ioctl }; allow kernel_t proc_t:{ lnk_file file } { read getattr lock ioctl }; allow kernel_t proc_net_t:dir { read getattr lock search ioctl }; allow kernel_t proc_net_t:file { read getattr lock ioctl }; allow kernel_t proc_mdstat_t:file { read getattr lock ioctl }; allow kernel_t proc_kcore_t:file getattr; allow kernel_t proc_kmsg_t:file getattr; allow kernel_t sysctl_t:dir { read getattr lock search ioctl }; allow kernel_t sysctl_kernel_t:dir { read getattr lock search ioctl }; allow kernel_t sysctl_kernel_t:file { read getattr lock ioctl }; allow kernel_t unlabeled_t:fifo_file { getattr read write append ioctl lock }; allow kernel_t unlabeled_t:association { sendto recvfrom }; allow kernel_t netif_type:netif rawip_send; allow kernel_t netif_type:netif rawip_recv; allow kernel_t node_type:node rawip_send; allow kernel_t node_type:node rawip_recv; allow kernel_t netif_t:netif rawip_send; allow kernel_t netif_type:netif { tcp_send tcp_recv }; allow kernel_t node_type:node { tcp_send tcp_recv }; allow kernel_t node_t:node rawip_send; allow kernel_t multicast_node_t:node rawip_send; allow kernel_t sysfs_t:dir { read getattr lock search ioctl }; allow kernel_t sysfs_t:{ file lnk_file } { read getattr lock ioctl }; allow kernel_t usbfs_t:dir search; allow kernel_t filesystem_type:filesystem mount; allow kernel_t security_t:dir { read search getattr }; allow kernel_t security_t:file { getattr read write }; typeattribute kernel_t can_load_policy; if(!secure_mode_policyload) { allow kernel_t security_t:security load_policy; auditallow kernel_t security_t:security load_policy; } allow kernel_t device_t:dir { read getattr lock search ioctl }; allow kernel_t device_t:lnk_file { getattr read }; allow kernel_t console_device_t:chr_file { getattr read write append ioctl lock }; allow kernel_t bin_t:dir { read getattr lock search ioctl }; allow kernel_t bin_t:lnk_file { read getattr lock ioctl }; allow kernel_t shell_exec_t:file { { read getattr lock execute ioctl } execute_no_trans }; allow kernel_t sbin_t:dir { read getattr lock search ioctl }; allow kernel_t bin_t:dir { read getattr lock search ioctl }; allow kernel_t bin_t:lnk_file { read getattr lock ioctl }; allow kernel_t bin_t:file { { read getattr lock execute ioctl } execute_no_trans }; allow kernel_t domain:process signal; allow kernel_t proc_t:dir search; allow kernel_t domain:dir search; allow kernel_t root_t:dir { read getattr lock search ioctl }; allow kernel_t root_t:lnk_file { read getattr lock ioctl }; allow kernel_t etc_t:dir { read getattr lock search ioctl }; allow kernel_t home_root_t:dir { read getattr lock search ioctl }; allow kernel_t usr_t:dir { read getattr lock search ioctl }; allow kernel_t usr_t:{ file lnk_file } { read getattr lock ioctl }; typeattribute kernel_t mlsprocread; typeattribute kernel_t mlsprocwrite; allow kernel_t self:capability *; allow kernel_t self:fifo_file { create ioctl read getattr lock write setattr append link unlink rename }; allow kernel_t self:process transition; allow kernel_t self:file { getattr read write append ioctl lock }; allow kernel_t self:nscd *; allow kernel_t self:dbus *; allow kernel_t self:passwd *; allow kernel_t proc_type:{ dir file } *; allow kernel_t sysctl_t:{ dir file } *; allow kernel_t kernel_t:system *; allow kernel_t unlabeled_t:{ dir file lnk_file sock_file fifo_file chr_file blk_file } *; allow kernel_t unlabeled_t:filesystem *; allow kernel_t unlabeled_t:association *; typeattribute kernel_t can_load_kernmodule, can_receive_kernel_messages; typeattribute kernel_t kern_unconfined; allow kernel_t { proc_t proc_net_t }:dir search; allow kernel_t sysctl_type:dir { read getattr lock search ioctl }; allow kernel_t sysctl_type:file { { getattr read write append ioctl lock } setattr }; allow kernel_t node_type:node *; allow kernel_t netif_type:netif *; allow kernel_t port_type:tcp_socket { send_msg recv_msg name_connect }; allow kernel_t port_type:udp_socket { send_msg recv_msg }; allow kernel_t port_type:{ tcp_socket udp_socket rawip_socket } name_bind; allow kernel_t node_type:{ tcp_socket udp_socket rawip_socket } node_bind; allow kernel_t unlabeled_t:association { sendto recvfrom }; allow kernel_t device_node:{ chr_file blk_file } *; allow kernel_t mtrr_device_t:{ dir file } *; allow kernel_t self:capability sys_rawio; typeattribute kernel_t memory_raw_write, memory_raw_read; typeattribute kernel_t unconfined_domain_type; typeattribute kernel_t can_change_process_identity; typeattribute kernel_t can_change_process_role; typeattribute kernel_t can_change_object_identity; typeattribute kernel_t set_curr_context; allow kernel_t domain:{ { tcp_socket udp_socket rawip_socket netlink_socket packet_socket unix_stream_socket unix_dgram_socket netlink_route_socket netlink_firewall_socket netlink_tcpdiag_socket netlink_nflog_socket netlink_xfrm_socket netlink_selinux_socket netlink_audit_socket netlink_ip6fw_socket netlink_dnrt_socket netlink_kobject_uevent_socket } socket key_socket } *; allow kernel_t domain:fd use; allow kernel_t domain:fifo_file { getattr read write append ioctl lock }; allow kernel_t domain:process ~{ transition dyntransition execmem execstack execheap }; allow kernel_t domain:{ sem msgq shm } *; allow kernel_t domain:msg { send receive }; allow kernel_t domain:dir { read getattr lock search ioctl }; allow kernel_t domain:file { read getattr lock ioctl }; allow kernel_t domain:lnk_file { read getattr lock ioctl }; dontaudit kernel_t domain:dir { read getattr lock search ioctl }; dontaudit kernel_t domain:lnk_file { read getattr lock ioctl }; dontaudit kernel_t domain:file { read getattr lock ioctl }; dontaudit kernel_t domain:sock_file { read getattr lock ioctl }; dontaudit kernel_t domain:fifo_file { read getattr lock ioctl }; allow kernel_t file_type:{ file chr_file } ~execmod; allow kernel_t file_type:{ dir lnk_file sock_file fifo_file blk_file } *; allow kernel_t file_type:filesystem *; allow kernel_t file_type:{ unix_stream_socket unix_dgram_socket } name_bind; if (allow_execmod) { allow kernel_t file_type:file execmod; } allow kernel_t filesystem_type:filesystem *; allow kernel_t filesystem_type:{ dir file lnk_file sock_file fifo_file chr_file blk_file } *; allow kernel_t security_t:dir { getattr search read }; allow kernel_t security_t:file { getattr read write }; typeattribute kernel_t can_load_policy, can_setenforce, can_setsecparam; if(!secure_mode_policyload) { allow kernel_t security_t:security *; auditallow kernel_t security_t:security { load_policy setenforce setbool }; } if (allow_execheap) { allow kernel_t self:process execheap; } if (allow_execmem) { allow kernel_t self:process execmem; } if (allow_execmem && allow_execstack) { allow kernel_t self:process execstack; auditallow kernel_t self:process execstack; } else { } if (allow_execheap) { auditallow kernel_t self:process execheap; } if (allow_execmem) { auditallow kernel_t self:process execmem; } if (read_default_t) { allow kernel_t default_t:dir { read getattr lock search ioctl }; allow kernel_t default_t:file { read getattr lock ioctl }; allow kernel_t default_t:lnk_file { read getattr lock ioctl }; allow kernel_t default_t:sock_file { read getattr lock ioctl }; allow kernel_t default_t:fifo_file { read getattr lock ioctl }; } allow unlabeled_t self:filesystem associate; range_transition getty_t login_exec_t s0 - s0:c0.c255; range_transition init_t xdm_exec_t s0 - s0:c0.c255; range_transition initrc_t crond_exec_t s0 - s0:c0.c255; range_transition initrc_t cupsd_exec_t s0 - s0:c0.c255; range_transition initrc_t sshd_exec_t s0 - s0:c0.c255; range_transition initrc_t udev_exec_t s0 - s0:c0.c255; range_transition initrc_t xdm_exec_t s0 - s0:c0.c255; range_transition kernel_t udev_exec_t s0 - s0:c0.c255; range_transition unconfined_t su_exec_t s0 - s0:c0.c255; range_transition unconfined_t initrc_exec_t s0; typeattribute security_t filesystem_type; allow security_t self:filesystem associate; typeattribute security_t mlstrustedobject; neverallow ~can_load_policy security_t:security load_policy; neverallow ~can_setenforce security_t:security setenforce; neverallow ~can_setsecparam security_t:security setsecparam; typeattribute bsdpty_device_t device_node; allow bsdpty_device_t fs_t:filesystem associate; allow bsdpty_device_t tmpfs_t:filesystem associate; allow bsdpty_device_t tmp_t:filesystem associate; typeattribute console_device_t device_node; allow console_device_t fs_t:filesystem associate; allow console_device_t tmpfs_t:filesystem associate; allow console_device_t tmp_t:filesystem associate; allow devpts_t fs_t:filesystem associate; allow devpts_t noxattrfs:filesystem associate; typeattribute devpts_t file_type; typeattribute devpts_t mountpoint; allow devpts_t tmpfs_t:filesystem associate; allow devpts_t tmp_t:filesystem associate; typeattribute devpts_t filesystem_type; allow devpts_t self:filesystem associate; typeattribute devpts_t ttynode, ptynode; typeattribute devtty_t device_node; allow devtty_t fs_t:filesystem associate; allow devtty_t tmpfs_t:filesystem associate; allow devtty_t tmp_t:filesystem associate; typeattribute devtty_t mlstrustedobject; typeattribute ptmx_t device_node; allow ptmx_t fs_t:filesystem associate; allow ptmx_t tmpfs_t:filesystem associate; allow ptmx_t tmp_t:filesystem associate; typeattribute ptmx_t mlstrustedobject; typeattribute tty_device_t device_node; allow tty_device_t fs_t:filesystem associate; allow tty_device_t tmpfs_t:filesystem associate; allow tty_device_t tmp_t:filesystem associate; typeattribute tty_device_t ttynode; typeattribute usbtty_device_t device_node; allow usbtty_device_t fs_t:filesystem associate; allow usbtty_device_t tmpfs_t:filesystem associate; allow usbtty_device_t tmp_t:filesystem associate; user system_u roles { system_r } level s0 range s0 - s0:c0.c255; user user_u roles { user_r sysadm_r system_r } level s0 range s0 - s0:c0.c255; user root roles { user_r sysadm_r system_r } level s0 range s0 - s0:c0.c255; constrain process transition ( u1 == u2 or t1 == can_change_process_identity ); constrain process transition ( r1 == r2 or t1 == can_change_process_role ); constrain process dyntransition ( u1 == u2 and r1 == r2 ); constrain { dir file lnk_file sock_file fifo_file chr_file blk_file } { create relabelto relabelfrom } ( u1 == u2 or t1 == can_change_object_identity ); constrain { tcp_socket udp_socket rawip_socket netlink_socket packet_socket unix_stream_socket unix_dgram_socket netlink_route_socket netlink_firewall_socket netlink_tcpdiag_socket netlink_nflog_socket netlink_xfrm_socket netlink_selinux_socket netlink_audit_socket netlink_ip6fw_socket netlink_dnrt_socket netlink_kobject_uevent_socket } { create relabelto relabelfrom } ( u1 == u2 or t1 == can_change_object_identity ); sid port system_u:object_r:port_t:s0 sid node system_u:object_r:node_t:s0 sid netif system_u:object_r:netif_t:s0 sid devnull system_u:object_r:null_device_t:s0 sid file system_u:object_r:file_t:s0 sid fs system_u:object_r:fs_t:s0 sid kernel system_u:system_r:kernel_t:s0 sid sysctl system_u:object_r:sysctl_t:s0 sid unlabeled system_u:object_r:unlabeled_t:s0 sid any_socket system_u:object_r:unlabeled_t:s0 sid file_labels system_u:object_r:unlabeled_t:s0 sid icmp_socket system_u:object_r:unlabeled_t:s0 sid igmp_packet system_u:object_r:unlabeled_t:s0 sid init system_u:object_r:unlabeled_t:s0 sid kmod system_u:object_r:unlabeled_t:s0 sid netmsg system_u:object_r:unlabeled_t:s0 sid policy system_u:object_r:unlabeled_t:s0 sid scmp_packet system_u:object_r:unlabeled_t:s0 sid sysctl_modprobe system_u:object_r:unlabeled_t:s0 sid sysctl_fs system_u:object_r:unlabeled_t:s0 sid sysctl_kernel system_u:object_r:unlabeled_t:s0 sid sysctl_net system_u:object_r:unlabeled_t:s0 sid sysctl_net_unix system_u:object_r:unlabeled_t:s0 sid sysctl_vm system_u:object_r:unlabeled_t:s0 sid sysctl_dev system_u:object_r:unlabeled_t:s0 sid tcp_socket system_u:object_r:unlabeled_t:s0 sid security system_u:object_r:security_t:s0 fs_use_xattr ext2 system_u:object_r:fs_t:s0; fs_use_xattr ext3 system_u:object_r:fs_t:s0; fs_use_xattr gfs system_u:object_r:fs_t:s0; fs_use_xattr jfs system_u:object_r:fs_t:s0; fs_use_xattr reiserfs system_u:object_r:fs_t:s0; fs_use_xattr xfs system_u:object_r:fs_t:s0; fs_use_task pipefs system_u:object_r:fs_t:s0; fs_use_task sockfs system_u:object_r:fs_t:s0; fs_use_trans mqueue system_u:object_r:tmpfs_t:s0; fs_use_trans shm system_u:object_r:tmpfs_t:s0; fs_use_trans tmpfs system_u:object_r:tmpfs_t:s0; fs_use_trans devpts system_u:object_r:devpts_t:s0; genfscon proc /mtrr system_u:object_r:mtrr_device_t:s0 genfscon sysfs / system_u:object_r:sysfs_t:s0 genfscon usbfs / system_u:object_r:usbfs_t:s0 genfscon usbdevfs / system_u:object_r:usbfs_t:s0 genfscon rootfs / system_u:object_r:root_t:s0 genfscon bdev / system_u:object_r:bdev_t:s0 genfscon binfmt_misc / system_u:object_r:binfmt_misc_fs_t:s0 genfscon capifs / system_u:object_r:capifs_t:s0 genfscon configfs / system_u:object_r:configfs_t:s0 genfscon eventpollfs / system_u:object_r:eventpollfs_t:s0 genfscon futexfs / system_u:object_r:futexfs_t:s0 genfscon hugetlbfs / system_u:object_r:hugetlbfs_t:s0 genfscon inotifyfs / system_u:object_r:inotifyfs_t:s0 genfscon nfsd / system_u:object_r:nfsd_fs_t:s0 genfscon ramfs / system_u:object_r:ramfs_t:s0 genfscon romfs / system_u:object_r:romfs_t:s0 genfscon cramfs / system_u:object_r:romfs_t:s0 genfscon rpc_pipefs / system_u:object_r:rpc_pipefs_t:s0 genfscon autofs / system_u:object_r:autofs_t:s0 genfscon automount / system_u:object_r:autofs_t:s0 genfscon cifs / system_u:object_r:cifs_t:s0 genfscon smbfs / system_u:object_r:cifs_t:s0 genfscon fat / system_u:object_r:dosfs_t:s0 genfscon msdos / system_u:object_r:dosfs_t:s0 genfscon ntfs / system_u:object_r:dosfs_t:s0 genfscon vfat / system_u:object_r:dosfs_t:s0 genfscon iso9660 / system_u:object_r:iso9660_t:s0 genfscon udf / system_u:object_r:iso9660_t:s0 genfscon nfs / system_u:object_r:nfs_t:s0 genfscon nfs4 / system_u:object_r:nfs_t:s0 genfscon afs / system_u:object_r:nfs_t:s0 genfscon hfsplus / system_u:object_r:nfs_t:s0 genfscon debugfs / system_u:object_r:debugfs_t:s0 genfscon proc / system_u:object_r:proc_t:s0 genfscon proc /sysvipc system_u:object_r:proc_t:s0 genfscon proc /kmsg system_u:object_r:proc_kmsg_t:s0 genfscon proc /kcore system_u:object_r:proc_kcore_t:s0 genfscon proc /mdstat system_u:object_r:proc_mdstat_t:s0 genfscon proc /net system_u:object_r:proc_net_t:s0 genfscon proc /xen system_u:object_r:proc_xen_t:s0 genfscon proc /sys system_u:object_r:sysctl_t:s0 genfscon proc /irq system_u:object_r:sysctl_irq_t:s0 genfscon proc /net/rpc system_u:object_r:sysctl_rpc_t:s0 genfscon proc /sys/fs system_u:object_r:sysctl_fs_t:s0 genfscon proc /sys/kernel system_u:object_r:sysctl_kernel_t:s0 genfscon proc /sys/kernel/modprobe system_u:object_r:sysctl_modprobe_t:s0 genfscon proc /sys/kernel/hotplug system_u:object_r:sysctl_hotplug_t:s0 genfscon proc /sys/net system_u:object_r:sysctl_net_t:s0 genfscon proc /sys/net/unix system_u:object_r:sysctl_net_unix_t:s0 genfscon proc /sys/vm system_u:object_r:sysctl_vm_t:s0 genfscon proc /sys/dev system_u:object_r:sysctl_dev_t:s0 genfscon selinuxfs / system_u:object_r:security_t:s0 portcon udp 7007 system_u:object_r:afs_bos_port_t:s0 portcon tcp 2040 system_u:object_r:afs_fs_port_t:s0 portcon udp 7000 system_u:object_r:afs_fs_port_t:s0 portcon udp 7005 system_u:object_r:afs_fs_port_t:s0 portcon udp 7004 system_u:object_r:afs_ka_port_t:s0 portcon udp 7002 system_u:object_r:afs_pt_port_t:s0 portcon udp 7003 system_u:object_r:afs_vl_port_t:s0 portcon udp 10080 system_u:object_r:amanda_port_t:s0 portcon tcp 10080 system_u:object_r:amanda_port_t:s0 portcon udp 10081 system_u:object_r:amanda_port_t:s0 portcon tcp 10081 system_u:object_r:amanda_port_t:s0 portcon tcp 10082 system_u:object_r:amanda_port_t:s0 portcon tcp 10083 system_u:object_r:amanda_port_t:s0 portcon tcp 10024 system_u:object_r:amavisd_recv_port_t:s0 portcon tcp 10025 system_u:object_r:amavisd_send_port_t:s0 portcon tcp 1720 system_u:object_r:asterisk_port_t:s0 portcon udp 2427 system_u:object_r:asterisk_port_t:s0 portcon udp 2727 system_u:object_r:asterisk_port_t:s0 portcon udp 4569 system_u:object_r:asterisk_port_t:s0 portcon udp 5060 system_u:object_r:asterisk_port_t:s0 portcon tcp 113 system_u:object_r:auth_port_t:s0 portcon tcp 179 system_u:object_r:bgp_port_t:s0 portcon udp 179 system_u:object_r:bgp_port_t:s0 portcon tcp 3310 system_u:object_r:clamd_port_t:s0 portcon udp 4041 system_u:object_r:clockspeed_port_t:s0 portcon udp 512 system_u:object_r:comsat_port_t:s0 portcon tcp 2401 system_u:object_r:cvs_port_t:s0 portcon udp 2401 system_u:object_r:cvs_port_t:s0 portcon udp 6276 system_u:object_r:dcc_port_t:s0 portcon udp 6277 system_u:object_r:dcc_port_t:s0 portcon tcp 1178 system_u:object_r:dbskkd_port_t:s0 portcon udp 68 system_u:object_r:dhcpc_port_t:s0 portcon udp 67 system_u:object_r:dhcpd_port_t:s0 portcon tcp 647 system_u:object_r:dhcpd_port_t:s0 portcon udp 647 system_u:object_r:dhcpd_port_t:s0 portcon tcp 847 system_u:object_r:dhcpd_port_t:s0 portcon udp 847 system_u:object_r:dhcpd_port_t:s0 portcon tcp 2628 system_u:object_r:dict_port_t:s0 portcon tcp 3632 system_u:object_r:distccd_port_t:s0 portcon udp 53 system_u:object_r:dns_port_t:s0 portcon tcp 53 system_u:object_r:dns_port_t:s0 portcon tcp 79 system_u:object_r:fingerd_port_t:s0 portcon tcp 20 system_u:object_r:ftp_data_port_t:s0 portcon tcp 21 system_u:object_r:ftp_port_t:s0 portcon udp 1718 system_u:object_r:gatekeeper_port_t:s0 portcon udp 1719 system_u:object_r:gatekeeper_port_t:s0 portcon tcp 1721 system_u:object_r:gatekeeper_port_t:s0 portcon tcp 7000 system_u:object_r:gatekeeper_port_t:s0 portcon tcp 1213 system_u:object_r:giftd_port_t:s0 portcon tcp 70 system_u:object_r:gopher_port_t:s0 portcon udp 70 system_u:object_r:gopher_port_t:s0 portcon tcp 3128 system_u:object_r:http_cache_port_t:s0 portcon udp 3130 system_u:object_r:http_cache_port_t:s0 portcon tcp 8080 system_u:object_r:http_cache_port_t:s0 portcon tcp 8118 system_u:object_r:http_cache_port_t:s0 portcon tcp 80 system_u:object_r:http_port_t:s0 portcon tcp 443 system_u:object_r:http_port_t:s0 portcon tcp 488 system_u:object_r:http_port_t:s0 portcon tcp 8008 system_u:object_r:http_port_t:s0 portcon tcp 9050 system_u:object_r:http_port_t:s0 portcon tcp 5335 system_u:object_r:howl_port_t:s0 portcon udp 5353 system_u:object_r:howl_port_t:s0 portcon tcp 50000 system_u:object_r:hplip_port_t:s0 portcon tcp 50002 system_u:object_r:hplip_port_t:s0 portcon tcp 9010 system_u:object_r:i18n_input_port_t:s0 portcon tcp 5323 system_u:object_r:imaze_port_t:s0 portcon udp 5323 system_u:object_r:imaze_port_t:s0 portcon tcp 7 system_u:object_r:inetd_child_port_t:s0 portcon udp 7 system_u:object_r:inetd_child_port_t:s0 portcon tcp 9 system_u:object_r:inetd_child_port_t:s0 portcon udp 9 system_u:object_r:inetd_child_port_t:s0 portcon tcp 13 system_u:object_r:inetd_child_port_t:s0 portcon udp 13 system_u:object_r:inetd_child_port_t:s0 portcon tcp 19 system_u:object_r:inetd_child_port_t:s0 portcon udp 19 system_u:object_r:inetd_child_port_t:s0 portcon tcp 37 system_u:object_r:inetd_child_port_t:s0 portcon udp 37 system_u:object_r:inetd_child_port_t:s0 portcon tcp 512 system_u:object_r:inetd_child_port_t:s0 portcon tcp 543 system_u:object_r:inetd_child_port_t:s0 portcon tcp 544 system_u:object_r:inetd_child_port_t:s0 portcon tcp 891 system_u:object_r:inetd_child_port_t:s0 portcon udp 891 system_u:object_r:inetd_child_port_t:s0 portcon tcp 892 system_u:object_r:inetd_child_port_t:s0 portcon udp 892 system_u:object_r:inetd_child_port_t:s0 portcon tcp 2105 system_u:object_r:inetd_child_port_t:s0 portcon tcp 5666 system_u:object_r:inetd_child_port_t:s0 portcon tcp 119 system_u:object_r:innd_port_t:s0 portcon tcp 631 system_u:object_r:ipp_port_t:s0 portcon udp 631 system_u:object_r:ipp_port_t:s0 portcon tcp 6667 system_u:object_r:ircd_port_t:s0 portcon udp 500 system_u:object_r:isakmp_port_t:s0 portcon tcp 5222 system_u:object_r:jabber_client_port_t:s0 portcon tcp 5223 system_u:object_r:jabber_client_port_t:s0 portcon tcp 5269 system_u:object_r:jabber_interserver_port_t:s0 portcon tcp 464 system_u:object_r:kerberos_admin_port_t:s0 portcon udp 464 system_u:object_r:kerberos_admin_port_t:s0 portcon tcp 749 system_u:object_r:kerberos_admin_port_t:s0 portcon tcp 4444 system_u:object_r:kerberos_master_port_t:s0 portcon udp 4444 system_u:object_r:kerberos_master_port_t:s0 portcon tcp 88 system_u:object_r:kerberos_port_t:s0 portcon udp 88 system_u:object_r:kerberos_port_t:s0 portcon tcp 750 system_u:object_r:kerberos_port_t:s0 portcon udp 750 system_u:object_r:kerberos_port_t:s0 portcon udp 517 system_u:object_r:ktalkd_port_t:s0 portcon udp 518 system_u:object_r:ktalkd_port_t:s0 portcon tcp 389 system_u:object_r:ldap_port_t:s0 portcon udp 389 system_u:object_r:ldap_port_t:s0 portcon tcp 636 system_u:object_r:ldap_port_t:s0 portcon udp 636 system_u:object_r:ldap_port_t:s0 portcon tcp 2000 system_u:object_r:mail_port_t:s0 portcon tcp 1234 system_u:object_r:monopd_port_t:s0 portcon tcp 3306 system_u:object_r:mysqld_port_t:s0 portcon tcp 1241 system_u:object_r:nessus_port_t:s0 portcon udp 137 system_u:object_r:nmbd_port_t:s0 portcon udp 138 system_u:object_r:nmbd_port_t:s0 portcon udp 139 system_u:object_r:nmbd_port_t:s0 portcon udp 123 system_u:object_r:ntp_port_t:s0 portcon udp 5000 system_u:object_r:openvpn_port_t:s0 portcon tcp 5988 system_u:object_r:pegasus_http_port_t:s0 portcon tcp 5989 system_u:object_r:pegasus_https_port_t:s0 portcon tcp 106 system_u:object_r:pop_port_t:s0 portcon tcp 109 system_u:object_r:pop_port_t:s0 portcon tcp 110 system_u:object_r:pop_port_t:s0 portcon tcp 143 system_u:object_r:pop_port_t:s0 portcon tcp 220 system_u:object_r:pop_port_t:s0 portcon tcp 993 system_u:object_r:pop_port_t:s0 portcon tcp 995 system_u:object_r:pop_port_t:s0 portcon tcp 1109 system_u:object_r:pop_port_t:s0 portcon udp 111 system_u:object_r:portmap_port_t:s0 portcon tcp 111 system_u:object_r:portmap_port_t:s0 portcon tcp 5432 system_u:object_r:postgresql_port_t:s0 portcon tcp 60000 system_u:object_r:postgrey_port_t:s0 portcon tcp 515 system_u:object_r:printer_port_t:s0 portcon tcp 5703 system_u:object_r:ptal_port_t:s0 portcon udp 4011 system_u:object_r:pxe_port_t:s0 portcon udp 24441 system_u:object_r:pyzor_port_t:s0 portcon udp 1646 system_u:object_r:radacct_port_t:s0 portcon udp 1813 system_u:object_r:radacct_port_t:s0 portcon udp 1645 system_u:object_r:radius_port_t:s0 portcon udp 1812 system_u:object_r:radius_port_t:s0 portcon tcp 2703 system_u:object_r:razor_port_t:s0 portcon tcp 513 system_u:object_r:rlogind_port_t:s0 portcon tcp 953 system_u:object_r:rndc_port_t:s0 portcon udp 520 system_u:object_r:router_port_t:s0 portcon tcp 514 system_u:object_r:rsh_port_t:s0 portcon tcp 873 system_u:object_r:rsync_port_t:s0 portcon udp 873 system_u:object_r:rsync_port_t:s0 portcon tcp 137-139 system_u:object_r:smbd_port_t:s0 portcon tcp 445 system_u:object_r:smbd_port_t:s0 portcon tcp 25 system_u:object_r:smtp_port_t:s0 portcon tcp 465 system_u:object_r:smtp_port_t:s0 portcon tcp 587 system_u:object_r:smtp_port_t:s0 portcon udp 161 system_u:object_r:snmp_port_t:s0 portcon udp 162 system_u:object_r:snmp_port_t:s0 portcon tcp 199 system_u:object_r:snmp_port_t:s0 portcon tcp 783 system_u:object_r:spamd_port_t:s0 portcon tcp 22 system_u:object_r:ssh_port_t:s0 portcon tcp 8000 system_u:object_r:soundd_port_t:s0 portcon tcp 9433 system_u:object_r:soundd_port_t:s0 portcon tcp 901 system_u:object_r:swat_port_t:s0 portcon udp 514 system_u:object_r:syslogd_port_t:s0 portcon tcp 23 system_u:object_r:telnetd_port_t:s0 portcon udp 69 system_u:object_r:tftp_port_t:s0 portcon tcp 8081 system_u:object_r:transproxy_port_t:s0 portcon tcp 540 system_u:object_r:uucpd_port_t:s0 portcon tcp 5900 system_u:object_r:vnc_port_t:s0 portcon tcp 6001 system_u:object_r:xserver_port_t:s0 portcon tcp 6002 system_u:object_r:xserver_port_t:s0 portcon tcp 6003 system_u:object_r:xserver_port_t:s0 portcon tcp 6004 system_u:object_r:xserver_port_t:s0 portcon tcp 6005 system_u:object_r:xserver_port_t:s0 portcon tcp 6006 system_u:object_r:xserver_port_t:s0 portcon tcp 6007 system_u:object_r:xserver_port_t:s0 portcon tcp 6008 system_u:object_r:xserver_port_t:s0 portcon tcp 6009 system_u:object_r:xserver_port_t:s0 portcon tcp 6010 system_u:object_r:xserver_port_t:s0 portcon tcp 6011 system_u:object_r:xserver_port_t:s0 portcon tcp 6012 system_u:object_r:xserver_port_t:s0 portcon tcp 6013 system_u:object_r:xserver_port_t:s0 portcon tcp 6014 system_u:object_r:xserver_port_t:s0 portcon tcp 6015 system_u:object_r:xserver_port_t:s0 portcon tcp 6016 system_u:object_r:xserver_port_t:s0 portcon tcp 6017 system_u:object_r:xserver_port_t:s0 portcon tcp 6018 system_u:object_r:xserver_port_t:s0 portcon tcp 6019 system_u:object_r:xserver_port_t:s0 portcon tcp 8002 system_u:object_r:xen_port_t:s0 portcon tcp 2601 system_u:object_r:zebra_port_t:s0 portcon tcp 8021 system_u:object_r:zope_port_t:s0 portcon tcp 1-1023 system_u:object_r:reserved_port_t:s0 portcon udp 1-1023 system_u:object_r:reserved_port_t:s0 nodecon :: ffff:ffff:ffff:ffff:ffff:ffff:: system_u:object_r:compat_ipv4_node_t:s0 nodecon 0.0.0.0 255.255.255.255 system_u:object_r:inaddr_any_node_t:s0 nodecon fe80:: ffff:ffff:ffff:ffff:: system_u:object_r:link_local_node_t:s0 nodecon 127.0.0.1 255.255.255.255 system_u:object_r:lo_node_t:s0 nodecon ::ffff:0000:0000 ffff:ffff:ffff:ffff:ffff:ffff:: system_u:object_r:mapped_ipv4_node_t:s0 nodecon ff00:: ff00:: system_u:object_r:multicast_node_t:s0 nodecon fec0:: ffc0:: system_u:object_r:site_local_node_t:s0 nodecon :: ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff system_u:object_r:unspec_node_t:s0 libsepol-3.8.1/tests/policies/test-deps/000077500000000000000000000000001476211737200202275ustar00rootroot00000000000000libsepol-3.8.1/tests/policies/test-deps/base-metreq.conf000066400000000000000000000164661476211737200233200ustar00rootroot00000000000000# FLASK # # Define the security object classes # class security class process class system class capability # file-related classes class filesystem class file class dir class fd class lnk_file class chr_file class blk_file class sock_file class fifo_file # network-related classes class socket class tcp_socket class udp_socket class rawip_socket class node class netif class netlink_socket class packet_socket class key_socket class unix_stream_socket class unix_dgram_socket # sysv-ipc-related classes class sem class msg class msgq class shm class ipc # FLASK # FLASK # # Define initial security identifiers # sid kernel # FLASK # # Define common prefixes for access vectors # # common common_name { permission_name ... } # # Define a common prefix for file access vectors. # common file { ioctl read write create getattr setattr lock relabelfrom relabelto append unlink link rename execute swapon quotaon mounton } # # Define a common prefix for socket access vectors. # common socket { # inherited from file ioctl read write create getattr setattr lock relabelfrom relabelto append # socket-specific bind connect listen accept getopt setopt shutdown recvfrom sendto recv_msg send_msg name_bind } # # Define a common prefix for ipc access vectors. # common ipc { create destroy getattr setattr read write associate unix_read unix_write } # # Define the access vectors. # # class class_name [ inherits common_name ] { permission_name ... } # # Define the access vector interpretation for file-related objects. # class filesystem { mount remount unmount getattr relabelfrom relabelto transition associate quotamod quotaget } class dir inherits file { add_name remove_name reparent search rmdir } class file inherits file { execute_no_trans entrypoint } class lnk_file inherits file class chr_file inherits file class blk_file inherits file class sock_file inherits file class fifo_file inherits file class fd { use } # # Define the access vector interpretation for network-related objects. # class socket inherits socket class tcp_socket inherits socket { connectto newconn acceptfrom } class udp_socket inherits socket class rawip_socket inherits socket class node { tcp_recv tcp_send udp_recv udp_send rawip_recv rawip_send enforce_dest } class netif { tcp_recv tcp_send udp_recv udp_send rawip_recv rawip_send } class netlink_socket inherits socket class packet_socket inherits socket class key_socket inherits socket class unix_stream_socket inherits socket { connectto newconn acceptfrom } class unix_dgram_socket inherits socket # # Define the access vector interpretation for process-related objects # class process { fork transition sigchld # commonly granted from child to parent sigkill # cannot be caught or ignored sigstop # cannot be caught or ignored signull # for kill(pid, 0) signal # all other signals ptrace getsched setsched getsession getpgid setpgid getcap setcap share } # # Define the access vector interpretation for ipc-related objects # class ipc inherits ipc class sem inherits ipc class msgq inherits ipc { enqueue } class msg { send receive } class shm inherits ipc { lock } # # Define the access vector interpretation for the security server. # class security { compute_av transition_sid member_sid sid_to_context context_to_sid load_policy get_sids change_sid get_user_sids } # # Define the access vector interpretation for system operations. # class system { ipc_info avc_toggle nfsd_control bdflush syslog_read syslog_mod syslog_console ichsid } # # Define the access vector interpretation for controlling capabilities # class capability { # The capabilities are defined in include/linux/capability.h # Care should be taken to ensure that these are consistent with # those definitions. (Order matters) chown dac_override dac_read_search fowner fsetid kill setgid setuid setpcap linux_immutable net_bind_service net_broadcast net_admin net_raw ipc_lock ipc_owner sys_module sys_rawio sys_chroot sys_ptrace sys_pacct sys_admin sys_boot sys_nice sys_resource sys_time sys_tty_config mknod lease } ifdef(`enable_mls',` sensitivity s0; # # Define the ordering of the sensitivity levels (least to greatest) # dominance { s0 } # # Define the categories # # Each category has a name and zero or more aliases. # category c0; category c1; category c2; category c3; category c4; category c5; category c6; category c7; category c8; category c9; category c10; category c11; category c12; category c13; category c14; category c15; category c16; category c17; category c18; category c19; category c20; category c21; category c22; category c23; level s0:c0.c23; mlsconstrain file { write setattr append unlink link rename ioctl lock execute relabelfrom } ( h1 dom h2 ); ') #################################### #################################### ##################################### # TE RULES attribute domain; attribute system; attribute foo; attribute num; attribute num_exec; attribute files; type net_foo_t, foo; type sys_foo_t, foo, system; role system_r; role system_r types sys_foo_t; type user_t, domain; role user_r; role user_r types user_t; type sysadm_t, domain, system; role sysadm_r; role sysadm_r types sysadm_t; type system_t, domain, system, foo; role system_r; role system_r types { system_t sys_foo_t }; type file_t; type file_exec_t, files; type fs_t; # Make this decl easy to find type base_global_decl_t; # Actually used in module tests type type_req_t; attribute attr_req; bool bool_req false; role role_req_r; allow sysadm_t file_exec_t: file { execute read write ioctl lock entrypoint }; optional { require { type base_optional_1, base_optional_2; } allow base_optional_1 base_optional_2 : file { read write }; } ##################################### # Role Allow allow user_r sysadm_r; #################################### # Booleans bool allow_ypbind true; bool secure_mode false; bool allow_execheap false; bool allow_execmem true; bool allow_execmod false; bool allow_execstack true; bool optional_bool_1 true; bool optional_bool_2 false; ##################################### # users gen_user(system_u,, system_r, s0, s0 - s0:c0.c23) gen_user(root,, user_r sysadm_r, s0, s0 - s0:c0.c23) gen_user(joe,, user_r, s0, s0 - s0:c0.c23) ##################################### # constraints #################################### #line 1 "initial_sid_contexts" sid kernel gen_context(system_u:system_r:sys_foo_t, s0) ############################################ #line 1 "fs_use" # fs_use_xattr ext2 gen_context(system_u:object_r:fs_t, s0); fs_use_xattr ext3 gen_context(system_u:object_r:fs_t, s0); fs_use_xattr reiserfs gen_context(system_u:object_r:fs_t, s0); genfscon proc / gen_context(system_u:object_r:sys_foo_t, s0) #################################### #line 1 "net_contexts" #portcon tcp 21 system_u:object_r:net_foo_t:s0 #netifcon lo system_u:object_r:net_foo_t system_u:object_r:net_foo_t:s0 # #nodecon 127.0.0.1 255.255.255.255 system_u:object_r:net_foo_t:s0 nodecon ::1 FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF gen_context(system_u:object_r:net_foo_t, s0) libsepol-3.8.1/tests/policies/test-deps/base-notmetreq.conf000066400000000000000000000162221476211737200240270ustar00rootroot00000000000000# FLASK # # Define the security object classes # class security class process class system class capability # file-related classes class filesystem class file class dir class fd class lnk_file class chr_file class blk_file class sock_file class fifo_file # network-related classes class socket class tcp_socket class udp_socket class rawip_socket class node class netif class netlink_socket class packet_socket class key_socket class unix_stream_socket class unix_dgram_socket # sysv-ipc-related classes class msg class msgq class shm class ipc # FLASK # FLASK # # Define initial security identifiers # sid kernel # FLASK # # Define common prefixes for access vectors # # common common_name { permission_name ... } # # Define a common prefix for file access vectors. # common file { ioctl read write create getattr setattr lock relabelfrom relabelto append unlink link rename execute swapon quotaon mounton } # # Define a common prefix for socket access vectors. # common socket { # inherited from file ioctl read write create getattr setattr lock relabelfrom relabelto append # socket-specific bind connect listen accept getopt setopt shutdown recvfrom sendto recv_msg send_msg name_bind } # # Define a common prefix for ipc access vectors. # common ipc { create destroy getattr setattr read write associate unix_read unix_write } # # Define the access vectors. # # class class_name [ inherits common_name ] { permission_name ... } # # Define the access vector interpretation for file-related objects. # class filesystem { mount remount unmount getattr relabelfrom relabelto transition associate quotamod quotaget } class dir inherits file { add_name remove_name reparent search rmdir } class file inherits file { execute_no_trans entrypoint } class lnk_file inherits file class chr_file inherits file class blk_file inherits file class sock_file inherits file class fifo_file inherits file class fd { use } # # Define the access vector interpretation for network-related objects. # class socket inherits socket class tcp_socket inherits socket { connectto newconn acceptfrom } class udp_socket inherits socket class rawip_socket inherits socket class node { tcp_recv tcp_send udp_recv udp_send rawip_recv rawip_send enforce_dest } class netif { tcp_recv tcp_send udp_recv udp_send rawip_recv rawip_send } class netlink_socket inherits socket class packet_socket inherits socket class key_socket inherits socket class unix_stream_socket inherits socket { connectto newconn acceptfrom } class unix_dgram_socket inherits socket # # Define the access vector interpretation for process-related objects # class process { fork transition sigchld # commonly granted from child to parent sigkill # cannot be caught or ignored sigstop # cannot be caught or ignored signull # for kill(pid, 0) signal # all other signals ptrace getsched setsched getsession getpgid setpgid getcap setcap share } # # Define the access vector interpretation for ipc-related objects # class ipc inherits ipc class msgq inherits ipc { enqueue } class msg { send } class shm inherits ipc { lock } # # Define the access vector interpretation for the security server. # class security { compute_av transition_sid member_sid sid_to_context context_to_sid load_policy get_sids change_sid get_user_sids } # # Define the access vector interpretation for system operations. # class system { ipc_info avc_toggle nfsd_control bdflush syslog_read syslog_mod syslog_console ichsid } # # Define the access vector interpretation for controlling capabilities # class capability { # The capabilities are defined in include/linux/capability.h # Care should be taken to ensure that these are consistent with # those definitions. (Order matters) chown dac_override dac_read_search fowner fsetid kill setgid setuid setpcap linux_immutable net_bind_service net_broadcast net_admin net_raw ipc_lock ipc_owner sys_module sys_rawio sys_chroot sys_ptrace sys_pacct sys_admin sys_boot sys_nice sys_resource sys_time sys_tty_config mknod lease } ifdef(`enable_mls',` sensitivity s0; # # Define the ordering of the sensitivity levels (least to greatest) # dominance { s0 } # # Define the categories # # Each category has a name and zero or more aliases. # category c0; category c1; category c2; category c3; category c4; category c5; category c6; category c7; category c8; category c9; category c10; category c11; category c12; category c13; category c14; category c15; category c16; category c17; category c18; category c19; category c20; category c21; category c22; category c23; level s0:c0.c23; mlsconstrain file { write setattr append unlink link rename ioctl lock execute relabelfrom } ( h1 dom h2 ); ') #################################### #################################### ##################################### # TE RULES attribute domain; attribute system; attribute foo; attribute num; attribute num_exec; attribute files; type net_foo_t, foo; type sys_foo_t, foo, system; role system_r; role system_r types sys_foo_t; type user_t, domain; role user_r; role user_r types user_t; type sysadm_t, domain, system; role sysadm_r; role sysadm_r types sysadm_t; type system_t, domain, system, foo; role system_r; role system_r types { system_t sys_foo_t }; type file_t; type file_exec_t, files; type fs_t; type base_optional_1; type base_optional_2; allow sysadm_t file_exec_t: file { execute read write ioctl lock entrypoint }; optional { require { type base_optional_1, base_optional_2; } allow base_optional_1 base_optional_2 : file { read write }; } ##################################### # Role Allow allow user_r sysadm_r; #################################### # Booleans bool allow_ypbind true; bool secure_mode false; bool allow_execheap false; bool allow_execmem true; bool allow_execmod false; bool allow_execstack true; bool optional_bool_1 true; bool optional_bool_2 false; ##################################### # users gen_user(system_u,, system_r, s0, s0 - s0:c0.c23) gen_user(root,, user_r sysadm_r, s0, s0 - s0:c0.c23) gen_user(joe,, user_r, s0, s0 - s0:c0.c23) ##################################### # constraints #################################### #line 1 "initial_sid_contexts" sid kernel gen_context(system_u:system_r:sys_foo_t, s0) ############################################ #line 1 "fs_use" # fs_use_xattr ext2 gen_context(system_u:object_r:fs_t, s0); fs_use_xattr ext3 gen_context(system_u:object_r:fs_t, s0); fs_use_xattr reiserfs gen_context(system_u:object_r:fs_t, s0); genfscon proc / gen_context(system_u:object_r:sys_foo_t, s0) #################################### #line 1 "net_contexts" #portcon tcp 21 system_u:object_r:net_foo_t:s0 #netifcon lo system_u:object_r:net_foo_t system_u:object_r:net_foo_t:s0 # #nodecon 127.0.0.1 255.255.255.255 system_u:object_r:net_foo_t:s0 nodecon ::1 FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF gen_context(system_u:object_r:net_foo_t, s0) libsepol-3.8.1/tests/policies/test-deps/modreq-attr-global.conf000066400000000000000000000001561476211737200245750ustar00rootroot00000000000000module modreq_attr_global 1.0; require { attribute attr_req; } type mod_global_t; type new_t, attr_req; libsepol-3.8.1/tests/policies/test-deps/modreq-attr-opt.conf000066400000000000000000000002641476211737200241370ustar00rootroot00000000000000module modreq_attr_opt 1.0; require { class file {read write}; } type mod_global_t; optional { require { attribute attr_req; } type mod_opt_t; type new_t, attr_req; } libsepol-3.8.1/tests/policies/test-deps/modreq-bool-global.conf000066400000000000000000000002731476211737200245560ustar00rootroot00000000000000module modreq_bool_global 1.0; require { bool bool_req; class file { read write }; } type mod_global_t; type a_t; type b_t; if (bool_req) { allow a_t b_t : file { read write }; } libsepol-3.8.1/tests/policies/test-deps/modreq-bool-opt.conf000066400000000000000000000003541476211737200241200ustar00rootroot00000000000000module modreq_bool_opt 1.0; require { class file {read write}; } type mod_global_t; optional { require { bool bool_req; } type a_t; type b_t; type mod_opt_t; if (bool_req) { allow a_t b_t : file { read write }; } } libsepol-3.8.1/tests/policies/test-deps/modreq-obj-global.conf000066400000000000000000000002661476211737200243770ustar00rootroot00000000000000module modreq_obj_global 1.0; require { class sem { create destroy }; } type mod_global_t; type mod_foo_t; type mod_bar_t; allow mod_foo_t mod_bar_t : sem { create destroy }; libsepol-3.8.1/tests/policies/test-deps/modreq-obj-opt.conf000066400000000000000000000003741476211737200237410ustar00rootroot00000000000000module modreq_obj_global 1.0; require { class file { read }; } type mod_global_t; type mod_foo_t; type mod_bar_t; optional { require { class sem { create destroy }; } type mod_opt_t; allow mod_foo_t mod_bar_t : sem { create destroy }; } libsepol-3.8.1/tests/policies/test-deps/modreq-perm-global.conf000066400000000000000000000002271476211737200245650ustar00rootroot00000000000000module modreq_perm_global 1.0; require { class msg { send receive }; } type mod_global_t; type a_t; type b_t; allow a_t b_t: msg { send receive }; libsepol-3.8.1/tests/policies/test-deps/modreq-perm-opt.conf000066400000000000000000000003621476211737200241270ustar00rootroot00000000000000module modreq_perm_opt 1.0; require { class file { read write }; } type mod_global_t; optional { require { class msg { send receive }; } type mod_opt_t; type a_mod_t; type b_mod_t; allow a_mod_t b_mod_t: msg { send receive }; } libsepol-3.8.1/tests/policies/test-deps/modreq-role-global.conf000066400000000000000000000002361476211737200245630ustar00rootroot00000000000000module modreq_role_global 1.0; require { role role_req_r, user_r; } type mod_global_t; type a_t; # role role_req_r types a_t; allow role_req_r user_r; libsepol-3.8.1/tests/policies/test-deps/modreq-role-opt.conf000066400000000000000000000002751476211737200241300ustar00rootroot00000000000000module modreq_role_opt 1.0; require { class file {read write}; } type mod_global_t; optional { require { role role_req_r, user_r; } type mod_opt_t; allow role_req_r user_r; } libsepol-3.8.1/tests/policies/test-deps/modreq-type-global.conf000066400000000000000000000002551476211737200246040ustar00rootroot00000000000000module modreq_type_global 1.0; require { type type_req_t; class file { read write }; } type mod_global_t; type test_t; allow test_t type_req_t : file { read write }; libsepol-3.8.1/tests/policies/test-deps/modreq-type-opt.conf000066400000000000000000000003271476211737200241460ustar00rootroot00000000000000module modreq_type_opt 1.0; require { type file_t; class file { read write }; } type mod_global_t; optional { require { type type_req_t; } type mod_opt_t; allow type_req_t file_t : file { read write }; }libsepol-3.8.1/tests/policies/test-deps/module.conf000066400000000000000000000004721476211737200223660ustar00rootroot00000000000000module my_module 1.0; require { bool secure_mode; type system_t, sysadm_t, file_t; attribute domain; role system_r; class file {read write}; } type new_t, domain; role system_r types new_t; allow system_t file_t : file { read write }; if (secure_mode) { allow sysadm_t file_t : file { read write }; } libsepol-3.8.1/tests/policies/test-deps/small-base.conf000066400000000000000000000162031476211737200231200ustar00rootroot00000000000000# FLASK # # Define the security object classes # class security class process class system class capability # file-related classes class filesystem class file class dir class fd class lnk_file class chr_file class blk_file class sock_file class fifo_file # network-related classes class socket class tcp_socket class udp_socket class rawip_socket class node class netif class netlink_socket class packet_socket class key_socket class unix_stream_socket class unix_dgram_socket # sysv-ipc-related classes class sem class msg class msgq class shm class ipc # FLASK # FLASK # # Define initial security identifiers # sid kernel # FLASK # # Define common prefixes for access vectors # # common common_name { permission_name ... } # # Define a common prefix for file access vectors. # common file { ioctl read write create getattr setattr lock relabelfrom relabelto append unlink link rename execute swapon quotaon mounton } # # Define a common prefix for socket access vectors. # common socket { # inherited from file ioctl read write create getattr setattr lock relabelfrom relabelto append # socket-specific bind connect listen accept getopt setopt shutdown recvfrom sendto recv_msg send_msg name_bind } # # Define a common prefix for ipc access vectors. # common ipc { create destroy getattr setattr read write associate unix_read unix_write } # # Define the access vectors. # # class class_name [ inherits common_name ] { permission_name ... } # # Define the access vector interpretation for file-related objects. # class filesystem { mount remount unmount getattr relabelfrom relabelto transition associate quotamod quotaget } class dir inherits file { add_name remove_name reparent search rmdir } class file inherits file { execute_no_trans entrypoint } class lnk_file inherits file class chr_file inherits file class blk_file inherits file class sock_file inherits file class fifo_file inherits file class fd { use } # # Define the access vector interpretation for network-related objects. # class socket inherits socket class tcp_socket inherits socket { connectto newconn acceptfrom } class udp_socket inherits socket class rawip_socket inherits socket class node { tcp_recv tcp_send udp_recv udp_send rawip_recv rawip_send enforce_dest } class netif { tcp_recv tcp_send udp_recv udp_send rawip_recv rawip_send } class netlink_socket inherits socket class packet_socket inherits socket class key_socket inherits socket class unix_stream_socket inherits socket { connectto newconn acceptfrom } class unix_dgram_socket inherits socket # # Define the access vector interpretation for process-related objects # class process { fork transition sigchld # commonly granted from child to parent sigkill # cannot be caught or ignored sigstop # cannot be caught or ignored signull # for kill(pid, 0) signal # all other signals ptrace getsched setsched getsession getpgid setpgid getcap setcap share } # # Define the access vector interpretation for ipc-related objects # class ipc inherits ipc class sem inherits ipc class msgq inherits ipc { enqueue } class msg { send receive } class shm inherits ipc { lock } # # Define the access vector interpretation for the security server. # class security { compute_av transition_sid member_sid sid_to_context context_to_sid load_policy get_sids change_sid get_user_sids } # # Define the access vector interpretation for system operations. # class system { ipc_info avc_toggle nfsd_control bdflush syslog_read syslog_mod syslog_console ichsid } # # Define the access vector interpretation for controlling capabilities # class capability { # The capabilities are defined in include/linux/capability.h # Care should be taken to ensure that these are consistent with # those definitions. (Order matters) chown dac_override dac_read_search fowner fsetid kill setgid setuid setpcap linux_immutable net_bind_service net_broadcast net_admin net_raw ipc_lock ipc_owner sys_module sys_rawio sys_chroot sys_ptrace sys_pacct sys_admin sys_boot sys_nice sys_resource sys_time sys_tty_config mknod lease } ifdef(`enable_mls',` sensitivity s0; # # Define the ordering of the sensitivity levels (least to greatest) # dominance { s0 } # # Define the categories # # Each category has a name and zero or more aliases. # category c0; category c1; category c2; category c3; category c4; category c5; category c6; category c7; category c8; category c9; category c10; category c11; category c12; category c13; category c14; category c15; category c16; category c17; category c18; category c19; category c20; category c21; category c22; category c23; level s0:c0.c23; mlsconstrain file { write setattr append unlink link rename ioctl lock execute relabelfrom } ( h1 dom h2 ); ') #################################### #################################### ##################################### # TE RULES attribute domain; attribute system; attribute foo; attribute num; attribute num_exec; attribute files; type net_foo_t, foo; type sys_foo_t, foo, system; role system_r types sys_foo_t; type user_t, domain; role user_r types user_t; type sysadm_t, domain, system; role sysadm_r types sysadm_t; type system_t, domain, system, foo; role system_r types { system_t sys_foo_t }; type file_t; type file_exec_t, files; type fs_t; type base_optional_1; type base_optional_2; allow sysadm_t file_exec_t: file { execute read write ioctl lock entrypoint }; optional { require { type base_optional_1, base_optional_2; } allow base_optional_1 base_optional_2 : file { read write }; } ##################################### # Role Allow allow user_r sysadm_r; #################################### # Booleans bool allow_ypbind true; bool secure_mode false; bool allow_execheap false; bool allow_execmem true; bool allow_execmod false; bool allow_execstack true; bool optional_bool_1 true; bool optional_bool_2 false; ##################################### # users gen_user(system_u,, system_r, s0, s0 - s0:c0.c23) gen_user(root,, user_r sysadm_r, s0, s0 - s0:c0.c23) gen_user(joe,, user_r, s0, s0 - s0:c0.c23) ##################################### # constraints #################################### #line 1 "initial_sid_contexts" sid kernel gen_context(system_u:system_r:sys_foo_t, s0) ############################################ #line 1 "fs_use" # fs_use_xattr ext2 gen_context(system_u:object_r:fs_t, s0); fs_use_xattr ext3 gen_context(system_u:object_r:fs_t, s0); fs_use_xattr reiserfs gen_context(system_u:object_r:fs_t, s0); genfscon proc / gen_context(system_u:object_r:sys_foo_t, s0) #################################### #line 1 "net_contexts" #portcon tcp 21 system_u:object_r:net_foo_t:s0 #netifcon lo system_u:object_r:net_foo_t system_u:object_r:net_foo_t:s0 # #nodecon 127.0.0.1 255.255.255.255 system_u:object_r:net_foo_t:s0 nodecon ::1 FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF gen_context(system_u:object_r:net_foo_t, s0) libsepol-3.8.1/tests/policies/test-expander/000077500000000000000000000000001476211737200211025ustar00rootroot00000000000000libsepol-3.8.1/tests/policies/test-expander/alias-base.conf000066400000000000000000000154471476211737200237650ustar00rootroot00000000000000# FLASK # # Define the security object classes # class security class process class system class capability # file-related classes class filesystem class file class dir class fd class lnk_file class chr_file class blk_file class sock_file class fifo_file # network-related classes class socket class tcp_socket class udp_socket class rawip_socket class node class netif class netlink_socket class packet_socket class key_socket class unix_stream_socket class unix_dgram_socket # sysv-ipc-related classes class sem class msg class msgq class shm class ipc # FLASK # FLASK # # Define initial security identifiers # sid kernel # FLASK # # Define common prefixes for access vectors # # common common_name { permission_name ... } # # Define a common prefix for file access vectors. # common file { ioctl read write create getattr setattr lock relabelfrom relabelto append unlink link rename execute swapon quotaon mounton } # # Define a common prefix for socket access vectors. # common socket { # inherited from file ioctl read write create getattr setattr lock relabelfrom relabelto append # socket-specific bind connect listen accept getopt setopt shutdown recvfrom sendto recv_msg send_msg name_bind } # # Define a common prefix for ipc access vectors. # common ipc { create destroy getattr setattr read write associate unix_read unix_write } # # Define the access vectors. # # class class_name [ inherits common_name ] { permission_name ... } # # Define the access vector interpretation for file-related objects. # class filesystem { mount remount unmount getattr relabelfrom relabelto transition associate quotamod quotaget } class dir inherits file { add_name remove_name reparent search rmdir } class file inherits file { execute_no_trans entrypoint } class lnk_file inherits file class chr_file inherits file class blk_file inherits file class sock_file inherits file class fifo_file inherits file class fd { use } # # Define the access vector interpretation for network-related objects. # class socket inherits socket class tcp_socket inherits socket { connectto newconn acceptfrom } class udp_socket inherits socket class rawip_socket inherits socket class node { tcp_recv tcp_send udp_recv udp_send rawip_recv rawip_send enforce_dest } class netif { tcp_recv tcp_send udp_recv udp_send rawip_recv rawip_send } class netlink_socket inherits socket class packet_socket inherits socket class key_socket inherits socket class unix_stream_socket inherits socket { connectto newconn acceptfrom } class unix_dgram_socket inherits socket # # Define the access vector interpretation for process-related objects # class process { fork transition sigchld # commonly granted from child to parent sigkill # cannot be caught or ignored sigstop # cannot be caught or ignored signull # for kill(pid, 0) signal # all other signals ptrace getsched setsched getsession getpgid setpgid getcap setcap share } # # Define the access vector interpretation for ipc-related objects # class ipc inherits ipc class sem inherits ipc class msgq inherits ipc { enqueue } class msg { send receive } class shm inherits ipc { lock } # # Define the access vector interpretation for the security server. # class security { compute_av transition_sid member_sid sid_to_context context_to_sid load_policy get_sids change_sid get_user_sids } # # Define the access vector interpretation for system operations. # class system { ipc_info avc_toggle nfsd_control bdflush syslog_read syslog_mod syslog_console ichsid } # # Define the access vector interpretation for controlling capabilities # class capability { # The capabilities are defined in include/linux/capability.h # Care should be taken to ensure that these are consistent with # those definitions. (Order matters) chown dac_override dac_read_search fowner fsetid kill setgid setuid setpcap linux_immutable net_bind_service net_broadcast net_admin net_raw ipc_lock ipc_owner sys_module sys_rawio sys_chroot sys_ptrace sys_pacct sys_admin sys_boot sys_nice sys_resource sys_time sys_tty_config mknod lease } ifdef(`enable_mls',` sensitivity s0; # # Define the ordering of the sensitivity levels (least to greatest) # dominance { s0 } # # Define the categories # # Each category has a name and zero or more aliases. # category c0; category c1; category c2; category c3; category c4; category c5; category c6; category c7; category c8; category c9; category c10; category c11; category c12; category c13; category c14; category c15; category c16; category c17; category c18; category c19; category c20; category c21; category c22; category c23; level s0:c0.c23; mlsconstrain file { write setattr append unlink link rename ioctl lock execute relabelfrom } ( h1 dom h2 ); ') type enable_optional; # Alias tests type alias_check_1_t; type alias_check_2_t; type alias_check_3_t; typealias alias_check_1_t alias alias_check_1_a; optional { require { type alias_check_2_t; } typealias alias_check_2_t alias alias_check_2_a; } optional { require { type alias_check_3_a; } allow alias_check_3_a enable_optional:file read; } ######## type fs_t; type system_t; type user_t; role system_r; role user_r; role sysadm_r; role system_r types system_t; role user_r types user_t; role sysadm_r types system_t; #################################### # Booleans bool allow_ypbind true; bool secure_mode false; bool allow_execheap false; bool allow_execmem true; bool allow_execmod false; bool allow_execstack true; bool optional_bool_1 true; bool optional_bool_2 false; ##################################### # users gen_user(system_u,, system_r, s0, s0 - s0:c0.c23) gen_user(root,, user_r sysadm_r, s0, s0 - s0:c0.c23) gen_user(joe,, user_r, s0, s0 - s0:c0.c23) ##################################### # constraints #################################### #line 1 "initial_sid_contexts" sid kernel gen_context(system_u:system_r:system_t, s0) ############################################ #line 1 "fs_use" # fs_use_xattr ext2 gen_context(system_u:object_r:fs_t, s0); fs_use_xattr ext3 gen_context(system_u:object_r:fs_t, s0); fs_use_xattr reiserfs gen_context(system_u:object_r:fs_t, s0); genfscon proc / gen_context(system_u:object_r:system_t, s0) #################################### #line 1 "net_contexts" #portcon tcp 21 system_u:object_r:net_foo_t:s0 #netifcon lo system_u:object_r:net_foo_t system_u:object_r:net_foo_t:s0 # #nodecon 127.0.0.1 255.255.255.255 system_u:object_r:net_foo_t:s0 nodecon ::1 FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF gen_context(system_u:object_r:system_t, s0) libsepol-3.8.1/tests/policies/test-expander/alias-module.conf000066400000000000000000000001561476211737200243270ustar00rootroot00000000000000module my_module 1.0; require { type alias_check_3_t; } typealias alias_check_3_t alias alias_check_3_a; libsepol-3.8.1/tests/policies/test-expander/base-base-only.conf000066400000000000000000000007231476211737200245540ustar00rootroot00000000000000class security class file sid kernel common file { read } class file inherits file { entrypoint } class security { compute_av } ifdef(`enable_mls',` sensitivity s0; dominance { s0 } category c0; level s0:c0; mlsconstrain file { read } ( h1 dom h2 ); ') attribute myattr; type mytype_t; role myrole_r; role myrole_r types mytype_t; bool mybool true; gen_user(myuser_u,, myrole_r, s0, s0 - s0:c0) sid kernel gen_context(myuser_u:myrole_r:mytype_t, s0) libsepol-3.8.1/tests/policies/test-expander/module.conf000066400000000000000000000140671476211737200232460ustar00rootroot00000000000000module my_module 1.0; require { bool allow_ypbind, secure_mode, allow_execstack; type system_t, sysadm_t; class file {read write}; attribute attr_check_base_2, attr_check_base_3; attribute attr_check_base_optional_2; } bool module_1_bool true; if (module_1_bool && allow_ypbind && secure_mode && allow_execstack) { allow system_t sysadm_t : file { read write }; } optional { bool module_1_bool_2 false; require { bool optional_bool_1, optional_bool_2; class file { execute ioctl }; } if (optional_bool_1 && optional_bool_2 || module_1_bool_2) { allow system_t sysadm_t : file {execute ioctl}; } } # Type - attribute mapping test type module_t; attribute attr_check_mod_1; attribute attr_check_mod_2; attribute attr_check_mod_3; attribute attr_check_mod_4; attribute attr_check_mod_5; attribute attr_check_mod_6; attribute attr_check_mod_7; attribute attr_check_mod_8; attribute attr_check_mod_9; attribute attr_check_mod_10; attribute attr_check_mod_11; optional { require { type base_t; } attribute attr_check_mod_optional_1; attribute attr_check_mod_optional_2; attribute attr_check_mod_optional_3; attribute attr_check_mod_optional_4; attribute attr_check_mod_optional_5; attribute attr_check_mod_optional_6; attribute attr_check_mod_optional_7; } optional { require { type does_not_exist_t; } attribute attr_check_mod_optional_disabled_4; attribute attr_check_mod_optional_disabled_7; } type attr_check_base_2_1_t, attr_check_base_2; type attr_check_base_2_2_t; typeattribute attr_check_base_2_2_t attr_check_base_2; type attr_check_base_3_3_t, attr_check_base_3; type attr_check_base_3_4_t; typeattribute attr_check_base_3_4_t attr_check_base_3; optional { require { attribute attr_check_base_5; } type attr_check_base_5_1_t, attr_check_base_5; type attr_check_base_5_2_t; typeattribute attr_check_base_5_2_t attr_check_base_5; } optional { require { attribute attr_check_base_6; } type attr_check_base_6_3_t, attr_check_base_6; type attr_check_base_6_4_t; typeattribute attr_check_base_6_4_t attr_check_base_6; } optional { require { type does_not_exist_t; attribute attr_check_base_8; } type attr_check_base_8_1_t, attr_check_base_8; type attr_check_base_8_2_t; typeattribute attr_check_base_8_2_t attr_check_base_8; } optional { require { type does_not_exist_t; attribute attr_check_base_9; } type attr_check_base_9_3_t, attr_check_base_9; type attr_check_base_9_4_t; typeattribute attr_check_base_9_4_t attr_check_base_9; } optional { require { type does_not_exist_t; attribute attr_check_base_10; } type attr_check_base_10_3_t, attr_check_base_10; type attr_check_base_10_4_t; typeattribute attr_check_base_10_4_t attr_check_base_10; } optional { require { attribute attr_check_base_11; } type attr_check_base_11_3_t, attr_check_base_11; type attr_check_base_11_4_t; typeattribute attr_check_base_11_4_t attr_check_base_11; } type attr_check_base_optional_2_1_t, attr_check_base_optional_2; type attr_check_base_optional_2_2_t; typeattribute attr_check_base_optional_2_2_t attr_check_base_optional_2; optional { require { attribute attr_check_base_optional_5; } type attr_check_base_optional_5_1_t, attr_check_base_optional_5; type attr_check_base_optional_5_2_t; typeattribute attr_check_base_optional_5_2_t attr_check_base_optional_5; } #optional { # require { # attribute attr_check_base_optional_6; # } # type attr_check_base_optional_6_3_t, attr_check_base_optional_6; # type attr_check_base_optional_6_4_t; # typeattribute attr_check_base_optional_6_4_t attr_check_base_optional_6; #} optional { require { type does_not_exist_t; attribute attr_check_base_optional_8; } type attr_check_base_optional_8_1_t, attr_check_base_optional_8; type attr_check_base_optional_8_2_t; typeattribute attr_check_base_optional_8_2_t attr_check_base_optional_8; } type attr_check_mod_2_1_t, attr_check_mod_2; type attr_check_mod_2_2_t; typeattribute attr_check_mod_2_2_t attr_check_mod_2; optional { require { attribute attr_check_mod_5; } type attr_check_mod_5_1_t, attr_check_mod_5; type attr_check_mod_5_2_t; typeattribute attr_check_mod_5_2_t attr_check_mod_5; } optional { require { attribute attr_check_mod_6; } type attr_check_mod_6_3_t, attr_check_mod_6; type attr_check_mod_6_4_t; typeattribute attr_check_mod_6_4_t attr_check_mod_6; } optional { require { type does_not_exist_t; } type attr_check_mod_8_1_t, attr_check_mod_8; type attr_check_mod_8_2_t; typeattribute attr_check_mod_8_2_t attr_check_mod_8; } optional { require { type does_not_exist_t; } type attr_check_mod_9_3_t, attr_check_mod_9; type attr_check_mod_9_4_t; typeattribute attr_check_mod_9_4_t attr_check_mod_9; } optional { require { type does_not_exist_t; } type attr_check_mod_10_3_t, attr_check_mod_10; type attr_check_mod_10_4_t; typeattribute attr_check_mod_10_4_t attr_check_mod_10; } optional { require { type base_t; } type attr_check_mod_11_3_t, attr_check_mod_11; type attr_check_mod_11_4_t; typeattribute attr_check_mod_11_4_t attr_check_mod_11; } #optional { # require { # attribute attr_check_mod_optional_5; # } # type attr_check_mod_optional_5_1_t, attr_check_mod_optional_5; # type attr_check_mod_optional_5_2_t; # typeattribute attr_check_mod_optional_5_2_t attr_check_mod_optional_5; #} #optional { # require { # attribute attr_check_mod_optional_6; # } # type attr_check_mod_optional_6_3_t, attr_check_mod_optional_6; # type attr_check_mod_optional_6_4_t; # typeattribute attr_check_mod_optional_6_4_t attr_check_mod_optional_6; #} optional { require { attribute attr_check_base_optional_disabled_5; } type attr_check_base_optional_disabled_5_1_t, attr_check_base_optional_disabled_5; type attr_check_base_optional_disabled_5_2_t; typeattribute attr_check_base_optional_disabled_5_2_t attr_check_base_optional_disabled_5; } optional { require { type does_not_exist_t; attribute attr_check_base_optional_disabled_8; } type attr_check_base_optional_disabled_8_1_t, attr_check_base_optional_disabled_8; type attr_check_base_optional_disabled_8_2_t; typeattribute attr_check_base_optional_disabled_8_2_t attr_check_base_optional_disabled_8; } libsepol-3.8.1/tests/policies/test-expander/role-base.conf000066400000000000000000000150521476211737200236250ustar00rootroot00000000000000# FLASK # # Define the security object classes # class security class process class system class capability # file-related classes class filesystem class file class dir class fd class lnk_file class chr_file class blk_file class sock_file class fifo_file # network-related classes class socket class tcp_socket class udp_socket class rawip_socket class node class netif class netlink_socket class packet_socket class key_socket class unix_stream_socket class unix_dgram_socket # sysv-ipc-related classes class sem class msg class msgq class shm class ipc # FLASK # FLASK # # Define initial security identifiers # sid kernel # FLASK # # Define common prefixes for access vectors # # common common_name { permission_name ... } # # Define a common prefix for file access vectors. # common file { ioctl read write create getattr setattr lock relabelfrom relabelto append unlink link rename execute swapon quotaon mounton } # # Define a common prefix for socket access vectors. # common socket { # inherited from file ioctl read write create getattr setattr lock relabelfrom relabelto append # socket-specific bind connect listen accept getopt setopt shutdown recvfrom sendto recv_msg send_msg name_bind } # # Define a common prefix for ipc access vectors. # common ipc { create destroy getattr setattr read write associate unix_read unix_write } # # Define the access vectors. # # class class_name [ inherits common_name ] { permission_name ... } # # Define the access vector interpretation for file-related objects. # class filesystem { mount remount unmount getattr relabelfrom relabelto transition associate quotamod quotaget } class dir inherits file { add_name remove_name reparent search rmdir } class file inherits file { execute_no_trans entrypoint } class lnk_file inherits file class chr_file inherits file class blk_file inherits file class sock_file inherits file class fifo_file inherits file class fd { use } # # Define the access vector interpretation for network-related objects. # class socket inherits socket class tcp_socket inherits socket { connectto newconn acceptfrom } class udp_socket inherits socket class rawip_socket inherits socket class node { tcp_recv tcp_send udp_recv udp_send rawip_recv rawip_send enforce_dest } class netif { tcp_recv tcp_send udp_recv udp_send rawip_recv rawip_send } class netlink_socket inherits socket class packet_socket inherits socket class key_socket inherits socket class unix_stream_socket inherits socket { connectto newconn acceptfrom } class unix_dgram_socket inherits socket # # Define the access vector interpretation for process-related objects # class process { fork transition sigchld # commonly granted from child to parent sigkill # cannot be caught or ignored sigstop # cannot be caught or ignored signull # for kill(pid, 0) signal # all other signals ptrace getsched setsched getsession getpgid setpgid getcap setcap share } # # Define the access vector interpretation for ipc-related objects # class ipc inherits ipc class sem inherits ipc class msgq inherits ipc { enqueue } class msg { send receive } class shm inherits ipc { lock } # # Define the access vector interpretation for the security server. # class security { compute_av transition_sid member_sid sid_to_context context_to_sid load_policy get_sids change_sid get_user_sids } # # Define the access vector interpretation for system operations. # class system { ipc_info avc_toggle nfsd_control bdflush syslog_read syslog_mod syslog_console ichsid } # # Define the access vector interpretation for controlling capabilities # class capability { # The capabilities are defined in include/linux/capability.h # Care should be taken to ensure that these are consistent with # those definitions. (Order matters) chown dac_override dac_read_search fowner fsetid kill setgid setuid setpcap linux_immutable net_bind_service net_broadcast net_admin net_raw ipc_lock ipc_owner sys_module sys_rawio sys_chroot sys_ptrace sys_pacct sys_admin sys_boot sys_nice sys_resource sys_time sys_tty_config mknod lease } ifdef(`enable_mls',` sensitivity s0; # # Define the ordering of the sensitivity levels (least to greatest) # dominance { s0 } # # Define the categories # # Each category has a name and zero or more aliases. # category c0; category c1; category c2; category c3; category c4; category c5; category c6; category c7; category c8; category c9; category c10; category c11; category c12; category c13; category c14; category c15; category c16; category c17; category c18; category c19; category c20; category c21; category c22; category c23; level s0:c0.c23; mlsconstrain file { write setattr append unlink link rename ioctl lock execute relabelfrom } ( h1 dom h2 ); ') # Role mapping test type role_check_1_1_t; role role_check_1; role role_check_1 types role_check_1_1_t; ######## type fs_t; type system_t; type user_t; role system_r; role user_r; role sysadm_r; role system_r types system_t; role user_r types user_t; role sysadm_r types system_t; #################################### # Booleans bool allow_ypbind true; bool secure_mode false; bool allow_execheap false; bool allow_execmem true; bool allow_execmod false; bool allow_execstack true; bool optional_bool_1 true; bool optional_bool_2 false; ##################################### # users gen_user(system_u,, system_r, s0, s0 - s0:c0.c23) gen_user(root,, user_r sysadm_r, s0, s0 - s0:c0.c23) gen_user(joe,, user_r, s0, s0 - s0:c0.c23) ##################################### # constraints #################################### #line 1 "initial_sid_contexts" sid kernel gen_context(system_u:system_r:system_t, s0) ############################################ #line 1 "fs_use" # fs_use_xattr ext2 gen_context(system_u:object_r:fs_t, s0); fs_use_xattr ext3 gen_context(system_u:object_r:fs_t, s0); fs_use_xattr reiserfs gen_context(system_u:object_r:fs_t, s0); genfscon proc / gen_context(system_u:object_r:system_t, s0) #################################### #line 1 "net_contexts" #portcon tcp 21 system_u:object_r:net_foo_t:s0 #netifcon lo system_u:object_r:net_foo_t system_u:object_r:net_foo_t:s0 # #nodecon 127.0.0.1 255.255.255.255 system_u:object_r:net_foo_t:s0 nodecon ::1 FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF gen_context(system_u:object_r:system_t, s0) libsepol-3.8.1/tests/policies/test-expander/role-module.conf000066400000000000000000000002241476211737200241730ustar00rootroot00000000000000module my_module 1.0; require { class file {read write}; role role_check_1; } type role_check_1_2_t; role role_check_1 types role_check_1_2_t; libsepol-3.8.1/tests/policies/test-expander/small-base.conf000066400000000000000000000314131476211737200237730ustar00rootroot00000000000000# FLASK # # Define the security object classes # class security class process class system class capability # file-related classes class filesystem class file class dir class fd class lnk_file class chr_file class blk_file class sock_file class fifo_file # network-related classes class socket class tcp_socket class udp_socket class rawip_socket class node class netif class netlink_socket class packet_socket class key_socket class unix_stream_socket class unix_dgram_socket # sysv-ipc-related classes class sem class msg class msgq class shm class ipc # FLASK # FLASK # # Define initial security identifiers # sid kernel # FLASK # # Define common prefixes for access vectors # # common common_name { permission_name ... } # # Define a common prefix for file access vectors. # common file { ioctl read write create getattr setattr lock relabelfrom relabelto append unlink link rename execute swapon quotaon mounton } # # Define a common prefix for socket access vectors. # common socket { # inherited from file ioctl read write create getattr setattr lock relabelfrom relabelto append # socket-specific bind connect listen accept getopt setopt shutdown recvfrom sendto recv_msg send_msg name_bind } # # Define a common prefix for ipc access vectors. # common ipc { create destroy getattr setattr read write associate unix_read unix_write } # # Define the access vectors. # # class class_name [ inherits common_name ] { permission_name ... } # # Define the access vector interpretation for file-related objects. # class filesystem { mount remount unmount getattr relabelfrom relabelto transition associate quotamod quotaget } class dir inherits file { add_name remove_name reparent search rmdir } class file inherits file { execute_no_trans entrypoint } class lnk_file inherits file class chr_file inherits file class blk_file inherits file class sock_file inherits file class fifo_file inherits file class fd { use } # # Define the access vector interpretation for network-related objects. # class socket inherits socket class tcp_socket inherits socket { connectto newconn acceptfrom } class udp_socket inherits socket class rawip_socket inherits socket class node { tcp_recv tcp_send udp_recv udp_send rawip_recv rawip_send enforce_dest } class netif { tcp_recv tcp_send udp_recv udp_send rawip_recv rawip_send } class netlink_socket inherits socket class packet_socket inherits socket class key_socket inherits socket class unix_stream_socket inherits socket { connectto newconn acceptfrom } class unix_dgram_socket inherits socket # # Define the access vector interpretation for process-related objects # class process { fork transition sigchld # commonly granted from child to parent sigkill # cannot be caught or ignored sigstop # cannot be caught or ignored signull # for kill(pid, 0) signal # all other signals ptrace getsched setsched getsession getpgid setpgid getcap setcap share } # # Define the access vector interpretation for ipc-related objects # class ipc inherits ipc class sem inherits ipc class msgq inherits ipc { enqueue } class msg { send receive } class shm inherits ipc { lock } # # Define the access vector interpretation for the security server. # class security { compute_av transition_sid member_sid sid_to_context context_to_sid load_policy get_sids change_sid get_user_sids } # # Define the access vector interpretation for system operations. # class system { ipc_info avc_toggle nfsd_control bdflush syslog_read syslog_mod syslog_console ichsid } # # Define the access vector interpretation for controlling capabilities # class capability { # The capabilities are defined in include/linux/capability.h # Care should be taken to ensure that these are consistent with # those definitions. (Order matters) chown dac_override dac_read_search fowner fsetid kill setgid setuid setpcap linux_immutable net_bind_service net_broadcast net_admin net_raw ipc_lock ipc_owner sys_module sys_rawio sys_chroot sys_ptrace sys_pacct sys_admin sys_boot sys_nice sys_resource sys_time sys_tty_config mknod lease } ifdef(`enable_mls',` sensitivity s0; # # Define the ordering of the sensitivity levels (least to greatest) # dominance { s0 } # # Define the categories # # Each category has a name and zero or more aliases. # category c0; category c1; category c2; category c3; category c4; category c5; category c6; category c7; category c8; category c9; category c10; category c11; category c12; category c13; category c14; category c15; category c16; category c17; category c18; category c19; category c20; category c21; category c22; category c23; level s0:c0.c23; mlsconstrain file { write setattr append unlink link rename ioctl lock execute relabelfrom } ( h1 dom h2 ); ') #################################### #################################### ##################################### # TE RULES attribute domain; attribute system; attribute foo; attribute num; attribute num_exec; attribute files; # Type - attribute mapping test # Shorthand tests # 1 = types in base, 2 = types in mod, 3 = types in both # 4 = types in optional in base, 5 = types in optional in mod # 6 = types in optional in both # 7 = types in disabled optional in base # 8 = types in disabled optional in module # 9 = types in disabled optional in both # 10 = types in enabled optional in base, disabled optional in module # 11 = types in disabled optional in base, enabled optional in module attribute attr_check_base_1; attribute attr_check_base_2; attribute attr_check_base_3; attribute attr_check_base_4; attribute attr_check_base_5; attribute attr_check_base_6; attribute attr_check_base_7; attribute attr_check_base_8; attribute attr_check_base_9; attribute attr_check_base_10; attribute attr_check_base_11; optional { require { type module_t; } attribute attr_check_base_optional_1; attribute attr_check_base_optional_2; attribute attr_check_base_optional_3; attribute attr_check_base_optional_4; attribute attr_check_base_optional_5; attribute attr_check_base_optional_6; attribute attr_check_base_optional_8; } optional { require { type does_not_exist_t; } attribute attr_check_base_optional_disabled_5; attribute attr_check_base_optional_disabled_8; } type net_foo_t, foo; type sys_foo_t, foo, system; role system_r; role system_r types sys_foo_t; type user_t, domain; role user_r; role user_r types user_t; type sysadm_t, domain, system; role sysadm_r; role sysadm_r types sysadm_t; type system_t, domain, system, foo; role system_r types { system_t sys_foo_t }; type file_t; type file_exec_t, files; type fs_t; type base_optional_1; type base_optional_2; allow sysadm_t file_exec_t: file { execute read write ioctl lock entrypoint }; optional { require { type base_optional_1, base_optional_2; } allow base_optional_1 base_optional_2 : file { read write }; } # Type - attribute mapping test type base_t; type attr_check_base_1_1_t, attr_check_base_1; type attr_check_base_1_2_t; typeattribute attr_check_base_1_2_t attr_check_base_1; type attr_check_base_3_1_t, attr_check_base_3; type attr_check_base_3_2_t; typeattribute attr_check_base_3_2_t attr_check_base_3; optional { require { attribute attr_check_base_4; } type attr_check_base_4_1_t, attr_check_base_4; type attr_check_base_4_2_t; typeattribute attr_check_base_4_2_t attr_check_base_4; } optional { require { type module_t; } type attr_check_base_6_1_t, attr_check_base_6; type attr_check_base_6_2_t; typeattribute attr_check_base_6_2_t attr_check_base_6; } optional { require { type does_not_exist_t; } type attr_check_base_7_1_t, attr_check_base_7; type attr_check_base_7_2_t; typeattribute attr_check_base_7_2_t attr_check_base_7; } optional { require { type does_not_exist_t; } type attr_check_base_9_1_t, attr_check_base_9; type attr_check_base_9_2_t; typeattribute attr_check_base_9_2_t attr_check_base_9; } optional { require { type module_t; } type attr_check_base_10_1_t, attr_check_base_10; type attr_check_base_10_2_t; typeattribute attr_check_base_10_2_t attr_check_base_10; } optional { require { type does_not_exist_t; } type attr_check_base_11_1_t, attr_check_base_11; type attr_check_base_11_2_t; typeattribute attr_check_base_11_2_t attr_check_base_11; } #optional { # require { # attribute attr_check_base_optional_4; # } # type attr_check_base_optional_4_1_t, attr_check_base_optional_4; # type attr_check_base_optional_4_2_t; # typeattribute attr_check_base_optional_4_2_t attr_check_base_optional_4; #} #optional { # require { # attribute attr_check_base_optional_6; # } # type attr_check_base_optional_6_1_t, attr_check_base_optional_6; # type attr_check_base_optional_6_2_t; # typeattribute attr_check_base_optional_6_2_t attr_check_base_optional_6; #} optional { require { attribute attr_check_mod_4; } type attr_check_mod_4_1_t, attr_check_mod_4; type attr_check_mod_4_2_t; typeattribute attr_check_mod_4_2_t attr_check_mod_4; } optional { require { attribute attr_check_mod_6; } type attr_check_mod_6_1_t, attr_check_mod_6; type attr_check_mod_6_2_t; typeattribute attr_check_mod_6_2_t attr_check_mod_6; } optional { require { type does_not_exist_t; attribute attr_check_mod_7; } type attr_check_mod_7_1_t, attr_check_mod_7; type attr_check_mod_7_2_t; typeattribute attr_check_mod_7_2_t attr_check_mod_7; } optional { require { type does_not_exist_t; attribute attr_check_mod_9; } type attr_check_mod_9_1_t, attr_check_mod_9; type attr_check_mod_9_2_t; typeattribute attr_check_mod_9_2_t attr_check_mod_9; } optional { require { attribute attr_check_mod_10; } type attr_check_mod_10_1_t, attr_check_mod_10; type attr_check_mod_10_2_t; typeattribute attr_check_mod_10_2_t attr_check_mod_10; } optional { require { type does_not_exist_t; attribute attr_check_mod_11; } type attr_check_mod_11_1_t, attr_check_mod_11; type attr_check_mod_11_2_t; typeattribute attr_check_mod_11_2_t attr_check_mod_11; } optional { require { attribute attr_check_mod_optional_4; } type attr_check_mod_optional_4_1_t, attr_check_mod_optional_4; type attr_check_mod_optional_4_2_t; typeattribute attr_check_mod_optional_4_2_t attr_check_mod_optional_4; } optional { require { attribute attr_check_mod_optional_6; } type attr_check_mod_optional_6_1_t, attr_check_mod_optional_6; type attr_check_mod_optional_6_2_t; typeattribute attr_check_mod_optional_6_2_t attr_check_mod_optional_6; } optional { require { type does_not_exist_t; attribute attr_check_mod_optional_7; } type attr_check_mod_optional_7_1_t, attr_check_mod_optional_7; type attr_check_mod_optional_7_2_t; typeattribute attr_check_mod_optional_7_2_t attr_check_mod_optional_7; } optional { require { attribute attr_check_mod_optional_disabled_4; } type attr_check_mod_optional_disabled_4_1_t, attr_check_mod_optional_disabled_4; type attr_check_mod_optional_disabled_4_2_t; typeattribute attr_check_mod_optional_disabled_4_2_t attr_check_mod_optional_disabled_4; } optional { require { type does_not_exist_t; attribute attr_check_mod_optional_disabled_7; } type attr_check_mod_optional_disabled_7_1_t, attr_check_mod_optional_disabled_7; type attr_check_mod_optional_disabled_7_2_t; typeattribute attr_check_mod_optional_disabled_7_2_t attr_check_mod_optional_disabled_7; } ##################################### # Role Allow allow user_r sysadm_r; #################################### # Booleans bool allow_ypbind true; bool secure_mode false; bool allow_execheap false; bool allow_execmem true; bool allow_execmod false; bool allow_execstack true; bool optional_bool_1 true; bool optional_bool_2 false; ##################################### # users gen_user(system_u,, system_r, s0, s0 - s0:c0.c23) gen_user(root,, user_r sysadm_r, s0, s0 - s0:c0.c23) gen_user(joe,, user_r, s0, s0 - s0:c0.c23) ##################################### # constraints #################################### #line 1 "initial_sid_contexts" sid kernel gen_context(system_u:system_r:sys_foo_t, s0) ############################################ #line 1 "fs_use" # fs_use_xattr ext2 gen_context(system_u:object_r:fs_t, s0); fs_use_xattr ext3 gen_context(system_u:object_r:fs_t, s0); fs_use_xattr reiserfs gen_context(system_u:object_r:fs_t, s0); genfscon proc / gen_context(system_u:object_r:sys_foo_t, s0) #################################### #line 1 "net_contexts" #portcon tcp 21 system_u:object_r:net_foo_t:s0 #netifcon lo system_u:object_r:net_foo_t system_u:object_r:net_foo_t:s0 # #nodecon 127.0.0.1 255.255.255.255 system_u:object_r:net_foo_t:s0 nodecon ::1 FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF gen_context(system_u:object_r:net_foo_t, s0) libsepol-3.8.1/tests/policies/test-expander/user-base.conf000066400000000000000000000153351476211737200236460ustar00rootroot00000000000000# FLASK # # Define the security object classes # class security class process class system class capability # file-related classes class filesystem class file class dir class fd class lnk_file class chr_file class blk_file class sock_file class fifo_file # network-related classes class socket class tcp_socket class udp_socket class rawip_socket class node class netif class netlink_socket class packet_socket class key_socket class unix_stream_socket class unix_dgram_socket # sysv-ipc-related classes class sem class msg class msgq class shm class ipc # FLASK # FLASK # # Define initial security identifiers # sid kernel # FLASK # # Define common prefixes for access vectors # # common common_name { permission_name ... } # # Define a common prefix for file access vectors. # common file { ioctl read write create getattr setattr lock relabelfrom relabelto append unlink link rename execute swapon quotaon mounton } # # Define a common prefix for socket access vectors. # common socket { # inherited from file ioctl read write create getattr setattr lock relabelfrom relabelto append # socket-specific bind connect listen accept getopt setopt shutdown recvfrom sendto recv_msg send_msg name_bind } # # Define a common prefix for ipc access vectors. # common ipc { create destroy getattr setattr read write associate unix_read unix_write } # # Define the access vectors. # # class class_name [ inherits common_name ] { permission_name ... } # # Define the access vector interpretation for file-related objects. # class filesystem { mount remount unmount getattr relabelfrom relabelto transition associate quotamod quotaget } class dir inherits file { add_name remove_name reparent search rmdir } class file inherits file { execute_no_trans entrypoint } class lnk_file inherits file class chr_file inherits file class blk_file inherits file class sock_file inherits file class fifo_file inherits file class fd { use } # # Define the access vector interpretation for network-related objects. # class socket inherits socket class tcp_socket inherits socket { connectto newconn acceptfrom } class udp_socket inherits socket class rawip_socket inherits socket class node { tcp_recv tcp_send udp_recv udp_send rawip_recv rawip_send enforce_dest } class netif { tcp_recv tcp_send udp_recv udp_send rawip_recv rawip_send } class netlink_socket inherits socket class packet_socket inherits socket class key_socket inherits socket class unix_stream_socket inherits socket { connectto newconn acceptfrom } class unix_dgram_socket inherits socket # # Define the access vector interpretation for process-related objects # class process { fork transition sigchld # commonly granted from child to parent sigkill # cannot be caught or ignored sigstop # cannot be caught or ignored signull # for kill(pid, 0) signal # all other signals ptrace getsched setsched getsession getpgid setpgid getcap setcap share } # # Define the access vector interpretation for ipc-related objects # class ipc inherits ipc class sem inherits ipc class msgq inherits ipc { enqueue } class msg { send receive } class shm inherits ipc { lock } # # Define the access vector interpretation for the security server. # class security { compute_av transition_sid member_sid sid_to_context context_to_sid load_policy get_sids change_sid get_user_sids } # # Define the access vector interpretation for system operations. # class system { ipc_info avc_toggle nfsd_control bdflush syslog_read syslog_mod syslog_console ichsid } # # Define the access vector interpretation for controlling capabilities # class capability { # The capabilities are defined in include/linux/capability.h # Care should be taken to ensure that these are consistent with # those definitions. (Order matters) chown dac_override dac_read_search fowner fsetid kill setgid setuid setpcap linux_immutable net_bind_service net_broadcast net_admin net_raw ipc_lock ipc_owner sys_module sys_rawio sys_chroot sys_ptrace sys_pacct sys_admin sys_boot sys_nice sys_resource sys_time sys_tty_config mknod lease } ifdef(`enable_mls',` sensitivity s0; # # Define the ordering of the sensitivity levels (least to greatest) # dominance { s0 } # # Define the categories # # Each category has a name and zero or more aliases. # category c0; category c1; category c2; category c3; category c4; category c5; category c6; category c7; category c8; category c9; category c10; category c11; category c12; category c13; category c14; category c15; category c16; category c17; category c18; category c19; category c20; category c21; category c22; category c23; level s0:c0.c23; mlsconstrain file { write setattr append unlink link rename ioctl lock execute relabelfrom } ( h1 dom h2 ); ') # User mapping test type user_check_1_1_t; type user_check_1_2_t; role user_check_1_1_r; role user_check_1_2_r; role user_check_1_1_r types user_check_1_1_t; role user_check_1_2_r types user_check_1_2_t; ######## type fs_t; type system_t; type user_t; role system_r; role user_r; role sysadm_r; role system_r types system_t; role user_r types user_t; role sysadm_r types system_t; #################################### # Booleans bool allow_ypbind true; bool secure_mode false; bool allow_execheap false; bool allow_execmem true; bool allow_execmod false; bool allow_execstack true; bool optional_bool_1 true; bool optional_bool_2 false; ##################################### # users gen_user(user_check_1,, user_check_1_1_r user_check_1_2_r, s0, s0 - s0:c0.c23) gen_user(system_u,, system_r, s0, s0 - s0:c0.c23) gen_user(root,, user_r sysadm_r, s0, s0 - s0:c0.c23) gen_user(joe,, user_r, s0, s0 - s0:c0.c23) ##################################### # constraints #################################### #line 1 "initial_sid_contexts" sid kernel gen_context(system_u:system_r:system_t, s0) ############################################ #line 1 "fs_use" # fs_use_xattr ext2 gen_context(system_u:object_r:fs_t, s0); fs_use_xattr ext3 gen_context(system_u:object_r:fs_t, s0); fs_use_xattr reiserfs gen_context(system_u:object_r:fs_t, s0); genfscon proc / gen_context(system_u:object_r:system_t, s0) #################################### #line 1 "net_contexts" #portcon tcp 21 system_u:object_r:net_foo_t:s0 #netifcon lo system_u:object_r:net_foo_t system_u:object_r:net_foo_t:s0 # #nodecon 127.0.0.1 255.255.255.255 system_u:object_r:net_foo_t:s0 nodecon ::1 FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF gen_context(system_u:object_r:system_t, s0) libsepol-3.8.1/tests/policies/test-expander/user-module.conf000066400000000000000000000001531476211737200242110ustar00rootroot00000000000000module my_module 1.0; require { class file {read write}; ifdef(`enable_mls',` user user_check_1; ') } libsepol-3.8.1/tests/policies/test-hooks/000077500000000000000000000000001476211737200204175ustar00rootroot00000000000000libsepol-3.8.1/tests/policies/test-hooks/cmp_policy.conf000066400000000000000000000144311476211737200234270ustar00rootroot00000000000000# FLASK # # Define the security object classes # class security class process class system class capability # file-related classes class filesystem class file class dir class fd class lnk_file class chr_file class blk_file class sock_file class fifo_file # network-related classes class socket class tcp_socket class udp_socket class rawip_socket class node class netif class netlink_socket class packet_socket class key_socket class unix_stream_socket class unix_dgram_socket # sysv-ipc-related classes class sem class msg class msgq class shm class ipc # FLASK # FLASK # # Define initial security identifiers # sid kernel # FLASK # # Define common prefixes for access vectors # # common common_name { permission_name ... } # # Define a common prefix for file access vectors. # common file { ioctl read write create getattr setattr lock relabelfrom relabelto append unlink link rename execute swapon quotaon mounton } # # Define a common prefix for socket access vectors. # common socket { # inherited from file ioctl read write create getattr setattr lock relabelfrom relabelto append # socket-specific bind connect listen accept getopt setopt shutdown recvfrom sendto recv_msg send_msg name_bind } # # Define a common prefix for ipc access vectors. # common ipc { create destroy getattr setattr read write associate unix_read unix_write } # # Define the access vectors. # # class class_name [ inherits common_name ] { permission_name ... } # # Define the access vector interpretation for file-related objects. # class filesystem { mount remount unmount getattr relabelfrom relabelto transition associate quotamod quotaget } class dir inherits file { add_name remove_name reparent search rmdir } class file inherits file { execute_no_trans entrypoint } class lnk_file inherits file class chr_file inherits file class blk_file inherits file class sock_file inherits file class fifo_file inherits file class fd { use } # # Define the access vector interpretation for network-related objects. # class socket inherits socket class tcp_socket inherits socket { connectto newconn acceptfrom } class udp_socket inherits socket class rawip_socket inherits socket class node { tcp_recv tcp_send udp_recv udp_send rawip_recv rawip_send enforce_dest } class netif { tcp_recv tcp_send udp_recv udp_send rawip_recv rawip_send } class netlink_socket inherits socket class packet_socket inherits socket class key_socket inherits socket class unix_stream_socket inherits socket { connectto newconn acceptfrom } class unix_dgram_socket inherits socket # # Define the access vector interpretation for process-related objects # class process { fork transition sigchld # commonly granted from child to parent sigkill # cannot be caught or ignored sigstop # cannot be caught or ignored signull # for kill(pid, 0) signal # all other signals ptrace getsched setsched getsession getpgid setpgid getcap setcap share } # # Define the access vector interpretation for ipc-related objects # class ipc inherits ipc class sem inherits ipc class msgq inherits ipc { enqueue } class msg { send receive } class shm inherits ipc { lock } # # Define the access vector interpretation for the security server. # class security { compute_av transition_sid member_sid sid_to_context context_to_sid load_policy get_sids change_sid get_user_sids } # # Define the access vector interpretation for system operations. # class system { ipc_info avc_toggle nfsd_control bdflush syslog_read syslog_mod syslog_console ichsid } # # Define the access vector interpretation for controlling capabilities # class capability { # The capabilities are defined in include/linux/capability.h # Care should be taken to ensure that these are consistent with # those definitions. (Order matters) chown dac_override dac_read_search fowner fsetid kill setgid setuid setpcap linux_immutable net_bind_service net_broadcast net_admin net_raw ipc_lock ipc_owner sys_module sys_rawio sys_chroot sys_ptrace sys_pacct sys_admin sys_boot sys_nice sys_resource sys_time sys_tty_config mknod lease } ifdef(`enable_mls',` sensitivity s0; # # Define the ordering of the sensitivity levels (least to greatest) # dominance { s0 } # # Define the categories # # Each category has a name and zero or more aliases. # category c0; category c1; category c2; category c3; category c4; category c5; category c6; category c7; category c8; category c9; category c10; category c11; category c12; category c13; category c14; category c15; category c16; category c17; category c18; category c19; category c20; category c21; category c22; category c23; level s0:c0.c23; mlsconstrain file { write setattr append unlink link rename ioctl lock execute relabelfrom } ( h1 dom h2 ); ') #################################### #################################### ##################################### #g_b stands for global base type g_b_type_1; role g_b_role_1 types g_b_type_1; role g_b_role_2 types g_b_type_1; role g_b_role_3 types g_b_type_1; type g_b_type_2; optional { require { type invalid_type; } allow g_b_role_2 g_b_role_3; role_transition g_b_role_2 g_b_type_2 g_b_role_3; } gen_user(g_b_user_1,, g_b_role_1, s0, s0 - s0:c0.c23) #################################### #line 1 "initial_sid_contexts" sid kernel gen_context(g_b_user_1:g_b_role_1:g_b_type_1, s0) ############################################ #line 1 "fs_use" # fs_use_xattr ext2 gen_context(g_b_user_1:object_r:g_b_type_1, s0); fs_use_xattr ext3 gen_context(g_b_user_1:object_r:g_b_type_1, s0); fs_use_xattr reiserfs gen_context(g_b_user_1:object_r:g_b_type_1, s0); genfscon proc / gen_context(g_b_user_1:object_r:g_b_type_1, s0) #################################### #line 1 "net_contexts" #portcon tcp 21 g_b_user_1:object_r:net_foo_t:s0 #netifcon lo g_b_user_1:object_r:net_foo_t g_b_user_1:object_r:net_foo_t:s0 # #nodecon 127.0.0.1 255.255.255.255 g_b_user_1:object_r:net_foo_t:s0 nodecon ::1 FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF gen_context(g_b_user_1:object_r:g_b_type_1, s0) libsepol-3.8.1/tests/policies/test-hooks/module_add_role_allow_trans.conf000066400000000000000000000003251476211737200270110ustar00rootroot00000000000000module add_symbol_test 1.0; require { class file { read }; } role role_a_1; role role_a_2; role role_t_1; role role_t_2; type type_rt_1; allow role_a_1 role_a_2; role_transition role_t_1 type_rt_1 role_t_2; libsepol-3.8.1/tests/policies/test-hooks/module_add_symbols.conf000066400000000000000000000003301476211737200251270ustar00rootroot00000000000000module add_symbol_test 1.0; require { class file { read write }; } type type_add_1; attribute attrib_add_1; role role_add_1; bool bool_add_1 false; ifdef(`enable_mls',`',` user user_add_1 roles { role_add_1 }; ') libsepol-3.8.1/tests/policies/test-hooks/small-base.conf000066400000000000000000000144311476211737200233110ustar00rootroot00000000000000# FLASK # # Define the security object classes # class security class process class system class capability # file-related classes class filesystem class file class dir class fd class lnk_file class chr_file class blk_file class sock_file class fifo_file # network-related classes class socket class tcp_socket class udp_socket class rawip_socket class node class netif class netlink_socket class packet_socket class key_socket class unix_stream_socket class unix_dgram_socket # sysv-ipc-related classes class sem class msg class msgq class shm class ipc # FLASK # FLASK # # Define initial security identifiers # sid kernel # FLASK # # Define common prefixes for access vectors # # common common_name { permission_name ... } # # Define a common prefix for file access vectors. # common file { ioctl read write create getattr setattr lock relabelfrom relabelto append unlink link rename execute swapon quotaon mounton } # # Define a common prefix for socket access vectors. # common socket { # inherited from file ioctl read write create getattr setattr lock relabelfrom relabelto append # socket-specific bind connect listen accept getopt setopt shutdown recvfrom sendto recv_msg send_msg name_bind } # # Define a common prefix for ipc access vectors. # common ipc { create destroy getattr setattr read write associate unix_read unix_write } # # Define the access vectors. # # class class_name [ inherits common_name ] { permission_name ... } # # Define the access vector interpretation for file-related objects. # class filesystem { mount remount unmount getattr relabelfrom relabelto transition associate quotamod quotaget } class dir inherits file { add_name remove_name reparent search rmdir } class file inherits file { execute_no_trans entrypoint } class lnk_file inherits file class chr_file inherits file class blk_file inherits file class sock_file inherits file class fifo_file inherits file class fd { use } # # Define the access vector interpretation for network-related objects. # class socket inherits socket class tcp_socket inherits socket { connectto newconn acceptfrom } class udp_socket inherits socket class rawip_socket inherits socket class node { tcp_recv tcp_send udp_recv udp_send rawip_recv rawip_send enforce_dest } class netif { tcp_recv tcp_send udp_recv udp_send rawip_recv rawip_send } class netlink_socket inherits socket class packet_socket inherits socket class key_socket inherits socket class unix_stream_socket inherits socket { connectto newconn acceptfrom } class unix_dgram_socket inherits socket # # Define the access vector interpretation for process-related objects # class process { fork transition sigchld # commonly granted from child to parent sigkill # cannot be caught or ignored sigstop # cannot be caught or ignored signull # for kill(pid, 0) signal # all other signals ptrace getsched setsched getsession getpgid setpgid getcap setcap share } # # Define the access vector interpretation for ipc-related objects # class ipc inherits ipc class sem inherits ipc class msgq inherits ipc { enqueue } class msg { send receive } class shm inherits ipc { lock } # # Define the access vector interpretation for the security server. # class security { compute_av transition_sid member_sid sid_to_context context_to_sid load_policy get_sids change_sid get_user_sids } # # Define the access vector interpretation for system operations. # class system { ipc_info avc_toggle nfsd_control bdflush syslog_read syslog_mod syslog_console ichsid } # # Define the access vector interpretation for controlling capabilities # class capability { # The capabilities are defined in include/linux/capability.h # Care should be taken to ensure that these are consistent with # those definitions. (Order matters) chown dac_override dac_read_search fowner fsetid kill setgid setuid setpcap linux_immutable net_bind_service net_broadcast net_admin net_raw ipc_lock ipc_owner sys_module sys_rawio sys_chroot sys_ptrace sys_pacct sys_admin sys_boot sys_nice sys_resource sys_time sys_tty_config mknod lease } ifdef(`enable_mls',` sensitivity s0; # # Define the ordering of the sensitivity levels (least to greatest) # dominance { s0 } # # Define the categories # # Each category has a name and zero or more aliases. # category c0; category c1; category c2; category c3; category c4; category c5; category c6; category c7; category c8; category c9; category c10; category c11; category c12; category c13; category c14; category c15; category c16; category c17; category c18; category c19; category c20; category c21; category c22; category c23; level s0:c0.c23; mlsconstrain file { write setattr append unlink link rename ioctl lock execute relabelfrom } ( h1 dom h2 ); ') #################################### #################################### ##################################### #g_b stands for global base type g_b_type_1; role g_b_role_1 types g_b_type_1; role g_b_role_2 types g_b_type_1; role g_b_role_3 types g_b_type_1; type g_b_type_2; optional { require { type invalid_type; } allow g_b_role_2 g_b_role_3; role_transition g_b_role_2 g_b_type_2 g_b_role_3; } gen_user(g_b_user_1,, g_b_role_1, s0, s0 - s0:c0.c23) #################################### #line 1 "initial_sid_contexts" sid kernel gen_context(g_b_user_1:g_b_role_1:g_b_type_1, s0) ############################################ #line 1 "fs_use" # fs_use_xattr ext2 gen_context(g_b_user_1:object_r:g_b_type_1, s0); fs_use_xattr ext3 gen_context(g_b_user_1:object_r:g_b_type_1, s0); fs_use_xattr reiserfs gen_context(g_b_user_1:object_r:g_b_type_1, s0); genfscon proc / gen_context(g_b_user_1:object_r:g_b_type_1, s0) #################################### #line 1 "net_contexts" #portcon tcp 21 g_b_user_1:object_r:net_foo_t:s0 #netifcon lo g_b_user_1:object_r:net_foo_t g_b_user_1:object_r:net_foo_t:s0 # #nodecon 127.0.0.1 255.255.255.255 g_b_user_1:object_r:net_foo_t:s0 nodecon ::1 FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF gen_context(g_b_user_1:object_r:g_b_type_1, s0) libsepol-3.8.1/tests/policies/test-linker/000077500000000000000000000000001476211737200205605ustar00rootroot00000000000000libsepol-3.8.1/tests/policies/test-linker/module1.conf000066400000000000000000000055751476211737200230110ustar00rootroot00000000000000module linker_test_1 1.0; require { class file { read write }; class lnk_file append; role g_b_role_2; attribute g_b_attr_3; attribute g_b_attr_5; attribute o4_b_attr_1; type g_b_type_3; } type tag_g_m1; #test for type in module and attr in module, added to in module attribute g_m1_attr_1; type g_m1_type_1, g_m1_attr_1; type g_m1_type_2; typeattribute g_m1_type_2 g_m1_attr_1; #add role in module test role g_m1_role_1; role g_m1_role_1 types g_m1_type_1; # test for attr declared in base, added to in module type g_m1_type_3; typeattribute g_m1_type_3 g_b_attr_3; # test for attr declared in base, added to in 2 modules type g_m1_type_4; typeattribute g_m1_type_4 g_b_attr_5; # test for attr declared in base optional, added to in module type g_m1_type_5; typeattribute g_m1_type_5 o4_b_attr_1; # test for attr declared in module, added to in base optional attribute g_m1_attr_2; #add type to base role test role g_b_role_2 types g_m1_type_1; role g_b_role_3; role g_b_role_3 types g_m1_type_2; #add type to base optional role test role o1_b_role_2; role o1_b_role_2 types g_m1_type_1; #optional base role w/ adds in 2 modules role o4_b_role_1; role o4_b_role_1 types g_m1_type_2; # attr a added to in base optional, declared/added to in module, added to in other module attribute g_m1_attr_3; type g_m1_type_6, g_m1_attr_3; # attr a added to in base optional, declared/added in module , added to in other module optional attribute g_m1_attr_4; type g_m1_type_7, g_m1_attr_4; # alias tests typealias g_b_type_3 alias g_m_alias_1; # single boolean in module bool g_m1_bool_1 true; if (g_m1_bool_1) { allow g_m1_type_1 g_m1_type_2 : lnk_file append; } optional { require { type optional_type; attribute g_b_attr_4; attribute o1_b_attr_2; class lnk_file { ioctl }; } type tag_o1_m1; attribute o1_m1_attr_1; type o1_m1_type_2, o1_m1_attr_1; type o1_m1_type_1; role o1_m1_role_1; role o1_m1_role_1 types o1_m1_type_1; type o1_m1_type_3; typeattribute o1_m1_type_3 g_b_attr_4; type o1_m1_type_5; typeattribute o1_m1_type_5 o1_b_attr_2; bool o1_m1_bool_1 false; if (o1_m1_bool_1) { allow o1_m1_type_2 o1_m1_type_1 : lnk_file ioctl; } } optional { require { type optional_type; #role g_b_role_4; // This causes a bug where the role scope doesn't get copied into base } type tag_o2_m1; role g_b_role_4; role g_b_role_4 types g_m1_type_2; } optional { require { attribute g_b_attr_6; } type tag_o3_m1; type o3_m1_type_1; role o3_b_role_1; role o3_b_role_1 types o3_m1_type_1; type o3_m1_type_2, g_b_attr_6; attribute o3_m1_attr_1; # attr a added to in base optional, declared/added in module optional, added to in other module attribute o3_m1_attr_2; type o3_m1_type_3, o3_m1_attr_2; } optional { require { type enable_optional; } type tag_o4_m1; attribute o4_m1_attr_1; type o4_m1_type_1; typeattribute o4_m1_type_1 o4_m1_attr_1; } libsepol-3.8.1/tests/policies/test-linker/module2.conf000066400000000000000000000023651476211737200230040ustar00rootroot00000000000000module linker_test_2 1.0; require { class file { read write }; class lnk_file { unlink }; attribute g_b_attr_5; attribute g_b_attr_6; attribute g_m1_attr_3; attribute o3_m1_attr_2; } type tag_g_m2; type g_m2_type_1; role g_m2_role_1; role g_m2_role_1 types g_m2_type_1; type g_m2_type_4, g_b_attr_5; type g_m2_type_5, g_b_attr_6; #add types to role declared in base test type g_m2_type_2; role g_b_role_3; role g_b_role_3 types g_m2_type_2; #optional base role w/ adds in 2 modules role o4_b_role_1; role o4_b_role_1 types g_m2_type_1; # attr a added to in base optional, declared/added to in module, added to in other module type g_m2_type_3, g_m1_attr_3; # attr a added to in base optional, declared/added in module optional, added to in other module type g_m2_type_6, o3_m1_attr_2; # cond mapping tests bool g_m2_bool_1 true; bool g_m2_bool_2 false; if (g_m2_bool_1 && g_m2_bool_2) { allow g_m2_type_1 g_m2_type_2 : lnk_file unlink; } optional { require { type optional_type; } type tag_o1_m2; type o1_m2_type_1; role o1_m2_role_1; role o1_m2_role_1 types o1_m2_type_1; } optional { require { attribute g_m1_attr_4; attribute o4_m1_attr_1; } type tag_o2_m2; type o2_m2_type_1, g_m1_attr_4; type o2_m2_type_2, o4_m1_attr_1; } libsepol-3.8.1/tests/policies/test-linker/small-base.conf000066400000000000000000000210141476211737200234450ustar00rootroot00000000000000# FLASK # # Define the security object classes # class security class process class system class capability # file-related classes class filesystem class file class dir class fd class lnk_file class chr_file class blk_file class sock_file class fifo_file # network-related classes class socket class tcp_socket class udp_socket class rawip_socket class node class netif class netlink_socket class packet_socket class key_socket class unix_stream_socket class unix_dgram_socket # sysv-ipc-related classes class sem class msg class msgq class shm class ipc # FLASK # FLASK # # Define initial security identifiers # sid kernel # FLASK # # Define common prefixes for access vectors # # common common_name { permission_name ... } # # Define a common prefix for file access vectors. # common file { ioctl read write create getattr setattr lock relabelfrom relabelto append unlink link rename execute swapon quotaon mounton } # # Define a common prefix for socket access vectors. # common socket { # inherited from file ioctl read write create getattr setattr lock relabelfrom relabelto append # socket-specific bind connect listen accept getopt setopt shutdown recvfrom sendto recv_msg send_msg name_bind } # # Define a common prefix for ipc access vectors. # common ipc { create destroy getattr setattr read write associate unix_read unix_write } # # Define the access vectors. # # class class_name [ inherits common_name ] { permission_name ... } # # Define the access vector interpretation for file-related objects. # class filesystem { mount remount unmount getattr relabelfrom relabelto transition associate quotamod quotaget } class dir inherits file { add_name remove_name reparent search rmdir } class file inherits file { execute_no_trans entrypoint } class lnk_file inherits file class chr_file inherits file class blk_file inherits file class sock_file inherits file class fifo_file inherits file class fd { use } # # Define the access vector interpretation for network-related objects. # class socket inherits socket class tcp_socket inherits socket { connectto newconn acceptfrom } class udp_socket inherits socket class rawip_socket inherits socket class node { tcp_recv tcp_send udp_recv udp_send rawip_recv rawip_send enforce_dest } class netif { tcp_recv tcp_send udp_recv udp_send rawip_recv rawip_send } class netlink_socket inherits socket class packet_socket inherits socket class key_socket inherits socket class unix_stream_socket inherits socket { connectto newconn acceptfrom } class unix_dgram_socket inherits socket # # Define the access vector interpretation for process-related objects # class process { fork transition sigchld # commonly granted from child to parent sigkill # cannot be caught or ignored sigstop # cannot be caught or ignored signull # for kill(pid, 0) signal # all other signals ptrace getsched setsched getsession getpgid setpgid getcap setcap share } # # Define the access vector interpretation for ipc-related objects # class ipc inherits ipc class sem inherits ipc class msgq inherits ipc { enqueue } class msg { send receive } class shm inherits ipc { lock } # # Define the access vector interpretation for the security server. # class security { compute_av transition_sid member_sid sid_to_context context_to_sid load_policy get_sids change_sid get_user_sids } # # Define the access vector interpretation for system operations. # class system { ipc_info avc_toggle nfsd_control bdflush syslog_read syslog_mod syslog_console ichsid } # # Define the access vector interpretation for controlling capabilities # class capability { # The capabilities are defined in include/linux/capability.h # Care should be taken to ensure that these are consistent with # those definitions. (Order matters) chown dac_override dac_read_search fowner fsetid kill setgid setuid setpcap linux_immutable net_bind_service net_broadcast net_admin net_raw ipc_lock ipc_owner sys_module sys_rawio sys_chroot sys_ptrace sys_pacct sys_admin sys_boot sys_nice sys_resource sys_time sys_tty_config mknod lease } ifdef(`enable_mls',` sensitivity s0; # # Define the ordering of the sensitivity levels (least to greatest) # dominance { s0 } # # Define the categories # # Each category has a name and zero or more aliases. # category c0; category c1; category c2; category c3; category c4; category c5; category c6; category c7; category c8; category c9; category c10; category c11; category c12; category c13; category c14; category c15; category c16; category c17; category c18; category c19; category c20; category c21; category c22; category c23; level s0:c0.c23; mlsconstrain file { write setattr append unlink link rename ioctl lock execute relabelfrom } ( h1 dom h2 ); ') #################################### #################################### ##################################### #g_b stands for global base type enable_optional; #decorative type for finding this decl, every block should have one type tag_g_b; attribute g_b_attr_1; attribute g_b_attr_2; attribute g_b_attr_3; attribute g_b_attr_4; attribute g_b_attr_5; attribute g_b_attr_6; type g_b_type_1, g_b_attr_1; type g_b_type_2, g_b_attr_2; type g_b_type_3; role g_b_role_1; role g_b_role_2; role g_b_role_3; role g_b_role_4; role g_b_role_1 types g_b_type_1; role g_b_role_2 types g_b_type_2; role g_b_role_3 types g_b_type_2; role g_b_role_4 types g_b_type_2; bool g_b_bool_1 false; bool g_b_bool_2 true; allow g_b_type_1 g_b_type_2 : security { compute_av load_policy }; allow g_b_type_1 g_b_type_2 : file *; # test * allow g_b_type_1 g_b_type_2 : process ~ptrace; #test ~ typealias g_b_type_3 alias g_b_alias_1; if (g_b_bool_1) { allow g_b_type_1 g_b_type_2: lnk_file read; } optional { require { type enable_optional; attribute g_m1_attr_2; } type tag_o1_b; attribute o1_b_attr_1; type o1_b_type_1, o1_b_attr_1; bool o1_b_bool_1 true; role o1_b_role_1; role o1_b_role_1 types o1_b_type_1; role o1_b_role_2; role o1_b_role_2 types o1_b_type_1; attribute o1_b_attr_2; type o1_b_type_2, g_m1_attr_2; if (o1_b_bool_1) { allow o1_b_type_1 o1_b_type_2: lnk_file write; } } optional { require { # this should be activated by module 1 type g_m1_type_1; attribute o3_m1_attr_2; } type tag_o2_b; type o2_b_type_1, o3_m1_attr_2; } optional { require { #this block should not come on type invalid_type; } type tag_o3_b; attribute o3_b_attr_1; type o3_b_type_1; bool o3_b_bool_1 true; role o3_b_role_1; role o3_b_role_1 types o3_b_type_1; allow g_b_type_1 invalid_type : sem { create destroy }; } optional { require { # also should be enabled by module 1 type enable_optional; type g_m1_type_1; attribute o3_m1_attr_1; attribute g_m1_attr_3; } type tag_o4_b; attribute o4_b_attr_1; role o4_b_role_1; role o4_b_role_1 types g_m1_type_1; # test for attr declared in module optional, added to in base optional type o4_b_type_1, o3_m1_attr_1; type o4_b_type_2, g_m1_attr_3; } optional { require { attribute g_m1_attr_4; attribute o4_m1_attr_1; } type tag_o5_b; type o5_b_type_1, g_m1_attr_4; type o5_b_type_2, o4_m1_attr_1; } optional { require { type enable_optional; } type tag_o6_b; typealias g_b_type_3 alias g_b_alias_2; } optional { require { type g_m_alias_1; } type tag_o7_b; allow g_m_alias_1 enable_optional:file read; } gen_user(g_b_user_1,, g_b_role_1, s0, s0 - s0:c0.c23) gen_user(g_b_user_2,, g_b_role_1, s0, s0 - s0:c0, c1, c3, c4, c5) #################################### #line 1 "initial_sid_contexts" sid kernel gen_context(g_b_user_1:g_b_role_1:g_b_type_1, s0) ############################################ #line 1 "fs_use" # fs_use_xattr ext2 gen_context(g_b_user_1:object_r:g_b_type_1, s0); fs_use_xattr ext3 gen_context(g_b_user_1:object_r:g_b_type_1, s0); fs_use_xattr reiserfs gen_context(g_b_user_1:object_r:g_b_type_1, s0); genfscon proc / gen_context(g_b_user_1:object_r:g_b_type_1, s0) #################################### #line 1 "net_contexts" #portcon tcp 21 g_b_user_1:object_r:net_foo_t:s0 #netifcon lo g_b_user_1:object_r:net_foo_t g_b_user_1:object_r:net_foo_t:s0 # #nodecon 127.0.0.1 255.255.255.255 g_b_user_1:object_r:net_foo_t:s0 nodecon ::1 FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF gen_context(g_b_user_1:object_r:g_b_type_1, s0) libsepol-3.8.1/tests/policies/test-neverallow/000077500000000000000000000000001476211737200214525ustar00rootroot00000000000000libsepol-3.8.1/tests/policies/test-neverallow/policy.conf000066400000000000000000000172431476211737200236270ustar00rootroot00000000000000class process class blk_file class chr_file class dir class fifo_file class file class lnk_file class sock_file sid kernel sid security sid unlabeled sid file sid port sid netif sid netmsg sid node sid devnull class process { dyntransition transition } class file { getattr ioctl open read write } ifdef(`enable_mls',` sensitivity s0; dominance { s0 } category c0; category c1; category c2; category c3; category c4; category c5; category c6; category c7; category c8; category c9; category c10; category c11; category c12; category c13; category c14; category c15; category c16; category c17; category c18; category c19; category c20; category c21; category c22; category c23; level s0:c0.c23; mlsconstrain file { write } ( h1 dom h2 ); ') ######################################## # # Test start # ######################################## ## Test 1 (basic) type test1_t; allow test1_t test1_t : file { read write }; neverallow test1_t test1_t : file read; ## Test 2 (wildcard permission) type test2_t; allow test2_t test2_t : file { read write }; neverallow test2_t test2_t : file *; ## Test 3 (complement permission) type test3_t; allow test3_t test3_t : file { read write }; neverallow test3_t test3_t : file ~{ write }; ## Test 4 (wildcard source) type test4_t; allow test4_t test4_t : file { read write }; neverallow * test4_t : file read; ## Test 5 (wildcard target) type test5_t; allow test5_t test5_t : file { read write }; neverallow test5_t * : file read; ## Test 6 (complement source) type test6_1_t; type test6_2_t; allow { test6_1_t test6_2_t } { test6_1_t test6_2_t } : file { read write }; neverallow ~{ test6_2_t } test6_1_t : file read; ## Test 7 (complement target) type test7_1_t; type test7_2_t; allow { test7_1_t test7_2_t } { test7_1_t test7_2_t } : file { read write }; neverallow test7_1_t ~{ test7_2_t } : file read; ## Test 8 (source attribute) attribute test8_a; type test8_t, test8_a; allow test8_a test8_a : file read; allow test8_t test8_t : file write; neverallow test8_a test8_t : file { read write }; ## Test 9 (target attribute) attribute test9_a; type test9_t, test9_a; allow test9_a test9_a : file read; allow test9_t test9_t : file write; neverallow test9_t test9_a : file { read write }; ## Test 10 (self) attribute test10_a; type test10_1_t, test10_a; type test10_2_t; allow { test10_1_t test10_2_t } { test10_1_t test10_2_t } : file read; neverallow test10_a self : file *; ## Test 11 (wildcard) type test11_t; allow test11_t self : process *; neverallow * * : process *; ## Test 12 (complement attributes) attribute test12_1_a; attribute test12_2_a; attribute test12_3_a; type test12_1_t, test12_1_a; type test12_2_t, test12_2_a; type test12_3_t, test12_3_a; allow { test12_1_a test12_2_a test12_3_a } { test12_1_a test12_2_a test12_3_a } : file *; neverallow ~{ test12_1_a test12_2_t } ~{ test12_3_a } : file getattr; neverallow ~{ test12_1_a } ~{ test12_2_a test12_3_t } : file open; ## Test 13 (excludes) attribute test13_1_a; attribute test13_2_a; attribute test13_3_a; type test13_1_t, test13_1_a; type test13_2_t, test13_2_a; type test13_3_t, test13_3_a; allow { test13_1_a test13_2_a test13_3_a } { test13_1_a test13_2_a test13_3_a } : file { read write }; neverallow { test13_1_a test13_2_a test13_3_a -test13_2_a -test13_3_t } { test13_1_a test13_2_a test13_3_a -test13_2_t -test13_3_a } : file read; ## Test 14 (misc avrules) type test14_t; auditallow test14_t test14_t : file read; dontaudit test14_t test14_t : file write; neverallow test14_t test14_t : file { read write }; type_transition test14_t test14_t : file test14_t; type_transition test14_t test14_t : file test14_t "objname"; neverallow test14_t test14_t : file *; # nofail ## Test 15 (extended permissions - standard allow) type test15_t; allow test15_t self : file ioctl; neverallowxperm test15_t self : file ioctl 0x1111; ## Test 16 (extended permissions - allowxperm) type test16_t; allow test16_t self : file ioctl; allowxperm test16_t self : file ioctl 0x1111; neverallowxperm test16_t self : file ioctl 0x1111; ## Test 17 (extended permissions - allowxperm mismatch) type test17_t; allow test17_t self : file ioctl; allowxperm test17_t self : file ioctl 0x1111; neverallowxperm test17_t self : file ioctl 0x2222; # nofail ## Test 18 (extended permissions - allowxperm range I) type test18_t; allow test18_t self : file ioctl; allowxperm test18_t self : file ioctl { 0x1100-0x1300 }; neverallowxperm test18_t self : file ioctl 0x1111; ## Test 19 (extended permissions - allowxperm range II) type test19_t; allow test19_t self : file ioctl; allowxperm test19_t self : file ioctl 0x1111; neverallowxperm test19_t self : file ioctl { 0x1100-0x1300 }; ## Test 20 (extended permissions - misc targets I) attribute test20_a; type test20_t, test20_a; allow test20_a test20_a : file ioctl; allowxperm test20_a test20_a : file ioctl 0x1111; neverallowxperm test20_a self : file ioctl 0x1111; ## Test 21 (extended permissions - misc targets II) attribute test21_1_a; attribute test21_2_a; type test21_t, test21_1_a, test21_2_a; allow test21_1_a test21_1_a : file ioctl; allowxperm test21_1_a test21_2_a : file ioctl 0x1111; neverallowxperm test21_1_a self : file ioctl 0x1111; ## Test 22 (extended permissions - misc targets III) attribute test22_a; type test22_t, test22_a; allow test22_a test22_a : file ioctl; allowxperm test22_t self : file ioctl 0x1111; neverallowxperm test22_a self : file ioctl 0x1111; ## Test 23 (extended permissions - misc targets IV) attribute test23_a; type test23_t, test23_a; allow test23_a test23_a : file ioctl; allowxperm test23_t test23_t : file ioctl 0x1111; neverallowxperm test23_a self : file ioctl 0x1111; ## Test 24 (extended permissions - misc targets V) attribute test24_a; type test24_t, test24_a; allow test24_a test24_a : file ioctl; allowxperm test24_t test24_a : file ioctl 0x1111; neverallowxperm test24_a self : file ioctl 0x1111; ## Test 25 (extended permissions - misc targets VI) attribute test25_a; type test25_t, test25_a; allow test25_a test25_a : file ioctl; allowxperm test25_a self : file ioctl 0x1111; neverallowxperm test25_a self : file ioctl 0x1111; ## Test 26 (extended permissions - assert twice) attribute test26_a; type test26_1_t, test26_a; type test26_2_t, test26_a; allow test26_a test26_a : file ioctl; allowxperm test26_a test26_a : file ioctl 0x1111; neverallowxperm test26_1_t test26_a : file ioctl 0x1111; ######################################## # # Test End # ######################################## type sys_isid; role sys_role; role sys_role types sys_isid; gen_user(sys_user,, sys_role, s0, s0 - s0:c0.c23) sid kernel gen_context(sys_user:sys_role:sys_isid, s0) sid security gen_context(sys_user:sys_role:sys_isid, s0) sid unlabeled gen_context(sys_user:sys_role:sys_isid, s0) sid file gen_context(sys_user:sys_role:sys_isid, s0) sid port gen_context(sys_user:sys_role:sys_isid, s0) sid netif gen_context(sys_user:sys_role:sys_isid, s0) sid netmsg gen_context(sys_user:sys_role:sys_isid, s0) sid node gen_context(sys_user:sys_role:sys_isid, s0) sid devnull gen_context(sys_user:sys_role:sys_isid, s0) fs_use_trans devpts gen_context(sys_user:sys_role:sys_isid, s0); fs_use_trans devtmpfs gen_context(sys_user:sys_role:sys_isid, s0); libsepol-3.8.1/tests/policies/test-neverallow/policy_cond.conf000066400000000000000000000127301476211737200246260ustar00rootroot00000000000000class process class blk_file class chr_file class dir class fifo_file class file class lnk_file class sock_file sid kernel sid security sid unlabeled sid file sid port sid netif sid netmsg sid node sid devnull class process { dyntransition transition } class file { getattr ioctl open read write } bool boolean1 false; bool boolean2 true; ifdef(`enable_mls',` sensitivity s0; dominance { s0 } category c0; category c1; category c2; category c3; category c4; category c5; category c6; category c7; category c8; category c9; category c10; category c11; category c12; category c13; category c14; category c15; category c16; category c17; category c18; category c19; category c20; category c21; category c22; category c23; level s0:c0.c23; mlsconstrain file { write } ( h1 dom h2 ); ') ######################################## # # Test start # ######################################## ## Test 1 (basic - fail) type test1_t; if boolean1 { allow test1_t self : file read; } neverallow test1_t * : file *; ## Test 2 (basic - fail) attribute test2_a; type test2_1_t, test2_a; type test2_2_t; if !boolean1 { allow test2_1_t test2_1_t : file write; allow test2_2_t test2_2_t : file write; } neverallow test2_a * : file *; ## Test 3 (xperm - no xperm in one branch - fail) type test3_t; if boolean1 { allow test3_t self : file ioctl; } else { allowxperm test3_t self : file ioctl 0x1; } neverallowxperm test3_t self : file ioctl 0x4; ## Test 4 (xperm - xperm in neither branch - fail) type test4_t; allow test4_t self : file ioctl; if boolean1 { allow test4_t self : file read; } else { allow test4_t self : file write; } neverallowxperm test4_t self : file ioctl 0x4; ## Test 5 (xperm - xperm in both branches - no failure) type test5_t; allow test5_t self : file ioctl; if boolean1 { allowxperm test5_t self : file ioctl 0x1; } else { allowxperm test5_t self : file ioctl 0x2; } neverallowxperm test5_t self : file ioctl 0x4; # nofail ## Test 6 (xperm - failure in one branch - fail) type test6_t; if boolean1 { allow test6_t self : file ioctl; allowxperm test6_t self : file ioctl 0x1; } else { allow test6_t self : file write; } neverallowxperm test6_t self : file ioctl 0x1; ## Test 7 (xperm - failure in both branches - fail) type test7_t; if boolean1 { allow test7_t self : file ioctl; allowxperm test7_t self : file ioctl 0x1; } else { allow test7_t self : file ioctl; allowxperm test7_t self : file ioctl 0x2; } neverallowxperm test7_t self : file ioctl { 0x1-0x2 }; ## Test 8 (xperm - different xperm in both branches - no failure) type test8_t; allow test8_t self : file ioctl; if boolean1 { allowxperm test8_t self : file ioctl 0x1; } else { allowxperm test8_t self : file ioctl 0x2; } neverallowxperm test8_t self : file ioctl 0x3; # nofail ## Test 9 (xperm - rules split into two booleans - no failure) type test9_t; allow test9_t self : file ioctl; if boolean1 { allowxperm test9_t self : file ioctl 0x1; } if !boolean2 { allowxperm test9_t self : file ioctl 0x1; } neverallowxperm test9_t self : file ioctl 0x4; ## Test 10 (xperm - valid usage in one branch - no failure) type test10_t; if boolean1 { allow test10_t self : file ioctl; allowxperm test10_t self : file ioctl 0x1; } else { allow test10_t self : file write; } neverallowxperm test10_t self : file ioctl 0x2; # nofail ## Test 11 (xperm - valid usage in both branches - no failure) type test11_t; if boolean1 { allow test11_t self : file ioctl; allowxperm test11_t self : file ioctl 0x1; } else { allow test11_t self : file ioctl; allowxperm test11_t self : file ioctl 0x2; } neverallowxperm test11_t self : file ioctl 0x3; # nofail ## Test 12 (xperm - base allow in one branch - fail) type test12_t; if boolean1 { allow test12_t self : file ioctl; } else { allow test12_t self : file write; } neverallowxperm test12_t self : file ioctl 0x1; ## Test 13 (xperm - invalid second branch - fail) type test13_t; allow test13_t self : file ioctl; if boolean1 { allow test13_t self : file ioctl; allowxperm test13_t self : file ioctl 0x1; } else { allow test13_t self : file write; } neverallowxperm test13_t self : file ioctl 0x1; ## Test 14 (xperm - invalid second branch - fail) type test14_t; allow test14_t self : file ioctl; if boolean1 { allow test14_t self : file ioctl; allowxperm test14_t self : file ioctl 0x1; } else { allow test14_t self : file write; } neverallowxperm test14_t self : file ioctl 0x2; ## Test 15 (xperm - base uncond in one branch - fail) type test15_t; allow test15_t self : file ioctl; allowxperm test15_t self : file ioctl 0x1; if boolean1 { allow test15_t self : file ioctl; } else { allow test15_t self : file write; } neverallowxperm test15_t self : file ioctl 0x2; ######################################## # # Test End # ######################################## type sys_isid; role sys_role; role sys_role types sys_isid; gen_user(sys_user,, sys_role, s0, s0 - s0:c0.c23) sid kernel gen_context(sys_user:sys_role:sys_isid, s0) sid security gen_context(sys_user:sys_role:sys_isid, s0) sid unlabeled gen_context(sys_user:sys_role:sys_isid, s0) sid file gen_context(sys_user:sys_role:sys_isid, s0) sid port gen_context(sys_user:sys_role:sys_isid, s0) sid netif gen_context(sys_user:sys_role:sys_isid, s0) sid netmsg gen_context(sys_user:sys_role:sys_isid, s0) sid node gen_context(sys_user:sys_role:sys_isid, s0) sid devnull gen_context(sys_user:sys_role:sys_isid, s0) fs_use_trans devpts gen_context(sys_user:sys_role:sys_isid, s0); fs_use_trans devtmpfs gen_context(sys_user:sys_role:sys_isid, s0); libsepol-3.8.1/tests/policies/test-neverallow/policy_minus_self.conf000066400000000000000000000255621476211737200260560ustar00rootroot00000000000000class process class blk_file class chr_file class dir class fifo_file class file class lnk_file class sock_file class class5 class class6 class class7 class class17 sid kernel sid security sid unlabeled sid file sid port sid netif sid netmsg sid node sid devnull class process { dyntransition transition } class file { ioctl read write } class class5 { perm } class class6 { perm } class class7 { perm } class class17 { ioctl } ifdef(`enable_mls',` sensitivity s0; dominance { s0 } category c0; category c1; category c2; category c3; category c4; category c5; category c6; category c7; category c8; category c9; category c10; category c11; category c12; category c13; category c14; category c15; category c16; category c17; category c18; category c19; category c20; category c21; category c22; category c23; level s0:c0.c23; mlsconstrain file { write } ( h1 dom h2 ); ') ######################################## # # Test start # ######################################## ## Test 1 (single type) type test1_t; allow test1_t test1_t : file read; neverallow test1_t { test1_t -self } : file read; # nofail ## Test 2 (single type) type test2_t; allow test2_t self : file read; neverallow test2_t { test1_t -self } : file read; # nofail ## Test 3 (single type) type test3_1_t; type test3_2_t; allow test3_1_t test3_2_t : file read; neverallow test3_1_t { test3_2_t -self } : file read; ## Test 4 (two types I) type test4_1_t; type test4_2_t; allow { test4_1_t test4_2_t } { test4_1_t test4_2_t } : file read; neverallow test4_1_t { test4_1_t test4_2_t -self } : file read; ## Test 5 (two types II) type test5_1_t; type test5_2_t; allow { test5_1_t test5_2_t } { test5_1_t test5_2_t } : class5 perm; neverallow * { test5_1_t test5_2_t -self } : class5 perm; ## Test 6 (two types III) type test6_1_t; type test6_2_t; allow { test6_1_t test6_2_t } { test6_1_t test6_2_t } : class6 perm; neverallow * { test6_2_t -self } : class6 perm; ## Test 7 (two types IV) type test7_1_t; type test7_2_t; allow { test7_1_t test7_2_t } test7_2_t : class7 perm; neverallow * { test7_1_t -self } : class7 perm; # nofail ## Test 8 (attribute violates type I) attribute test8_a; type test8_1_t, test8_a; type test8_2_t, test8_a; allow test8_a test8_a : file read; neverallow test8_1_t { test8_a -self } : file *; ## Test 9 (attribute violates type II) attribute test9_a; type test9_1_t, test9_a; type test9_2_t, test9_a; allow test9_1_t test9_a : file read; neverallow test9_1_t { test9_a -self } : file *; ## Test 10 (attribute violates type III) attribute test10_1_a; attribute test10_2_a; type test10_1_t, test10_1_a, test10_1_a; type test10_2_t, test10_1_a, test10_1_a; allow test10_1_a test10_1_a : file read; neverallow test10_1_t { test10_2_a -self } : file *; ## Test 11 (attribute violates attribute I) attribute test11_1_a; attribute test11_2_a; type test11_1_t, test11_1_a, test11_2_a; type test11_2_t, test11_1_a, test11_2_a; allow test11_1_t self : file read; allow test11_2_t test11_2_t : file read; neverallow test11_1_a { test11_2_a -self } : file *; # nofail ## Test 12 (attribute violates attribute II) attribute test12_a; type test12_1_t, test12_a; type test12_2_t, test12_a; allow test12_1_t test12_2_t : file read; neverallow test12_a { test12_a -self } : file *; ## Test 13 (attribute violates attribute III) attribute test13_a; type test13_1_t, test13_a; type test13_2_t, test13_a; allow test13_1_t test13_a : file read; neverallow test13_a { test13_a -self } : file *; ## Test 14 (attribute violates attribute IV) attribute test14_a; type test14_1_t, test14_a; type test14_2_t, test14_a; allow test14_a test14_a : file read; neverallow test14_a { test14_a -self } : file *; # ## Test 15 (attribute violates attribute V) attribute test13_1_a; attribute test13_2_a; type test13_t, test13_1_a, test13_2_a; allow test13_1_a test13_2_a : file read; neverallow test13_a { test13_2_a -self } : file *; ## Test 16 (types violate attribute) attribute test16_a; type test16_1_t, test16_a; type test16_2_t, test16_a; allow { test16_1_t test16_2_t } { test16_1_t test16_2_t } : file read; neverallow test16_a { test16_a -self } : file ~write; ## Test 17 (extended permissions I) type test17_1_t; type test17_2_t; allow { test17_1_t test17_2_t } { test17_1_t test17_2_t } : class17 ioctl; neverallowxperm ~test17_2_t { test17_1_t test17_2_t -self } : class17 ioctl 0x1111; ## Test 18 (extended permissions II) type test18_1_t; type test18_2_t; allow { test18_1_t test18_2_t } { test18_1_t test18_2_t } : file ioctl; allowxperm { test18_1_t test18_2_t } { test18_1_t test18_2_t } : file ioctl 0x1111; neverallowxperm { test18_1_t test18_2_t } { test18_1_t test18_2_t -self } : file ioctl 0x2222; # nofail ## Test 19 (extended permissions III) type test19_1_t; type test19_2_t; allow { test19_1_t test19_2_t } { test19_1_t test19_2_t } : file ioctl; allowxperm { test19_1_t test19_2_t } { test19_1_t test19_2_t } : file ioctl { 0x0100 - 0x0102 }; neverallowxperm test19_2_t { test19_1_t test19_2_t -self } : file ioctl { 0x0101 - 0x0104 }; ## Test 20 (extended permissions IV) type test20_1_t; type test20_2_t; allow { test20_1_t test20_2_t } { test20_1_t test20_2_t } : file ioctl; allowxperm test20_1_t test20_1_t : file ioctl 0x0101; allowxperm test20_1_t test20_2_t : file ioctl 0x0102; allowxperm test20_2_t test20_1_t : file ioctl 0x0103; allowxperm test20_2_t test20_2_t : file ioctl 0x0104; neverallowxperm { test20_1_t test20_2_t } { test20_1_t test20_2_t -self } : file ioctl { 0x0000 - 0x9000 }; ## Test 21 (extended permissions V) attribute test21_a; type test21_1_t, test21_a; type test21_2_t, test21_a; allow test21_a test21_a : file ioctl; allowxperm test21_a test21_a : file ioctl 0x9501; neverallowxperm test21_1_t { test21_a -self } : file ioctl 0x9511; # nofail ## Test 22 (extended permissions VI) type test22_t; allow test22_t self : file ioctl; allowxperm test22_t self : file ioctl 0x9501; allowxperm test22_t self : file ioctl 0x9511; neverallowxperm test22_t { test22_t -self } : file ioctl 0x9511; # nofail ## Test 23 (extended permissions VII) attribute test23_a; type test23_1_t, test23_a; type test23_2_t, test23_a; allow test23_a test23_a : file ioctl; allowxperm test23_a test23_a : file ioctl 0x9501; allowxperm test23_1_t test23_2_t : file ioctl 0x9511; neverallowxperm test23_1_t { test23_a -self } : file ioctl 0x9511; ## Test 24 (extended permissions VII) attribute test24_a; type test24_1_t, test24_a; type test24_2_t, test24_a; allow test24_a test24_a : file ioctl; allowxperm test24_a test24_a : file ioctl 0x9501; allowxperm test24_1_t test24_a : file ioctl 0x9511; neverallowxperm test24_1_t { test24_a -self } : file ioctl 0x9511; ## Test 25 (extended permissions IX) attribute test25_a; type test25_1_t, test25_a; type test25_2_t, test25_a; allow test25_a test25_a : file ioctl; allowxperm test25_a test25_a : file ioctl 0x9501; allowxperm test25_a test25_a : file ioctl 0x9511; neverallowxperm test25_1_t { test25_a -self } : file ioctl 0x9511; ## Test 26 (extended permissions X) attribute test26_1_a; attribute test26_2_a; type test26_1_t, test26_1_a, test26_2_a; type test26_2_t, test26_1_a, test26_2_a; allow { test26_1_a test26_2_a } { test26_1_a test26_2_a } : file ioctl; allowxperm { test26_1_a test26_2_a } { test26_1_a test26_2_a } : file ioctl 0x9501; allowxperm test26_1_a test26_2_a : file ioctl 0x9511; neverallowxperm test26_1_t { test26_2_a -self } : file ioctl 0x9511; # ## Test 27 (extended permissions attribute violation I) attribute test27_a; type test27_1_t, test27_a; type test27_2_t, test27_a; allow test27_a test27_a : file ioctl; allowxperm test27_a test27_a : file ioctl 0x9501; allowxperm test27_1_t self : file ioctl 0x9521; allowxperm test27_2_t test27_2_t : file ioctl 0x9521; neverallowxperm test27_a { test27_a -self } : file ioctl 0x9521; # nofail # ## Test 28 (extended permissions attribute violation II) attribute test28_a; type test28_1_t, test28_a; type test28_2_t, test28_a; allow test28_a test28_a : file ioctl; allowxperm test28_1_t test28_2_t : file ioctl 0x9521; neverallowxperm test28_a { test28_a -self } : file ioctl 0x9521; ## Test 29 (extended permissions attribute violation III) attribute test29_a; type test29_1_t, test29_a; type test29_2_t, test29_a; allow test29_a test29_a : file ioctl; allowxperm test29_1_t test29_a : file ioctl 0x9521; neverallowxperm test29_a { test29_a -self } : file ioctl 0x9521; ## Test 30 (extended permissions attribute violation IV) attribute test30_a; type test30_1_t, test30_a; type test30_2_t, test30_a; allow test30_a test30_a : file ioctl; allowxperm test30_a test30_a : file ioctl 0x9521; neverallowxperm test30_a { test30_a -self } : file ioctl 0x9521; ## Test 31 (extended permissions attribute violation V) attribute test31_1_a; attribute test31_2_a; type test31_1_t, test31_1_a, test31_2_a; type test31_2_t, test31_1_a, test31_2_a; allow test31_1_a test31_1_a : file ioctl; allowxperm test31_1_a test31_2_a : file ioctl 0x9521; neverallowxperm test31_1_a { test31_2_a -self } : file ioctl 0x9521; ######################################## # # Test End # ######################################## type sys_isid; role sys_role; role sys_role types sys_isid; gen_user(sys_user,, sys_role, s0, s0 - s0:c0.c23) sid kernel gen_context(sys_user:sys_role:sys_isid, s0) sid security gen_context(sys_user:sys_role:sys_isid, s0) sid unlabeled gen_context(sys_user:sys_role:sys_isid, s0) sid file gen_context(sys_user:sys_role:sys_isid, s0) sid port gen_context(sys_user:sys_role:sys_isid, s0) sid netif gen_context(sys_user:sys_role:sys_isid, s0) sid netmsg gen_context(sys_user:sys_role:sys_isid, s0) sid node gen_context(sys_user:sys_role:sys_isid, s0) sid devnull gen_context(sys_user:sys_role:sys_isid, s0) fs_use_trans devpts gen_context(sys_user:sys_role:sys_isid, s0); fs_use_trans devtmpfs gen_context(sys_user:sys_role:sys_isid, s0); libsepol-3.8.1/tests/policies/test-neverallow/policy_not_self.conf000066400000000000000000000243471476211737200255230ustar00rootroot00000000000000class process class blk_file class chr_file class dir class fifo_file class file class lnk_file class sock_file class class5 class class6 class class7 class class17 sid kernel sid security sid unlabeled sid file sid port sid netif sid netmsg sid node sid devnull class process { dyntransition transition } class file { ioctl read write } class class5 { perm } class class6 { perm } class class7 { perm } class class17 { ioctl } ifdef(`enable_mls',` sensitivity s0; dominance { s0 } category c0; category c1; category c2; category c3; category c4; category c5; category c6; category c7; category c8; category c9; category c10; category c11; category c12; category c13; category c14; category c15; category c16; category c17; category c18; category c19; category c20; category c21; category c22; category c23; level s0:c0.c23; mlsconstrain file { write } ( h1 dom h2 ); ') ######################################## # # Test start # ######################################## ## Test 1 (single type) type test1_t; allow test1_t test1_t : file read; neverallow test1_t ~self : file read; # nofail ## Test 2 (single type) type test2_t; allow test2_t self : file read; neverallow test2_t ~self : file read; # nofail ## Test 3 (single type) type test3_1_t; type test3_2_t; allow test3_1_t test3_2_t : file read; neverallow test3_1_t ~self : file read; ## Test 4 (two types I) type test4_1_t; type test4_2_t; allow { test4_1_t test4_2_t } { test4_1_t test4_2_t } : file read; neverallow test4_1_t ~self : file read; ## Test 5 (two types II) type test5_1_t; type test5_2_t; allow { test5_1_t test5_2_t } { test5_1_t test5_2_t } : class5 perm; neverallow * ~self : class5 perm; ## Test 6 (two types III) type test6_1_t; type test6_2_t; allow { test6_1_t test6_2_t } { test6_1_t test6_2_t } : class6 perm; neverallow * ~{ self test6_1_t } : class6 perm; ## Test 7 (two types IV) type test7_1_t; type test7_2_t; allow { test7_1_t test7_2_t } { test7_1_t test7_2_t } : class7 perm; neverallow * ~{ self test7_1_t test7_2_t } : class7 perm; # nofail ## Test 8 (attribute violates type I) attribute test8_a; type test8_1_t, test8_a; type test8_2_t, test8_a; allow test8_a test8_a : file read; neverallow test8_1_t ~self : file *; ## Test 9 (attribute violates type II) attribute test9_a; type test9_1_t, test9_a; type test9_2_t, test9_a; allow test9_1_t test9_a : file read; neverallow test9_1_t ~self : file *; ## Test 10 (attribute violates type III) attribute test10_1_a; attribute test10_2_a; type test10_1_t, test10_1_a, test10_1_a; type test10_2_t, test10_1_a, test10_1_a; allow test10_1_a test10_1_a : file read; neverallow test10_1_t ~self : file *; ## Test 11 (attribute violates attribute I) attribute test11_1_a; attribute test11_2_a; type test11_1_t, test11_1_a, test11_2_a; type test11_2_t, test11_1_a, test11_2_a; allow test11_1_t self : file read; allow test11_2_t test11_2_t : file read; neverallow test11_1_a ~self : file *; # nofail ## Test 12 (attribute violates attribute II) attribute test12_a; type test12_1_t, test12_a; type test12_2_t, test12_a; allow test12_1_t test12_2_t : file read; neverallow test12_a ~self : file *; ## Test 13 (attribute violates attribute III) attribute test13_a; type test13_1_t, test13_a; type test13_2_t, test13_a; allow test13_1_t test13_a : file read; neverallow test13_a ~self : file *; ## Test 14 (attribute violates attribute IV) attribute test14_a; type test14_1_t, test14_a; type test14_2_t, test14_a; allow test14_a test14_a : file read; neverallow test14_a ~self : file *; ## Test 15 (attribute violates attribute V) attribute test13_1_a; attribute test13_2_a; type test13_t, test13_1_a, test13_2_a; allow test13_1_a test13_2_a : file read; neverallow test13_a ~self : file *; ## Test 16 (types violate attribute) attribute test16_a; type test16_1_t, test16_a; type test16_2_t, test16_a; allow { test16_1_t test16_2_t } { test16_1_t test16_2_t } : file read; neverallow test16_a ~self : file ~write; ## Test 17 (extended permissions I) type test17_1_t; type test17_2_t; allow { test17_1_t test17_2_t } { test17_1_t test17_2_t } : class17 ioctl; neverallowxperm ~test17_2_t ~self : class17 ioctl 0x1111; ## Test 18 (extended permissions II) type test18_1_t; type test18_2_t; allow { test18_1_t test18_2_t } { test18_1_t test18_2_t } : file ioctl; allowxperm { test18_1_t test18_2_t } { test18_1_t test18_2_t } : file ioctl 0x1111; neverallowxperm test18_1_t ~self : file ioctl 0x2222; # nofail ## Test 19 (extended permissions III) type test19_1_t; type test19_2_t; allow { test19_1_t test19_2_t } { test19_1_t test19_2_t } : file ioctl; allowxperm { test19_1_t test19_2_t } { test19_1_t test19_2_t } : file ioctl { 0x0100 - 0x0102 }; neverallowxperm test19_2_t ~self : file ioctl { 0x0101 - 0x0104 }; ## Test 20 (extended permissions IV) type test20_1_t; type test20_2_t; allow { test20_1_t test20_2_t } { test20_1_t test20_2_t } : file ioctl; allowxperm test20_1_t test20_1_t : file ioctl 0x0101; allowxperm test20_1_t test20_2_t : file ioctl 0x0102; allowxperm test20_2_t test20_1_t : file ioctl 0x0103; allowxperm test20_2_t test20_2_t : file ioctl 0x0104; neverallowxperm { test20_1_t test20_2_t } ~self : file ioctl { 0x0000 - 0x9000 }; ## Test 21 (extended permissions V) attribute test21_a; type test21_1_t, test21_a; type test21_2_t, test21_a; allow test21_a test21_a : file ioctl; allowxperm test21_a test21_a : file ioctl 0x9501; neverallowxperm test21_1_t ~self : file ioctl 0x9511; # nofail ## Test 22 (extended permissions VI) type test22_t; allow test22_t self : file ioctl; allowxperm test22_t self : file ioctl 0x9501; allowxperm test22_t self : file ioctl 0x9511; neverallowxperm test22_t ~self : file ioctl 0x9511; # nofail ## Test 23 (extended permissions VII) attribute test23_a; type test23_1_t, test23_a; type test23_2_t, test23_a; allow test23_a test23_a : file ioctl; allowxperm test23_a test23_a : file ioctl 0x9501; allowxperm test23_1_t test23_2_t : file ioctl 0x9511; neverallowxperm test23_1_t ~self : file ioctl 0x9511; ## Test 24 (extended permissions VII) attribute test24_a; type test24_1_t, test24_a; type test24_2_t, test24_a; allow test24_a test24_a : file ioctl; allowxperm test24_a test24_a : file ioctl 0x9501; allowxperm test24_1_t test24_a : file ioctl 0x9511; neverallowxperm test24_1_t ~self : file ioctl 0x9511; ## Test 25 (extended permissions IX) attribute test25_a; type test25_1_t, test25_a; type test25_2_t, test25_a; allow test25_a test25_a : file ioctl; allowxperm test25_a test25_a : file ioctl 0x9501; allowxperm test25_a test25_a : file ioctl 0x9511; neverallowxperm test25_1_t ~self : file ioctl 0x9511; ## Test 26 (extended permissions X) attribute test26_1_a; attribute test26_2_a; type test26_1_t, test26_1_a, test26_2_a; type test26_2_t, test26_1_a, test26_2_a; allow { test26_1_a test26_2_a } { test26_1_a test26_2_a } : file ioctl; allowxperm { test26_1_a test26_2_a } { test26_1_a test26_2_a } : file ioctl 0x9501; allowxperm test26_1_a test26_2_a : file ioctl 0x9511; neverallowxperm test26_1_t ~self : file ioctl 0x9511; ## Test 27 (extended permissions attribute violation I) attribute test27_a; type test27_1_t, test27_a; type test27_2_t, test27_a; allow test27_a test27_a : file ioctl; allowxperm test27_a test27_a : file ioctl 0x9501; allowxperm test27_1_t self : file ioctl 0x9521; allowxperm test27_2_t test27_2_t : file ioctl 0x9521; neverallowxperm test27_a ~self : file ioctl 0x9521; # nofail ## Test 28 (extended permissions attribute violation II) attribute test28_a; type test28_1_t, test28_a; type test28_2_t, test28_a; allow test28_a test28_a : file ioctl; allowxperm test28_1_t test28_2_t : file ioctl 0x9521; neverallowxperm test28_a ~self : file ioctl 0x9521; ## Test 29 (extended permissions attribute violation III) attribute test29_a; type test29_1_t, test29_a; type test29_2_t, test29_a; allow test29_a test29_a : file ioctl; allowxperm test29_1_t test29_a : file ioctl 0x9521; neverallowxperm test29_a ~self : file ioctl 0x9521; ## Test 30 (extended permissions attribute violation IV) attribute test30_a; type test30_1_t, test30_a; type test30_2_t, test30_a; allow test30_a test30_a : file ioctl; allowxperm test30_a test30_a : file ioctl 0x9521; neverallowxperm test30_a ~self : file ioctl 0x9521; ## Test 31 (extended permissions attribute violation V) attribute test31_1_a; attribute test31_2_a; type test31_1_t, test31_1_a, test31_2_a; type test31_2_t, test31_1_a, test31_2_a; allow test31_1_a test31_1_a : file ioctl; allowxperm test31_1_a test31_2_a : file ioctl 0x9521; neverallowxperm test31_1_a ~self : file ioctl 0x9521; ######################################## # # Test End # ######################################## type sys_isid; role sys_role; role sys_role types sys_isid; gen_user(sys_user,, sys_role, s0, s0 - s0:c0.c23) sid kernel gen_context(sys_user:sys_role:sys_isid, s0) sid security gen_context(sys_user:sys_role:sys_isid, s0) sid unlabeled gen_context(sys_user:sys_role:sys_isid, s0) sid file gen_context(sys_user:sys_role:sys_isid, s0) sid port gen_context(sys_user:sys_role:sys_isid, s0) sid netif gen_context(sys_user:sys_role:sys_isid, s0) sid netmsg gen_context(sys_user:sys_role:sys_isid, s0) sid node gen_context(sys_user:sys_role:sys_isid, s0) sid devnull gen_context(sys_user:sys_role:sys_isid, s0) fs_use_trans devpts gen_context(sys_user:sys_role:sys_isid, s0); fs_use_trans devtmpfs gen_context(sys_user:sys_role:sys_isid, s0); libsepol-3.8.1/tests/test-common.c000066400000000000000000000170761476211737200171340ustar00rootroot00000000000000/* * Author: Joshua Brindle * Chad Sellers * Chris PeBenito * * Copyright (C) 2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* This has tests that are common between test suites*/ #include #include #include "test-common.h" #include "helpers.h" void test_sym_presence(policydb_t * p, const char *id, int sym_type, unsigned int scope_type, unsigned int *decls, unsigned int len) { scope_datum_t *scope; int found; unsigned int i, j; /* make sure it is in global symtab */ if (!hashtab_search(p->symtab[sym_type].table, id)) { fprintf(stderr, "symbol %s not found in table %d\n", id, sym_type); CU_FAIL_FATAL(); } /* make sure its scope is correct */ scope = hashtab_search(p->scope[sym_type].table, id); CU_ASSERT_FATAL(scope != NULL); CU_ASSERT(scope->scope == scope_type); CU_ASSERT(scope->decl_ids_len == len); if (scope->decl_ids_len != len) fprintf(stderr, "sym %s has %d decls, %d expected\n", id, scope->decl_ids_len, len); for (i = 0; i < len; i++) { found = 0; for (j = 0; j < len; j++) { if (decls[i] == scope->decl_ids[j]) found++; } CU_ASSERT(found == 1); } } static int common_test_index(hashtab_key_t key, hashtab_datum_t datum, void *data) { common_datum_t *d = (common_datum_t *) datum; policydb_t *p = (policydb_t *) data; CU_ASSERT(p->sym_val_to_name[SYM_COMMONS][d->s.value - 1] == (char *)key); return 0; } static int class_test_index(hashtab_key_t key, hashtab_datum_t datum, void *data) { class_datum_t *d = (class_datum_t *) datum; policydb_t *p = (policydb_t *) data; CU_ASSERT(p->sym_val_to_name[SYM_CLASSES][d->s.value - 1] == (char *)key); CU_ASSERT(p->class_val_to_struct[d->s.value - 1] == d); return 0; } static int role_test_index(hashtab_key_t key, hashtab_datum_t datum, void *data) { role_datum_t *d = (role_datum_t *) datum; policydb_t *p = (policydb_t *) data; CU_ASSERT(p->sym_val_to_name[SYM_ROLES][d->s.value - 1] == (char *)key); CU_ASSERT(p->role_val_to_struct[d->s.value - 1] == d); return 0; } static int type_test_index(hashtab_key_t key, hashtab_datum_t datum, void *data) { type_datum_t *d = (type_datum_t *) datum; policydb_t *p = (policydb_t *) data; if (!d->primary) return 0; CU_ASSERT(p->sym_val_to_name[SYM_TYPES][d->s.value - 1] == (char *)key); CU_ASSERT(p->type_val_to_struct[d->s.value - 1] == d); return 0; } static int user_test_index(hashtab_key_t key, hashtab_datum_t datum, void *data) { user_datum_t *d = (user_datum_t *) datum; policydb_t *p = (policydb_t *) data; CU_ASSERT(p->sym_val_to_name[SYM_USERS][d->s.value - 1] == (char *)key); CU_ASSERT(p->user_val_to_struct[d->s.value - 1] == d); return 0; } static int cond_test_index(hashtab_key_t key, hashtab_datum_t datum, void *data) { cond_bool_datum_t *d = (cond_bool_datum_t *) datum; policydb_t *p = (policydb_t *) data; CU_ASSERT(p->sym_val_to_name[SYM_BOOLS][d->s.value - 1] == (char *)key); CU_ASSERT(p->bool_val_to_struct[d->s.value - 1] == d); return 0; } static int level_test_index(hashtab_key_t key, hashtab_datum_t datum, void *data) { level_datum_t *d = (level_datum_t *) datum; policydb_t *p = (policydb_t *) data; CU_ASSERT(p->sym_val_to_name[SYM_LEVELS][d->level->sens - 1] == (char *)key); return 0; } static int cat_test_index(hashtab_key_t key, hashtab_datum_t datum, void *data) { cat_datum_t *d = (cat_datum_t *) datum; policydb_t *p = (policydb_t *) data; CU_ASSERT(p->sym_val_to_name[SYM_CATS][d->s.value - 1] == (char *)key); return 0; } static int (*test_index_f[SYM_NUM]) (hashtab_key_t key, hashtab_datum_t datum, void *p) = { common_test_index, class_test_index, role_test_index, type_test_index, user_test_index, cond_test_index, level_test_index, cat_test_index,}; void test_policydb_indexes(policydb_t * p) { int i; for (i = 0; i < SYM_NUM; i++) { hashtab_map(p->symtab[i].table, test_index_f[i], p); } } void test_alias_datum(policydb_t * p, const char *id, const char *primary_id, char mode, unsigned int flavor) { type_datum_t *type, *primary; unsigned int my_primary, my_flavor, my_value; type = hashtab_search(p->p_types.table, id); primary = hashtab_search(p->p_types.table, primary_id); CU_ASSERT_PTR_NOT_NULL(type); CU_ASSERT_PTR_NOT_NULL(primary); if (type && primary) { if (mode) { my_flavor = type->flavor; } else { my_flavor = flavor; } if (my_flavor == TYPE_TYPE) { my_primary = 0; my_value = primary->s.value; } else { CU_ASSERT(my_flavor == TYPE_ALIAS); my_primary = primary->s.value; CU_ASSERT_NOT_EQUAL(type->s.value, primary->s.value); my_value = type->s.value; } CU_ASSERT(type->primary == my_primary); CU_ASSERT(type->flavor == my_flavor); CU_ASSERT(type->s.value == my_value); } } role_datum_t *test_role_type_set(policydb_t * p, const char *id, avrule_decl_t * decl, const char **types, unsigned int len, unsigned int flags) { ebitmap_node_t *tnode; unsigned int i, j, new, found = 0; role_datum_t *role; if (decl) role = hashtab_search(decl->p_roles.table, id); else role = hashtab_search(p->p_roles.table, id); if (!role) printf("role %s can't be found! \n", id); CU_ASSERT_FATAL(role != NULL); ebitmap_for_each_positive_bit(&role->types.types, tnode, i) { new = 0; for (j = 0; j < len; j++) { if (strcmp(p->sym_val_to_name[SYM_TYPES][i], types[j]) == 0) { found++; new = 1; } } if (new == 0) { printf("\nRole %s had type %s not in types array\n", id, p->sym_val_to_name[SYM_TYPES][i]); } CU_ASSERT(new == 1); } CU_ASSERT(found == len); if (found != len) printf("\nrole %s has %d types, %d expected\n", p->sym_val_to_name[SYM_ROLES][role->s.value - 1], found, len); /* roles should never have anything in the negset */ CU_ASSERT(role->types.negset.highbit == 0); CU_ASSERT(role->types.flags == flags); return role; } void test_attr_types(policydb_t * p, const char *id, avrule_decl_t * decl, const char **types, int len) { ebitmap_node_t *tnode; int j, new, found = 0; unsigned int i; type_datum_t *attr; if (decl) { attr = hashtab_search(decl->p_types.table, id); if (attr == NULL) printf("could not find attr %s in decl %d\n", id, decl->decl_id); } else { attr = hashtab_search(p->p_types.table, id); if (attr == NULL) printf("could not find attr %s in policy\n", id); } CU_ASSERT_FATAL(attr != NULL); CU_ASSERT(attr->flavor == TYPE_ATTRIB); CU_ASSERT(attr->primary == 1); ebitmap_for_each_positive_bit(&attr->types, tnode, i) { new = 0; for (j = 0; j < len; j++) { if (strcmp(p->sym_val_to_name[SYM_TYPES][i], types[j]) == 0) { found++; new = 1; } } if (new == 0) { printf("\nattr %s had type %s not in types array\n", id, p->sym_val_to_name[SYM_TYPES][i]); } CU_ASSERT(new == 1); } CU_ASSERT(found == len); if (found != len) printf("\nattr %s has %d types, %d expected\n", id, found, len); } libsepol-3.8.1/tests/test-common.h000066400000000000000000000066641476211737200171420ustar00rootroot00000000000000/* * Author: Joshua Brindle * Chad Sellers * * Copyright (C) 2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __TEST_COMMON_H__ #define __TEST_COMMON_H__ #include /* p the policy being inspected * id string symbol identifier * sym_type symbol type (eg., SYM_ROLES, SYM_TYPES) * scope_type what scope the role should have (eg., SCOPE_DECL or SCOPE_REQ) * decls integer array of decl id's that we expect the role to have in the scope table * len number of elements in decls * * This is a utility function to test for the symbol's presence in the global symbol table, * the scope table, and that the decl blocks we think this symbol is in are correct */ extern void test_sym_presence(policydb_t * p, const char *id, int sym_type, unsigned int scope_type, unsigned int *decls, unsigned int len); /* Test the indexes in the policydb to ensure their correctness. These include * the sym_val_to_name[], class_val_to_struct, role_val_to_struct, type_val_to_struct, * user_val_to_struct, and bool_val_to_struct indexes. */ extern void test_policydb_indexes(policydb_t * p); /* Test alias datum to ensure that it is as expected * * id = the key for the alias * primary_id = the key for its primary * mode: 0 = test the datum according to the flavor value in the call 1 = automatically detect the flavor value and test the datum accordingly * flavor = flavor value if in mode 0 */ extern void test_alias_datum(policydb_t * p, const char *id, const char *primary_id, char mode, unsigned int flavor); /* p the policy being inspected * id string role identifier * decl the decl block which we are looking in for the role datum * types the array of string types which we expect the role has in its type ebitmap * len number of elements in types * flags the expected flags in the role typeset (eg., * or ~) * * This is a utility function to test whether the type set associated with a role in a specific * avrule decl block matches our expectations */ extern role_datum_t *test_role_type_set(policydb_t * p, const char *id, avrule_decl_t * decl, const char **types, unsigned int len, unsigned int flags); /* p the policy being inspected * id string attribute identifier * decl the decl block which we are looking in for the attribute datum * types the array of string types which we expect the attribute has in its type ebitmap * len number of elements in types * * This is a utility function to test whether the type set associated with an attribute in a specific * avrule decl block matches our expectations */ extern void test_attr_types(policydb_t * p, const char *id, avrule_decl_t * decl, const char **types, int len); #endif libsepol-3.8.1/tests/test-cond.c000066400000000000000000000043751476211737200165650ustar00rootroot00000000000000/* * Author: Karl MacMillan * * Copyright (C) 2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "test-cond.h" #include "parse_util.h" #include "helpers.h" #include #include #include #include static policydb_t basemod; static policydb_t base_expanded; int cond_test_init(void) { if (policydb_init(&base_expanded)) { fprintf(stderr, "out of memory!\n"); policydb_destroy(&basemod); return -1; } if (test_load_policy(&basemod, POLICY_BASE, 1, "test-cond", "refpolicy-base.conf")) goto cleanup; if (link_modules(NULL, &basemod, NULL, 0, 0)) { fprintf(stderr, "link modules failed\n"); goto cleanup; } if (expand_module(NULL, &basemod, &base_expanded, 0, 1)) { fprintf(stderr, "expand module failed\n"); goto cleanup; } return 0; cleanup: policydb_destroy(&basemod); policydb_destroy(&base_expanded); return -1; } int cond_test_cleanup(void) { policydb_destroy(&basemod); policydb_destroy(&base_expanded); return 0; } static void test_cond_expr_equal(void) { cond_node_t *a, *b; a = base_expanded.cond_list; while (a) { b = base_expanded.cond_list; while (b) { if (a == b) { CU_ASSERT(cond_expr_equal(a, b)); } else { CU_ASSERT(cond_expr_equal(a, b) == 0); } b = b->next; } a = a->next; } } int cond_add_tests(CU_pSuite suite) { if (NULL == CU_add_test(suite, "cond_expr_equal", test_cond_expr_equal)) { return CU_get_error(); } return 0; } libsepol-3.8.1/tests/test-cond.h000066400000000000000000000020101476211737200165520ustar00rootroot00000000000000/* * Author: Karl MacMillan * * Copyright (C) 2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __TEST_COND_H__ #define __TEST_COND_H__ #include int cond_test_init(void); int cond_test_cleanup(void); int cond_add_tests(CU_pSuite suite); #endif libsepol-3.8.1/tests/test-deps.c000066400000000000000000000240761476211737200165750ustar00rootroot00000000000000/* * Author: Karl MacMillan * * Copyright (C) 2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "test-deps.h" #include "parse_util.h" #include "helpers.h" #include #include #include /* Tests for dependency checking / handling, specifically: * * 1 type in module global. * 2 attribute in module global. * 3 object class / perm in module global. * 4 boolean in module global. * 5 role in module global. * * 6 type in module optional. * 7 attribute in module optional. * 8 object class / perm in module optional. * 9 boolean in module optional. * 10 role in module optional. * * 11 type in base optional. * 12 attribute in base optional. * 13 object class / perm in base optional. * 14 boolean in base optional. * 15 role in base optional. * * Each of these tests are done with the dependency met and not * met. Additionally, each of the required symbols is used in the * scope it is required. * * In addition to the simple tests, we have test with more complex * modules that test: * * 17 mutual dependencies between two modules. * 18 circular dependency between three modules. * 19 large number of dependencies in a module with a more complex base. * 20 nested optionals with requires. * * Again, each of these tests is done with the requirements met and not * met. */ #include #include #include "helpers.h" #define BASE_MODREQ_TYPE_GLOBAL 0 #define BASE_MODREQ_ATTR_GLOBAL 1 #define BASE_MODREQ_OBJ_GLOBAL 2 #define BASE_MODREQ_BOOL_GLOBAL 3 #define BASE_MODREQ_ROLE_GLOBAL 4 #define BASE_MODREQ_PERM_GLOBAL 5 #define BASE_MODREQ_TYPE_OPT 6 #define BASE_MODREQ_ATTR_OPT 7 #define BASE_MODREQ_OBJ_OPT 8 #define BASE_MODREQ_BOOL_OPT 9 #define BASE_MODREQ_ROLE_OPT 10 #define BASE_MODREQ_PERM_OPT 11 #define NUM_BASES 12 static policydb_t bases_met[NUM_BASES]; static policydb_t bases_notmet[NUM_BASES]; extern int mls; int deps_test_init(void) { int i; /* To test linking we need 1 base per link test and in * order to load them in the init function we have * to keep them all around. Not ideal, but it shouldn't * matter too much. */ for (i = 0; i < NUM_BASES; i++) { if (test_load_policy(&bases_met[i], POLICY_BASE, mls, "test-deps", "base-metreq.conf")) return -1; } for (i = 0; i < NUM_BASES; i++) { if (test_load_policy(&bases_notmet[i], POLICY_BASE, mls, "test-deps", "base-notmetreq.conf")) return -1; } return 0; } int deps_test_cleanup(void) { int i; for (i = 0; i < NUM_BASES; i++) { policydb_destroy(&bases_met[i]); } for (i = 0; i < NUM_BASES; i++) { policydb_destroy(&bases_notmet[i]); } return 0; } /* This function performs testing of the dependency handles for module global * symbols. It is capable of testing 2 scenarios - the dependencies are met * and the dependencies are not met. * * Parameters: * req_met boolean indicating whether the base policy meets the * requirements for the modules global block. * b index of the base policy in the global bases_met array. * * policy name of the policy module to load for this test. * decl_type name of the unique type found in the module's global * section is to find that avrule_decl. */ static void do_deps_modreq_global(int req_met, int b, const char *policy, const char *decl_type) { policydb_t *base; policydb_t mod; policydb_t *mods[] = { &mod }; avrule_decl_t *decl; int ret, link_ret; sepol_handle_t *h; /* suppress error reporting - this is because we know that we * are going to get errors and don't want libsepol complaining * about it constantly. */ h = sepol_handle_create(); CU_ASSERT_FATAL(h != NULL); sepol_msg_set_callback(h, NULL, NULL); if (req_met) { base = &bases_met[b]; link_ret = 0; } else { base = &bases_notmet[b]; link_ret = -3; } CU_ASSERT_FATAL(test_load_policy(&mod, POLICY_MOD, mls, "test-deps", policy) == 0); /* link the modules and check for the correct return value. */ ret = link_modules(h, base, mods, 1, 0); CU_ASSERT_FATAL(ret == link_ret); policydb_destroy(&mod); sepol_handle_destroy(h); if (!req_met) return; decl = test_find_decl_by_sym(base, SYM_TYPES, decl_type); CU_ASSERT_FATAL(decl != NULL); CU_ASSERT(decl->enabled == 1); } /* Test that symbol require statements in the global scope of a module * work correctly. This will cover tests 1 - 5 (described above). * * Each of these policies will require as few symbols as possible to * use the required symbol in addition requiring (for example, the type * test also requires an object class for an allow rule). */ static void deps_modreq_global(void) { /* object classes */ do_deps_modreq_global(1, BASE_MODREQ_OBJ_GLOBAL, "modreq-obj-global.conf", "mod_global_t"); do_deps_modreq_global(0, BASE_MODREQ_OBJ_GLOBAL, "modreq-obj-global.conf", "mod_global_t"); /* types */ do_deps_modreq_global(1, BASE_MODREQ_TYPE_GLOBAL, "modreq-type-global.conf", "mod_global_t"); do_deps_modreq_global(0, BASE_MODREQ_TYPE_GLOBAL, "modreq-type-global.conf", "mod_global_t"); /* attributes */ do_deps_modreq_global(1, BASE_MODREQ_ATTR_GLOBAL, "modreq-attr-global.conf", "mod_global_t"); do_deps_modreq_global(0, BASE_MODREQ_ATTR_GLOBAL, "modreq-attr-global.conf", "mod_global_t"); /* booleans */ do_deps_modreq_global(1, BASE_MODREQ_BOOL_GLOBAL, "modreq-bool-global.conf", "mod_global_t"); do_deps_modreq_global(0, BASE_MODREQ_BOOL_GLOBAL, "modreq-bool-global.conf", "mod_global_t"); /* roles */ do_deps_modreq_global(1, BASE_MODREQ_ROLE_GLOBAL, "modreq-role-global.conf", "mod_global_t"); do_deps_modreq_global(0, BASE_MODREQ_ROLE_GLOBAL, "modreq-role-global.conf", "mod_global_t"); do_deps_modreq_global(1, BASE_MODREQ_PERM_GLOBAL, "modreq-perm-global.conf", "mod_global_t"); do_deps_modreq_global(0, BASE_MODREQ_PERM_GLOBAL, "modreq-perm-global.conf", "mod_global_t"); } /* This function performs testing of the dependency handles for module optional * symbols. It is capable of testing 2 scenarios - the dependencies are met * and the dependencies are not met. * * Parameters: * req_met boolean indicating whether the base policy meets the * requirements for the modules global block. * b index of the base policy in the global bases_met array. * * policy name of the policy module to load for this test. * decl_type name of the unique type found in the module's global * section is to find that avrule_decl. */ static void do_deps_modreq_opt(int req_met, int ret_val, int b, const char *policy, const char *decl_type) { policydb_t *base; policydb_t mod; policydb_t *mods[] = { &mod }; avrule_decl_t *decl; int ret; sepol_handle_t *h; /* suppress error reporting - this is because we know that we * are going to get errors and don't want libsepol complaining * about it constantly. */ h = sepol_handle_create(); CU_ASSERT_FATAL(h != NULL); sepol_msg_set_callback(h, NULL, NULL); if (req_met) { base = &bases_met[b]; } else { base = &bases_notmet[b]; } CU_ASSERT_FATAL(test_load_policy(&mod, POLICY_MOD, mls, "test-deps", policy) == 0); /* link the modules and check for the correct return value. */ ret = link_modules(h, base, mods, 1, 0); CU_ASSERT_FATAL(ret == ret_val); policydb_destroy(&mod); sepol_handle_destroy(h); if (ret_val < 0) return; decl = test_find_decl_by_sym(base, SYM_TYPES, decl_type); CU_ASSERT_FATAL(decl != NULL); if (req_met) { CU_ASSERT(decl->enabled == 1); } else { CU_ASSERT(decl->enabled == 0); } } /* Test that symbol require statements in the global scope of a module * work correctly. This will cover tests 6 - 10 (described above). * * Each of these policies will require as few symbols as possible to * use the required symbol in addition requiring (for example, the type * test also requires an object class for an allow rule). */ static void deps_modreq_opt(void) { /* object classes */ do_deps_modreq_opt(1, 0, BASE_MODREQ_OBJ_OPT, "modreq-obj-opt.conf", "mod_opt_t"); do_deps_modreq_opt(0, 0, BASE_MODREQ_OBJ_OPT, "modreq-obj-opt.conf", "mod_opt_t"); /* types */ do_deps_modreq_opt(1, 0, BASE_MODREQ_TYPE_OPT, "modreq-type-opt.conf", "mod_opt_t"); do_deps_modreq_opt(0, 0, BASE_MODREQ_TYPE_OPT, "modreq-type-opt.conf", "mod_opt_t"); /* attributes */ do_deps_modreq_opt(1, 0, BASE_MODREQ_ATTR_OPT, "modreq-attr-opt.conf", "mod_opt_t"); do_deps_modreq_opt(0, 0, BASE_MODREQ_ATTR_OPT, "modreq-attr-opt.conf", "mod_opt_t"); /* booleans */ do_deps_modreq_opt(1, 0, BASE_MODREQ_BOOL_OPT, "modreq-bool-opt.conf", "mod_opt_t"); do_deps_modreq_opt(0, 0, BASE_MODREQ_BOOL_OPT, "modreq-bool-opt.conf", "mod_opt_t"); /* roles */ do_deps_modreq_opt(1, 0, BASE_MODREQ_ROLE_OPT, "modreq-role-opt.conf", "mod_opt_t"); do_deps_modreq_opt(0, 0, BASE_MODREQ_ROLE_OPT, "modreq-role-opt.conf", "mod_opt_t"); /* permissions */ do_deps_modreq_opt(1, 0, BASE_MODREQ_PERM_OPT, "modreq-perm-opt.conf", "mod_opt_t"); do_deps_modreq_opt(0, -3, BASE_MODREQ_PERM_OPT, "modreq-perm-opt.conf", "mod_opt_t"); } int deps_add_tests(CU_pSuite suite) { if (NULL == CU_add_test(suite, "deps_modreq_global", deps_modreq_global)) { return CU_get_error(); } if (NULL == CU_add_test(suite, "deps_modreq_opt", deps_modreq_opt)) { return CU_get_error(); } return 0; } libsepol-3.8.1/tests/test-deps.h000066400000000000000000000020101476211737200165620ustar00rootroot00000000000000/* * Author: Karl MacMillan * * Copyright (C) 2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __TEST_DEPS_H__ #define __TEST_DEPS_H__ #include int deps_test_init(void); int deps_test_cleanup(void); int deps_add_tests(CU_pSuite suite); #endif libsepol-3.8.1/tests/test-downgrade.c000066400000000000000000000157721476211737200176170ustar00rootroot00000000000000/* * Author: Mary Garvin * * Copyright (C) 2007-2008 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "test-downgrade.h" #include "parse_util.h" #include "helpers.h" #include #include #include #include #include #include #include #include #define POLICY_BIN_HI "policies/test-downgrade/policy.hi" #define POLICY_BIN_LO "policies/test-downgrade/policy.lo" static policydb_t policydb; /* * Function Name: downgrade_test_init * * Input: None * * Output: None * * Description: Initialize the policydb (policy data base structure) */ int downgrade_test_init(void) { /* Initialize the policydb_t structure */ if (policydb_init(&policydb)) { fprintf(stderr, "%s: Out of memory!\n", __FUNCTION__); return -1; } return 0; } /* * Function Name: downgrade_test_cleanup * * Input: None * * Output: None * * Description: Destroys policydb structure */ int downgrade_test_cleanup(void) { policydb_destroy(&policydb); return 0; } /* * Function Name: downgrade_add_tests * * Input: CU_pSuite * * Output: Returns 0 upon success. Returns a CUnit error value on failure. * * Description: Add the given downgrade tests to the downgrade suite. */ int downgrade_add_tests(CU_pSuite suite) { if (CU_add_test(suite, "downgrade", test_downgrade) == NULL) return CU_get_error(); return 0; } /* * Function Name: test_downgrade_possible * * Input: None * * Output: None * * Description: * Tests the backward compatibility of MLS and Non-MLS binary policy versions. */ void test_downgrade(void) { if (do_downgrade_test(0) < 0) fprintf(stderr, "\nError during downgrade testing of Non-MLS policy\n"); if (do_downgrade_test(1) < 0) fprintf(stderr, "\nError during downgrade testing of MLS policy\n"); } /* * Function Name: do_downgrade_test * * Input: 0 for Non-MLS policy and 1 for MLS policy downgrade testing * * Output: 0 on success, negative number upon failure * * Description: This function handles the downgrade testing. * A binary policy is read into the policydb structure, the * policy version is decreased by a specific amount, written * back out and then read back in again. The process is * repeated until the minimum policy version is reached. */ int do_downgrade_test(int mls) { policydb_t policydb_tmp; int hi, lo, version; /* Reset policydb for re-use */ policydb_destroy(&policydb); downgrade_test_init(); /* Read in the hi policy from file */ if (read_binary_policy(POLICY_BIN_HI, &policydb) != 0) { fprintf(stderr, "error reading %spolicy binary\n", mls ? "mls " : ""); CU_FAIL("Unable to read the binary policy"); return -1; } /* Change MLS value based on parameter */ policydb.mls = mls ? 1 : 0; for (hi = policydb.policyvers; hi >= POLICYDB_VERSION_MIN; hi--) { /* Stash old version number */ version = policydb.policyvers; /* Try downgrading to each possible version. */ for (lo = hi - 1; lo >= POLICYDB_VERSION_MIN; lo--) { /* Reduce policy version */ policydb.policyvers = lo; /* Write out modified binary policy */ if (write_binary_policy(POLICY_BIN_LO, &policydb) != 0) { /* * Error from MLS to pre-MLS is expected due * to MLS re-implementation in version 19. */ if (mls && lo < POLICYDB_VERSION_MLS) continue; fprintf(stderr, "error writing %spolicy binary, version %d (downgraded from %d)\n", mls ? "mls " : "", lo, hi); CU_FAIL("Failed to write downgraded binary policy"); return -1; } /* Make sure we can read back what we wrote. */ if (policydb_init(&policydb_tmp)) { fprintf(stderr, "%s: Out of memory!\n", __FUNCTION__); return -1; } if (read_binary_policy(POLICY_BIN_LO, &policydb_tmp) != 0) { fprintf(stderr, "error reading %spolicy binary, version %d (downgraded from %d)\n", mls ? "mls " : "", lo, hi); CU_FAIL("Unable to read downgraded binary policy"); return -1; } policydb_destroy(&policydb_tmp); } /* Restore version number */ policydb.policyvers = version; } return 0; } /* * Function Name: read_binary_policy * * Input: char * which is the path to the file containing the binary policy * * Output: Returns 0 upon success. Upon failure, -1 is returned. * Possible failures are, filename with given path does not exist, * a failure to open the file, or a failure from prolicydb_read * function call. * * Description: Get a filename, open file and read binary policy into policydb * structure. */ int read_binary_policy(const char *path, policydb_t *p) { FILE *in_fp = NULL; struct policy_file f; int rc; /* Open the binary policy file */ if ((in_fp = fopen(path, "rb")) == NULL) { fprintf(stderr, "Unable to open %s: %s\n", path, strerror(errno)); return -1; } /* Read in the binary policy. */ memset(&f, 0, sizeof(struct policy_file)); f.type = PF_USE_STDIO; f.fp = in_fp; rc = policydb_read(p, &f, 0); fclose(in_fp); return rc; } /* * Function Name: write_binary_policy * * Input: char * which is the path to the file containing the binary policy * * Output: Returns 0 upon success. Upon failure, -1 is returned. * Possible failures are, filename with given path does not exist, * a failure to open the file, or a failure from prolicydb_read * function call. * * Description: open file and write the binary policy from policydb structure. */ int write_binary_policy(const char *path, policydb_t *p) { FILE *out_fp = NULL; struct policy_file f; sepol_handle_t *handle; int rc; /* We don't want libsepol to print warnings to stderr */ handle = sepol_handle_create(); if (handle == NULL) { fprintf(stderr, "Out of memory!\n"); return -1; } sepol_msg_set_callback(handle, NULL, NULL); /* Open the binary policy file for writing */ if ((out_fp = fopen(path, "w" )) == NULL) { fprintf(stderr, "Unable to open %s: %s\n", path, strerror(errno)); sepol_handle_destroy(handle); return -1; } /* Write the binary policy */ memset(&f, 0, sizeof(struct policy_file)); f.type = PF_USE_STDIO; f.fp = out_fp; f.handle = handle; rc = policydb_write(p, &f); sepol_handle_destroy(f.handle); fclose(out_fp); return rc; } libsepol-3.8.1/tests/test-downgrade.h000066400000000000000000000065601476211737200176170ustar00rootroot00000000000000/* * Author: Mary Garvin * * Copyright (C) 2007-2008 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __TEST_DOWNGRADE_H__ #define __TEST_DOWNGRADE_H__ #include #include /* * Function Name: downgrade_test_init * * Input: None * * Output: None * * Description: Initialize the policydb (policy data base structure) */ int downgrade_test_init(void); /* * Function Name: downgrade_test_cleanup * * Input: None * * Output: None * * Description: Destroys policydb structure */ int downgrade_test_cleanup(void); /* * Function Name: downgrade_add_tests * * Input: CU_pSuite * * Output: Returns 0 upon success. Upon failure, a CUnit testing error * value is returned * * Description: Add the given downgrade tests to the downgrade suite. */ int downgrade_add_tests(CU_pSuite suite); /* * Function Name: test_downgrade_possible * * Input: None * * Output: None * * Description: Tests the backward compatibility of MLS and Non-MLS binary * policy versions. */ void test_downgrade(void); /* * Function Name: do_downgrade_test * * Input: int that represents a 0 for Non-MLS policy and a * 1 for MLS policy downgrade testing * * Output: (int) 0 on success, negative number upon failure * * Description: This function handles the downgrade testing. A binary policy * is read into the policydb structure, the policy version is * decreased by a specific amount, written back out and then read * back in again. The process is iterative until the minimum * policy version is reached. */ int do_downgrade_test(int mls); /* * Function Name: read_binary_policy * * Input: char * which is the path to the file containing the binary policy * * Output: Returns 0 upon success. Upon failure, -1 is returned. * Possible failures are, filename with given path does not exist, * a failure to open the file, or a failure from prolicydb_read * function call. * * Description: Get a filename, open file and read in the binary policy * into the policydb structure. */ int read_binary_policy(const char *path, policydb_t *); /* * Function Name: write_binary_policy * * Input: char * which is the path to the file containing the binary policy * * Output: Returns 0 upon success. Upon failure, -1 is returned. * Possible failures are, filename with given path does not exist, * a failure to open the file, or a failure from prolicydb_read * function call. * * Description: Get a filename, open file and read in the binary policy * into the policydb structure. */ int write_binary_policy(const char *path, policydb_t *); #endif libsepol-3.8.1/tests/test-ebitmap.c000066400000000000000000000654301476211737200172620ustar00rootroot00000000000000#include "test-ebitmap.h" #include #include #include #include #define RANDOM_ROUNDS 10 static int ebitmap_init_random(ebitmap_t *e, unsigned int length, int set_chance) { unsigned int i; int rc; if (set_chance <= 0 || set_chance > 100) return -EINVAL; ebitmap_init(e); for (i = 0; i < length; i++) { if ((random() % 100) < set_chance) { rc = ebitmap_set_bit(e, i, 1); if (rc) return rc; } } return 0; } static void test_ebitmap_init_destroy(void) { ebitmap_t e; /* verify idempotence */ ebitmap_init(&e); ebitmap_init(&e); ebitmap_init(&e); CU_ASSERT(ebitmap_is_empty(&e)); CU_ASSERT_PTR_NULL(ebitmap_startnode(&e)); /* verify idempotence */ ebitmap_destroy(&e); ebitmap_destroy(&e); ebitmap_destroy(&e); CU_ASSERT(ebitmap_is_empty(&e)); CU_ASSERT_PTR_NULL(ebitmap_startnode(&e)); } static void test_ebitmap_cmp(void) { ebitmap_t e1, e2; ebitmap_init(&e1); ebitmap_init(&e2); CU_ASSERT(ebitmap_cmp(&e1, &e2)); CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 10, 1), 0); CU_ASSERT_FALSE(ebitmap_cmp(&e1, &e2)); CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 10, 1), 0); CU_ASSERT(ebitmap_cmp(&e1, &e2)); CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 63, 1), 0); CU_ASSERT_FALSE(ebitmap_cmp(&e1, &e2)); CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 63, 1), 0); CU_ASSERT(ebitmap_cmp(&e1, &e2)); CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 64, 1), 0); CU_ASSERT_FALSE(ebitmap_cmp(&e1, &e2)); CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 64, 1), 0); CU_ASSERT(ebitmap_cmp(&e1, &e2)); CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 1022, 1), 0); CU_ASSERT_FALSE(ebitmap_cmp(&e1, &e2)); CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 1022, 1), 0); CU_ASSERT(ebitmap_cmp(&e1, &e2)); CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 1023, 1), 0); CU_ASSERT_FALSE(ebitmap_cmp(&e1, &e2)); CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 1023, 1), 0); CU_ASSERT(ebitmap_cmp(&e1, &e2)); CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 1024, 1), 0); CU_ASSERT_FALSE(ebitmap_cmp(&e1, &e2)); CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 1024, 1), 0); CU_ASSERT(ebitmap_cmp(&e1, &e2)); CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 1025, 1), 0); CU_ASSERT_FALSE(ebitmap_cmp(&e1, &e2)); CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 1025, 1), 0); CU_ASSERT(ebitmap_cmp(&e1, &e2)); CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 255, 1), 0); CU_ASSERT_FALSE(ebitmap_cmp(&e1, &e2)); CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 255, 1), 0); CU_ASSERT(ebitmap_cmp(&e1, &e2)); CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 256, 1), 0); CU_ASSERT_FALSE(ebitmap_cmp(&e1, &e2)); CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 256, 1), 0); CU_ASSERT(ebitmap_cmp(&e1, &e2)); CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 639, 1), 0); CU_ASSERT_FALSE(ebitmap_cmp(&e1, &e2)); CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 639, 1), 0); CU_ASSERT(ebitmap_cmp(&e1, &e2)); CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 640, 1), 0); CU_ASSERT_FALSE(ebitmap_cmp(&e1, &e2)); CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 640, 1), 0); CU_ASSERT(ebitmap_cmp(&e1, &e2)); CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 900, 1), 0); CU_ASSERT_FALSE(ebitmap_cmp(&e1, &e2)); CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 900, 1), 0); CU_ASSERT(ebitmap_cmp(&e1, &e2)); ebitmap_destroy(&e2); CU_ASSERT_FALSE(ebitmap_cmp(&e1, &e2)); ebitmap_destroy(&e1); CU_ASSERT(ebitmap_cmp(&e1, &e2)); } static void test_ebitmap_set_and_get(void) { ebitmap_t e; ebitmap_init(&e); CU_ASSERT(ebitmap_is_empty(&e)); CU_ASSERT_TRUE(ebitmap_is_empty(&e)); CU_ASSERT_EQUAL(ebitmap_cardinality(&e), 0); CU_ASSERT_EQUAL(ebitmap_highest_set_bit(&e), 0); CU_ASSERT_EQUAL(ebitmap_get_bit(&e, 10), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e, UINT32_MAX, 1), -EINVAL); CU_ASSERT_EQUAL(ebitmap_set_bit(&e, 10, 0), 0); CU_ASSERT(ebitmap_is_empty(&e)); CU_ASSERT_EQUAL(ebitmap_cardinality(&e), 0); CU_ASSERT_EQUAL(ebitmap_highest_set_bit(&e), 0); CU_ASSERT_EQUAL(ebitmap_get_bit(&e, 10), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e, 10, 1), 0); CU_ASSERT_FALSE(ebitmap_is_empty(&e)); CU_ASSERT_EQUAL(ebitmap_cardinality(&e), 1); CU_ASSERT_EQUAL(ebitmap_highest_set_bit(&e), 10); CU_ASSERT_EQUAL(ebitmap_get_bit(&e, 10), 1); CU_ASSERT_EQUAL(ebitmap_set_bit(&e, 100, 1), 0); CU_ASSERT_FALSE(ebitmap_is_empty(&e)); CU_ASSERT_EQUAL(ebitmap_cardinality(&e), 2); CU_ASSERT_EQUAL(ebitmap_highest_set_bit(&e), 100); CU_ASSERT_EQUAL(ebitmap_get_bit(&e, 100), 1); CU_ASSERT_EQUAL(ebitmap_set_bit(&e, 50, 1), 0); CU_ASSERT_FALSE(ebitmap_is_empty(&e)); CU_ASSERT_EQUAL(ebitmap_cardinality(&e), 3); CU_ASSERT_EQUAL(ebitmap_highest_set_bit(&e), 100); CU_ASSERT_EQUAL(ebitmap_get_bit(&e, 50), 1); CU_ASSERT_EQUAL(ebitmap_set_bit(&e, 1023, 1), 0); CU_ASSERT_FALSE(ebitmap_is_empty(&e)); CU_ASSERT_EQUAL(ebitmap_cardinality(&e), 4); CU_ASSERT_EQUAL(ebitmap_highest_set_bit(&e), 1023); CU_ASSERT_EQUAL(ebitmap_get_bit(&e, 1023), 1); CU_ASSERT_EQUAL(ebitmap_set_bit(&e, 1024, 1), 0); CU_ASSERT_FALSE(ebitmap_is_empty(&e)); CU_ASSERT_EQUAL(ebitmap_cardinality(&e), 5); CU_ASSERT_EQUAL(ebitmap_highest_set_bit(&e), 1024); CU_ASSERT_EQUAL(ebitmap_get_bit(&e, 1024), 1); CU_ASSERT_EQUAL(ebitmap_set_bit(&e, 1050, 1), 0); CU_ASSERT_FALSE(ebitmap_is_empty(&e)); CU_ASSERT_EQUAL(ebitmap_cardinality(&e), 6); CU_ASSERT_EQUAL(ebitmap_highest_set_bit(&e), 1050); CU_ASSERT_EQUAL(ebitmap_get_bit(&e, 1050), 1); { ebitmap_node_t *n; unsigned int bit, count; /* iterate all allocated bits */ count = 0; ebitmap_for_each_bit(&e, n, bit) { CU_ASSERT( bit < 64 || (64 <= bit && bit < 128) || (960 <= bit && bit < 1024) || (1024 <= bit && bit < 1088)); count++; } CU_ASSERT_EQUAL(count, 4 * 64); count = 0; ebitmap_for_each_positive_bit(&e, n, bit) { CU_ASSERT(bit == 10 || bit == 50 || bit == 100 || bit == 1023 || bit == 1024 || bit == 1050); CU_ASSERT_EQUAL(ebitmap_get_bit(&e, bit), 1); count++; } CU_ASSERT_EQUAL(count, 6); } CU_ASSERT_EQUAL(ebitmap_set_bit(&e, 1024, 0), 0); CU_ASSERT_FALSE(ebitmap_is_empty(&e)); CU_ASSERT_EQUAL(ebitmap_cardinality(&e), 5); CU_ASSERT_EQUAL(ebitmap_highest_set_bit(&e), 1050); CU_ASSERT_EQUAL(ebitmap_get_bit(&e, 1024), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e, 1050, 0), 0); CU_ASSERT_FALSE(ebitmap_is_empty(&e)); CU_ASSERT_EQUAL(ebitmap_cardinality(&e), 4); CU_ASSERT_EQUAL(ebitmap_highest_set_bit(&e), 1023); CU_ASSERT_EQUAL(ebitmap_get_bit(&e, 1050), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e, 100, 0), 0); CU_ASSERT_FALSE(ebitmap_is_empty(&e)); CU_ASSERT_EQUAL(ebitmap_cardinality(&e), 3); CU_ASSERT_EQUAL(ebitmap_highest_set_bit(&e), 1023); CU_ASSERT_EQUAL(ebitmap_get_bit(&e, 100), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e, 10, 0), 0); CU_ASSERT_FALSE(ebitmap_is_empty(&e)); CU_ASSERT_EQUAL(ebitmap_cardinality(&e), 2); CU_ASSERT_EQUAL(ebitmap_highest_set_bit(&e), 1023); CU_ASSERT_EQUAL(ebitmap_get_bit(&e, 10), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e, 50, 0), 0); CU_ASSERT_FALSE(ebitmap_is_empty(&e)); CU_ASSERT_EQUAL(ebitmap_cardinality(&e), 1); CU_ASSERT_EQUAL(ebitmap_highest_set_bit(&e), 1023); CU_ASSERT_EQUAL(ebitmap_get_bit(&e, 50), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e, 1023, 0), 0); CU_ASSERT_TRUE(ebitmap_is_empty(&e)); CU_ASSERT_EQUAL(ebitmap_cardinality(&e), 0); CU_ASSERT_EQUAL(ebitmap_highest_set_bit(&e), 0); CU_ASSERT_EQUAL(ebitmap_get_bit(&e, 1023), 0); ebitmap_destroy(&e); } static void test_ebitmap_init_range(void) { ebitmap_t e1, e2, e3, e4, e5, e6; CU_ASSERT_EQUAL(ebitmap_init_range(&e1, 0, 0), 0); CU_ASSERT_EQUAL(ebitmap_highest_set_bit(&e1), 0); CU_ASSERT_EQUAL(ebitmap_cardinality(&e1), 1); CU_ASSERT_EQUAL(ebitmap_init_range(&e2, 0, 5), 0); CU_ASSERT_EQUAL(ebitmap_highest_set_bit(&e2), 5); CU_ASSERT_EQUAL(ebitmap_cardinality(&e2), 6); CU_ASSERT_EQUAL(ebitmap_init_range(&e3, 20, 100), 0); CU_ASSERT_EQUAL(ebitmap_highest_set_bit(&e3), 100); CU_ASSERT_EQUAL(ebitmap_cardinality(&e3), 81); CU_ASSERT_EQUAL(ebitmap_init_range(&e4, 100, 400), 0); CU_ASSERT_EQUAL(ebitmap_highest_set_bit(&e4), 400); CU_ASSERT_EQUAL(ebitmap_cardinality(&e4), 301); CU_ASSERT_EQUAL(ebitmap_init_range(&e5, 10, 5), -EINVAL); CU_ASSERT_EQUAL(ebitmap_init_range(&e6, 0, UINT32_MAX), -EOVERFLOW); ebitmap_destroy(&e6); ebitmap_destroy(&e5); ebitmap_destroy(&e4); ebitmap_destroy(&e3); ebitmap_destroy(&e2); ebitmap_destroy(&e1); } static void test_ebitmap_or(void) { ebitmap_t e1, e2, e3, e4; ebitmap_init(&e1); ebitmap_init(&e2); ebitmap_init(&e3); ebitmap_init(&e4); CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 10, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 100, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 101, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 318, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 319, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 383, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 384, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 449, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 1013, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 11, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 101, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 430, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 665, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 10, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 11, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 100, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 101, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 318, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 319, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 383, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 384, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 430, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 449, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 665, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 1013, 1), 0); { ebitmap_t dst; CU_ASSERT_EQUAL(ebitmap_or(&dst, &e1, &e1), 0); CU_ASSERT(ebitmap_cmp(&dst, &e1)); ebitmap_destroy(&dst); } { ebitmap_t dst; CU_ASSERT_EQUAL(ebitmap_or(&dst, &e2, &e2), 0); CU_ASSERT(ebitmap_cmp(&dst, &e2)); ebitmap_destroy(&dst); } { ebitmap_t dst; CU_ASSERT_EQUAL(ebitmap_or(&dst, &e1, &e2), 0); CU_ASSERT(ebitmap_cmp(&dst, &e3)); ebitmap_destroy(&dst); } { ebitmap_t dst; CU_ASSERT_EQUAL(ebitmap_or(&dst, &e3, &e3), 0); CU_ASSERT(ebitmap_cmp(&dst, &e3)); ebitmap_destroy(&dst); } { ebitmap_t dst; CU_ASSERT_EQUAL(ebitmap_or(&dst, &e3, &e4), 0); CU_ASSERT(ebitmap_cmp(&dst, &e3)); ebitmap_destroy(&dst); } { ebitmap_t dst; CU_ASSERT_EQUAL(ebitmap_or(&dst, &e4, &e4), 0); CU_ASSERT(ebitmap_cmp(&dst, &e4)); ebitmap_destroy(&dst); } ebitmap_destroy(&e4); ebitmap_destroy(&e3); ebitmap_destroy(&e2); ebitmap_destroy(&e1); } static void test_ebitmap_and(void) { { ebitmap_t e1, e2, e12, e3, e4; ebitmap_init(&e1); ebitmap_init(&e2); ebitmap_init(&e12); ebitmap_init(&e3); ebitmap_init(&e4); CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 10, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 100, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 101, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 318, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 319, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 383, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 384, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 449, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 1013, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 11, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 101, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 319, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 665, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e12, 101, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e12, 319, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 10, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 11, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 100, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 101, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 318, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 319, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 383, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 384, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 430, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 449, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 665, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 1013, 1), 0); { ebitmap_t dst; CU_ASSERT_EQUAL(ebitmap_and(&dst, &e1, &e1), 0); CU_ASSERT(ebitmap_cmp(&dst, &e1)); ebitmap_destroy(&dst); } { ebitmap_t dst; CU_ASSERT_EQUAL(ebitmap_and(&dst, &e2, &e2), 0); CU_ASSERT(ebitmap_cmp(&dst, &e2)); ebitmap_destroy(&dst); } { ebitmap_t dst; CU_ASSERT_EQUAL(ebitmap_and(&dst, &e1, &e2), 0); CU_ASSERT(ebitmap_cmp(&dst, &e12)); ebitmap_destroy(&dst); } { ebitmap_t dst; CU_ASSERT_EQUAL(ebitmap_and(&dst, &e3, &e3), 0); CU_ASSERT(ebitmap_cmp(&dst, &e3)); ebitmap_destroy(&dst); } { ebitmap_t dst; CU_ASSERT_EQUAL(ebitmap_and(&dst, &e1, &e3), 0); CU_ASSERT(ebitmap_cmp(&dst, &e1)); ebitmap_destroy(&dst); } { ebitmap_t dst; CU_ASSERT_EQUAL(ebitmap_and(&dst, &e2, &e3), 0); CU_ASSERT(ebitmap_cmp(&dst, &e2)); ebitmap_destroy(&dst); } { ebitmap_t dst; CU_ASSERT_EQUAL(ebitmap_and(&dst, &e4, &e4), 0); CU_ASSERT(ebitmap_cmp(&dst, &e4)); ebitmap_destroy(&dst); } { ebitmap_t dst; CU_ASSERT_EQUAL(ebitmap_and(&dst, &e3, &e4), 0); CU_ASSERT(ebitmap_cmp(&dst, &e4)); ebitmap_destroy(&dst); } ebitmap_destroy(&e4); ebitmap_destroy(&e3); ebitmap_destroy(&e12); ebitmap_destroy(&e2); ebitmap_destroy(&e1); } { ebitmap_t e5; ebitmap_t e6; ebitmap_t e56; ebitmap_t dst; ebitmap_init(&e5); ebitmap_init(&e6); ebitmap_init(&e56); CU_ASSERT_EQUAL(ebitmap_set_bit(&e5, 63, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e5, 191, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e5, 192, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e5, 318, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e5, 319, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e6, 64, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e6, 192, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e6, 319, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e6, 320, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e56, 192, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e56, 319, 1), 0); CU_ASSERT_EQUAL(ebitmap_and(&dst, &e5, &e6), 0); CU_ASSERT(ebitmap_cmp(&dst, &e56)); ebitmap_destroy(&dst); ebitmap_destroy(&e56); ebitmap_destroy(&e6); ebitmap_destroy(&e5); } } static void test_ebitmap_xor(void) { { ebitmap_t e1, e2, e3, e4; ebitmap_init(&e1); ebitmap_init(&e2); ebitmap_init(&e3); ebitmap_init(&e4); CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 1, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 5, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 10, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 1, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 3, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 6, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 9, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 3, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 5, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 6, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 9, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 10, 1), 0); { ebitmap_t dst1, dst2; CU_ASSERT_EQUAL(ebitmap_xor(&dst1, &e1, &e1), 0); CU_ASSERT(ebitmap_cmp(&dst1, &e4)); CU_ASSERT_EQUAL(ebitmap_xor(&dst2, &dst1, &e1), 0); CU_ASSERT(ebitmap_cmp(&dst2, &e1)); ebitmap_destroy(&dst2); ebitmap_destroy(&dst1); } { ebitmap_t dst; CU_ASSERT_EQUAL(ebitmap_xor(&dst, &e2, &e2), 0); CU_ASSERT(ebitmap_cmp(&dst, &e4)); ebitmap_destroy(&dst); } { ebitmap_t dst; CU_ASSERT_EQUAL(ebitmap_xor(&dst, &e3, &e3), 0); CU_ASSERT(ebitmap_cmp(&dst, &e4)); ebitmap_destroy(&dst); } { ebitmap_t dst; CU_ASSERT_EQUAL(ebitmap_xor(&dst, &e4, &e4), 0); CU_ASSERT(ebitmap_cmp(&dst, &e4)); ebitmap_destroy(&dst); } { ebitmap_t dst; CU_ASSERT_EQUAL(ebitmap_xor(&dst, &e1, &e2), 0); CU_ASSERT(ebitmap_cmp(&dst, &e3)); ebitmap_destroy(&dst); } { ebitmap_t dst; CU_ASSERT_EQUAL(ebitmap_xor(&dst, &e2, &e4), 0); CU_ASSERT(ebitmap_cmp(&dst, &e2)); ebitmap_destroy(&dst); } ebitmap_destroy(&e4); ebitmap_destroy(&e3); ebitmap_destroy(&e2); ebitmap_destroy(&e1); } { ebitmap_t e5; ebitmap_t e6; ebitmap_t e56; ebitmap_t dst; ebitmap_init(&e5); ebitmap_init(&e6); ebitmap_init(&e56); CU_ASSERT_EQUAL(ebitmap_set_bit(&e5, 63, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e5, 191, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e5, 192, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e5, 318, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e5, 319, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e6, 64, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e6, 192, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e6, 319, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e6, 320, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e56, 63, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e56, 64, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e56, 191, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e56, 318, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e56, 320, 1), 0); CU_ASSERT_EQUAL(ebitmap_xor(&dst, &e5, &e6), 0); CU_ASSERT(ebitmap_cmp(&dst, &e56)); ebitmap_destroy(&dst); ebitmap_destroy(&e56); ebitmap_destroy(&e6); ebitmap_destroy(&e5); } } static void test_ebitmap_not(void) { { ebitmap_t e1, e2, e3, e4; ebitmap_init(&e1); ebitmap_init(&e2); ebitmap_init(&e3); ebitmap_init(&e4); CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 0, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 1, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 5, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 10, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 2, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 3, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 4, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 6, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 7, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 8, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 9, 1), 0); { ebitmap_t dst1, dst2; CU_ASSERT_EQUAL(ebitmap_not(&dst1, &e3, 10), 0); CU_ASSERT_EQUAL(ebitmap_highest_set_bit(&dst1), 9); CU_ASSERT_EQUAL(ebitmap_cardinality(&dst1), 10); CU_ASSERT_EQUAL(ebitmap_not(&dst2, &dst1, 10), 0); CU_ASSERT(ebitmap_cmp(&dst2, &e3)); ebitmap_destroy(&dst2); ebitmap_destroy(&dst1); } { ebitmap_t dst1, dst2; CU_ASSERT_EQUAL(ebitmap_not(&dst1, &e1, 11), 0); CU_ASSERT(ebitmap_cmp(&dst1, &e2)); CU_ASSERT_EQUAL(ebitmap_not(&dst2, &dst1, 11), 0); CU_ASSERT(ebitmap_cmp(&dst2, &e1)); ebitmap_destroy(&dst2); ebitmap_destroy(&dst1); } { ebitmap_t dst; CU_ASSERT_EQUAL(ebitmap_not(&dst, &e1, 8), 0); CU_ASSERT_EQUAL(ebitmap_highest_set_bit(&dst), 7); CU_ASSERT_EQUAL(ebitmap_cardinality(&dst), 5); ebitmap_destroy(&dst); } { ebitmap_t dst; CU_ASSERT_EQUAL(ebitmap_not(&dst, &e1, 12), 0); CU_ASSERT_EQUAL(ebitmap_highest_set_bit(&dst), 11); CU_ASSERT_EQUAL(ebitmap_cardinality(&dst), 8); ebitmap_destroy(&dst); } ebitmap_destroy(&e3); ebitmap_destroy(&e2); ebitmap_destroy(&e1); } { ebitmap_t e5; ebitmap_t e5not; ebitmap_node_t *n; unsigned int bit; ebitmap_init(&e5); ebitmap_init(&e5not); CU_ASSERT_EQUAL(ebitmap_set_bit(&e5, 63, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e5, 191, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e5, 192, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e5, 318, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e5, 319, 1), 0); for (bit = 0; bit < 317; bit++) CU_ASSERT_EQUAL(ebitmap_set_bit(&e5not, bit, 1), 0); ebitmap_for_each_positive_bit(&e5, n, bit) CU_ASSERT_EQUAL(ebitmap_set_bit(&e5not, bit, 0), 0); { ebitmap_t dst; CU_ASSERT_EQUAL(ebitmap_not(&dst, &e5, 317), 0); CU_ASSERT(ebitmap_cmp(&dst, &e5not)); ebitmap_destroy(&dst); } { ebitmap_t dst; CU_ASSERT_EQUAL(ebitmap_not(&dst, &e5, 318), 0); CU_ASSERT_FALSE(ebitmap_cmp(&dst, &e5not)); CU_ASSERT_EQUAL(ebitmap_set_bit(&e5not, 317, 1), 0); CU_ASSERT(ebitmap_cmp(&dst, &e5not)); ebitmap_destroy(&dst); } { ebitmap_t dst; CU_ASSERT_EQUAL(ebitmap_not(&dst, &e5, 319), 0); CU_ASSERT(ebitmap_cmp(&dst, &e5not)); ebitmap_destroy(&dst); } ebitmap_destroy(&e5not); ebitmap_destroy(&e5); } } static void test_ebitmap_andnot(void) { { ebitmap_t e1, e2, e12, e3, e4; ebitmap_init(&e1); ebitmap_init(&e2); ebitmap_init(&e12); ebitmap_init(&e3); ebitmap_init(&e4); CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 10, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 100, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 101, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 430, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 1013, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 11, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 101, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 665, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e12, 10, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e12, 100, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e12, 430, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e12, 1013, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 10, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 11, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 100, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 101, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 430, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 665, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 1013, 1), 0); { ebitmap_t dst; CU_ASSERT_EQUAL(ebitmap_andnot(&dst, &e1, &e1, 1024), 0); CU_ASSERT(ebitmap_cmp(&dst, &e4)); ebitmap_destroy(&dst); } { ebitmap_t dst; CU_ASSERT_EQUAL(ebitmap_andnot(&dst, &e2, &e2, 1024), 0); CU_ASSERT(ebitmap_cmp(&dst, &e4)); ebitmap_destroy(&dst); } { ebitmap_t dst; CU_ASSERT_EQUAL(ebitmap_andnot(&dst, &e1, &e2, 1024), 0); CU_ASSERT(ebitmap_cmp(&dst, &e12)); ebitmap_destroy(&dst); } { ebitmap_t dst; CU_ASSERT_EQUAL(ebitmap_andnot(&dst, &e3, &e3, 1024), 0); CU_ASSERT(ebitmap_cmp(&dst, &e4)); ebitmap_destroy(&dst); } { ebitmap_t dst; CU_ASSERT_EQUAL(ebitmap_andnot(&dst, &e1, &e3, 1024), 0); CU_ASSERT(ebitmap_cmp(&dst, &e4)); ebitmap_destroy(&dst); } { ebitmap_t dst; CU_ASSERT_EQUAL(ebitmap_andnot(&dst, &e2, &e12, 1024), 0); CU_ASSERT(ebitmap_cmp(&dst, &e2)); ebitmap_destroy(&dst); } { ebitmap_t dst; CU_ASSERT_EQUAL(ebitmap_andnot(&dst, &e4, &e4, 1024), 0); CU_ASSERT(ebitmap_cmp(&dst, &e4)); ebitmap_destroy(&dst); } { ebitmap_t dst; CU_ASSERT_EQUAL(ebitmap_andnot(&dst, &e3, &e4, 1024), 0); CU_ASSERT(ebitmap_cmp(&dst, &e3)); ebitmap_destroy(&dst); } ebitmap_destroy(&e4); ebitmap_destroy(&e3); ebitmap_destroy(&e12); ebitmap_destroy(&e2); ebitmap_destroy(&e1); } { ebitmap_t e5; ebitmap_t e6; ebitmap_t e56; ebitmap_init(&e5); ebitmap_init(&e6); ebitmap_init(&e56); CU_ASSERT_EQUAL(ebitmap_set_bit(&e5, 63, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e5, 191, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e5, 192, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e5, 318, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e5, 319, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e6, 64, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e6, 192, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e6, 319, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e6, 320, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e56, 63, 1), 0); CU_ASSERT_EQUAL(ebitmap_set_bit(&e56, 191, 1), 0); { ebitmap_t dst; CU_ASSERT_EQUAL(ebitmap_andnot(&dst, &e5, &e6, 317), 0); CU_ASSERT(ebitmap_cmp(&dst, &e56)); ebitmap_destroy(&dst); } { ebitmap_t dst; CU_ASSERT_EQUAL(ebitmap_andnot(&dst, &e5, &e6, 318), 0); CU_ASSERT(ebitmap_cmp(&dst, &e56)); ebitmap_destroy(&dst); } { ebitmap_t dst; CU_ASSERT_EQUAL(ebitmap_andnot(&dst, &e5, &e6, 319), 0); CU_ASSERT_FALSE(ebitmap_cmp(&dst, &e56)); CU_ASSERT_EQUAL(ebitmap_set_bit(&e56, 318, 1), 0); CU_ASSERT(ebitmap_cmp(&dst, &e56)); ebitmap_destroy(&dst); } { ebitmap_t dst; CU_ASSERT_EQUAL(ebitmap_andnot(&dst, &e5, &e6, 320), 0); CU_ASSERT(ebitmap_cmp(&dst, &e56)); ebitmap_destroy(&dst); } ebitmap_destroy(&e56); ebitmap_destroy(&e6); ebitmap_destroy(&e5); } } static void test_ebitmap__random_impl(unsigned int length, int set_chance) { ebitmap_t e1, e2, dst_cpy, dst_or, dst_and, dst_xor1, dst_xor2, dst_not1, dst_not2, dst_andnot; unsigned int i; CU_ASSERT_EQUAL(ebitmap_init_random(&e1, length, set_chance), 0); CU_ASSERT_EQUAL(ebitmap_init_random(&e2, length, set_chance), 0); CU_ASSERT_EQUAL(ebitmap_cpy(&dst_cpy, &e1), 0); CU_ASSERT(ebitmap_cmp(&dst_cpy, &e1)); CU_ASSERT_EQUAL(ebitmap_or(&dst_or, &e1, &e2), 0); for (i = 0; i < length; i++) CU_ASSERT_EQUAL(ebitmap_get_bit(&dst_or, i), ebitmap_get_bit(&e1, i) | ebitmap_get_bit(&e2, i)); CU_ASSERT_EQUAL(ebitmap_and(&dst_and, &e1, &e2), 0); for (i = 0; i < length; i++) CU_ASSERT_EQUAL(ebitmap_get_bit(&dst_and, i), ebitmap_get_bit(&e1, i) & ebitmap_get_bit(&e2, i)); CU_ASSERT_EQUAL(ebitmap_xor(&dst_xor1, &e1, &e2), 0); for (i = 0; i < length; i++) CU_ASSERT_EQUAL(ebitmap_get_bit(&dst_xor1, i), ebitmap_get_bit(&e1, i) ^ ebitmap_get_bit(&e2, i)); CU_ASSERT_EQUAL(ebitmap_xor(&dst_xor2, &dst_xor1, &e2), 0); CU_ASSERT(ebitmap_cmp(&dst_xor2, &e1)); CU_ASSERT_EQUAL(ebitmap_not(&dst_not1, &e1, length), 0); for (i = 0; i < length; i++) CU_ASSERT_EQUAL(ebitmap_get_bit(&dst_not1, i), !ebitmap_get_bit(&e1, i)); CU_ASSERT_EQUAL(ebitmap_not(&dst_not2, &dst_not1, length), 0); CU_ASSERT(ebitmap_cmp(&dst_not2, &e1)); CU_ASSERT_EQUAL(ebitmap_andnot(&dst_andnot, &e1, &e2, length), 0); for (i = 0; i < length; i++) CU_ASSERT_EQUAL(ebitmap_get_bit(&dst_andnot, i), ebitmap_get_bit(&e1, i) & !ebitmap_get_bit(&e2, i)); ebitmap_destroy(&dst_andnot); ebitmap_destroy(&dst_not2); ebitmap_destroy(&dst_not1); ebitmap_destroy(&dst_xor2); ebitmap_destroy(&dst_xor1); ebitmap_destroy(&dst_and); ebitmap_destroy(&dst_or); ebitmap_destroy(&dst_cpy); ebitmap_destroy(&e2); ebitmap_destroy(&e1); } static void test_ebitmap__random(void) { unsigned int i; for (i = 0; i < RANDOM_ROUNDS; i++) test_ebitmap__random_impl(5, 10); for (i = 0; i < RANDOM_ROUNDS; i++) test_ebitmap__random_impl(5, 90); for (i = 0; i < RANDOM_ROUNDS; i++) test_ebitmap__random_impl(1024, 50); for (i = 0; i < RANDOM_ROUNDS; i++) test_ebitmap__random_impl(8000, 5); for (i = 0; i < RANDOM_ROUNDS; i++) test_ebitmap__random_impl(8000, 95); } /* * External hooks */ int ebitmap_test_init(void) { srandom(time(NULL)); /* silence ebitmap_set_bit() failure message */ sepol_debug(0); return 0; } int ebitmap_test_cleanup(void) { return 0; } #define ADD_TEST(name) \ do { \ if (NULL == CU_add_test(suite, #name, test_##name)) { \ return CU_get_error(); \ } \ } while (0) int ebitmap_add_tests(CU_pSuite suite) { ADD_TEST(ebitmap_init_destroy); ADD_TEST(ebitmap_cmp); ADD_TEST(ebitmap_set_and_get); ADD_TEST(ebitmap_init_range); ADD_TEST(ebitmap_or); ADD_TEST(ebitmap_and); ADD_TEST(ebitmap_xor); ADD_TEST(ebitmap_not); ADD_TEST(ebitmap_andnot); ADD_TEST(ebitmap__random); return 0; } libsepol-3.8.1/tests/test-ebitmap.h000066400000000000000000000003221476211737200172540ustar00rootroot00000000000000#ifndef TEST_EBITMAP_H__ #define TEST_EBITMAP_H__ #include int ebitmap_test_init(void); int ebitmap_test_cleanup(void); int ebitmap_add_tests(CU_pSuite suite); #endif /* TEST_EBITMAP_H__ */ libsepol-3.8.1/tests/test-expander-attr-map.c000066400000000000000000000136661476211737200211760ustar00rootroot00000000000000/* * Authors: Chad Sellers * Joshua Brindle * * Copyright (C) 2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "test-expander-attr-map.h" #include "test-common.h" #include "helpers.h" #include #include #include extern policydb_t base_expanded2; void test_expander_attr_mapping(void) { /* note that many cases are omitted because they don't make sense (i.e. declaring in an optional and then using it in the base) or because declare in optional then require in a different optional logic still doesn't work */ const char *typesb1[] = { "attr_check_base_1_1_t", "attr_check_base_1_2_t" }; const char *typesb2[] = { "attr_check_base_2_1_t", "attr_check_base_2_2_t" }; const char *typesb3[] = { "attr_check_base_3_1_t", "attr_check_base_3_2_t", "attr_check_base_3_3_t", "attr_check_base_3_4_t" }; const char *typesb4[] = { "attr_check_base_4_1_t", "attr_check_base_4_2_t" }; const char *typesb5[] = { "attr_check_base_5_1_t", "attr_check_base_5_2_t" }; const char *typesb6[] = { "attr_check_base_6_1_t", "attr_check_base_6_2_t", "attr_check_base_6_3_t", "attr_check_base_6_4_t" }; const char *typesbo2[] = { "attr_check_base_optional_2_1_t", "attr_check_base_optional_2_2_t" }; const char *typesbo5[] = { "attr_check_base_optional_5_1_t", "attr_check_base_optional_5_2_t" }; const char *typesm2[] = { "attr_check_mod_2_1_t", "attr_check_mod_2_2_t" }; const char *typesm4[] = { "attr_check_mod_4_1_t", "attr_check_mod_4_2_t" }; const char *typesm5[] = { "attr_check_mod_5_1_t", "attr_check_mod_5_2_t" }; const char *typesm6[] = { "attr_check_mod_6_1_t", "attr_check_mod_6_2_t", "attr_check_mod_6_3_t", "attr_check_mod_6_4_t" }; const char *typesmo2[] = { "attr_check_mod_optional_4_1_t", "attr_check_mod_optional_4_2_t" }; const char *typesb10[] = { "attr_check_base_10_1_t", "attr_check_base_10_2_t" }; const char *typesb11[] = { "attr_check_base_11_3_t", "attr_check_base_11_4_t" }; const char *typesm10[] = { "attr_check_mod_10_1_t", "attr_check_mod_10_2_t" }; const char *typesm11[] = { "attr_check_mod_11_3_t", "attr_check_mod_11_4_t" }; test_attr_types(&base_expanded2, "attr_check_base_1", NULL, typesb1, 2); test_attr_types(&base_expanded2, "attr_check_base_2", NULL, typesb2, 2); test_attr_types(&base_expanded2, "attr_check_base_3", NULL, typesb3, 4); test_attr_types(&base_expanded2, "attr_check_base_4", NULL, typesb4, 2); test_attr_types(&base_expanded2, "attr_check_base_5", NULL, typesb5, 2); test_attr_types(&base_expanded2, "attr_check_base_6", NULL, typesb6, 4); test_attr_types(&base_expanded2, "attr_check_base_optional_2", NULL, typesbo2, 2); test_attr_types(&base_expanded2, "attr_check_base_optional_5", NULL, typesbo5, 2); test_attr_types(&base_expanded2, "attr_check_mod_2", NULL, typesm2, 2); test_attr_types(&base_expanded2, "attr_check_mod_4", NULL, typesm4, 2); test_attr_types(&base_expanded2, "attr_check_mod_5", NULL, typesm5, 2); test_attr_types(&base_expanded2, "attr_check_mod_6", NULL, typesm6, 4); test_attr_types(&base_expanded2, "attr_check_mod_optional_4", NULL, typesmo2, 2); test_attr_types(&base_expanded2, "attr_check_base_7", NULL, NULL, 0); test_attr_types(&base_expanded2, "attr_check_base_8", NULL, NULL, 0); test_attr_types(&base_expanded2, "attr_check_base_9", NULL, NULL, 0); test_attr_types(&base_expanded2, "attr_check_base_10", NULL, typesb10, 2); test_attr_types(&base_expanded2, "attr_check_base_11", NULL, typesb11, 2); test_attr_types(&base_expanded2, "attr_check_mod_7", NULL, NULL, 0); test_attr_types(&base_expanded2, "attr_check_mod_8", NULL, NULL, 0); test_attr_types(&base_expanded2, "attr_check_mod_9", NULL, NULL, 0); test_attr_types(&base_expanded2, "attr_check_mod_10", NULL, typesm10, 2); test_attr_types(&base_expanded2, "attr_check_mod_11", NULL, typesm11, 2); test_attr_types(&base_expanded2, "attr_check_base_optional_8", NULL, NULL, 0); test_attr_types(&base_expanded2, "attr_check_mod_optional_7", NULL, NULL, 0); CU_ASSERT(!hashtab_search((&base_expanded2)->p_types.table, "attr_check_base_optional_disabled_5")); CU_ASSERT(!hashtab_search((&base_expanded2)->p_types.table, "attr_check_base_optional_disabled_5_1_t")); CU_ASSERT(!hashtab_search((&base_expanded2)->p_types.table, "attr_check_base_optional_disabled_5_2_t")); CU_ASSERT(!hashtab_search((&base_expanded2)->p_types.table, "attr_check_base_optional_disabled_8")); CU_ASSERT(!hashtab_search((&base_expanded2)->p_types.table, "attr_check_base_optional_disabled_8_1_t")); CU_ASSERT(!hashtab_search((&base_expanded2)->p_types.table, "attr_check_base_optional_disabled_8_2_t")); CU_ASSERT(!hashtab_search((&base_expanded2)->p_types.table, "attr_check_mod_optional_disabled_4")); CU_ASSERT(!hashtab_search((&base_expanded2)->p_types.table, "attr_check_mod_optional_disabled_4_1_t")); CU_ASSERT(!hashtab_search((&base_expanded2)->p_types.table, "attr_check_mod_optional_disabled_4_2_t")); CU_ASSERT(!hashtab_search((&base_expanded2)->p_types.table, "attr_check_mod_optional_disabled_7")); CU_ASSERT(!hashtab_search((&base_expanded2)->p_types.table, "attr_check_mod_optional_disabled_7_1_t")); CU_ASSERT(!hashtab_search((&base_expanded2)->p_types.table, "attr_check_mod_optional_disabled_7_2_t")); } libsepol-3.8.1/tests/test-expander-attr-map.h000066400000000000000000000017231476211737200211720ustar00rootroot00000000000000/* * Author: Joshua Brindle * * Copyright (C) 2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __TEST_EXPANDER__ATTR_MAP_H__ #define __TEST_EXPANDER__ATTR_MAP_H__ void test_expander_attr_mapping(void); #endif libsepol-3.8.1/tests/test-expander-roles.c000066400000000000000000000024661476211737200205710ustar00rootroot00000000000000/* * Authors: Chad Sellers * Joshua Brindle * Chris PeBenito * * Copyright (C) 2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "test-expander-roles.h" #include "test-common.h" #include "helpers.h" #include #include #include extern policydb_t role_expanded; void test_expander_role_mapping(void) { const char *types1[] = { "role_check_1_1_t", "role_check_1_2_t" }; test_role_type_set(&role_expanded, "role_check_1", NULL, types1, 2, 0); } libsepol-3.8.1/tests/test-expander-roles.h000066400000000000000000000017721476211737200205750ustar00rootroot00000000000000/* * Author: Joshua Brindle * Author: Chris PeBenito * * Copyright (C) 2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __TEST_EXPANDER_ROLE_H__ #define __TEST_EXPANDER_ROLE_H__ void test_expander_role_mapping(void); #endif libsepol-3.8.1/tests/test-expander-users.c000066400000000000000000000044061476211737200206020ustar00rootroot00000000000000/* * Authors: Chad Sellers * Joshua Brindle * Chris PeBenito * * Copyright (C) 2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "test-expander-users.h" #include "helpers.h" #include #include #include extern policydb_t user_expanded; static void check_user_roles(policydb_t * p, const char *user_name, const char **role_names, int num_roles) { user_datum_t *user; ebitmap_node_t *tnode; unsigned int i; int j; unsigned char *found; /* array of booleans of roles found */ int extra = 0; /* number of extra roles found */ user = (user_datum_t *) hashtab_search(p->p_users.table, user_name); if (!user) { printf("%s not found\n", user_name); CU_FAIL("user not found"); return; } found = calloc(num_roles, sizeof(unsigned char)); CU_ASSERT_FATAL(found != NULL); ebitmap_for_each_positive_bit(&user->roles.roles, tnode, i) { extra++; for (j = 0; j < num_roles; j++) { if (strcmp(role_names[j], p->p_role_val_to_name[i]) == 0) { extra--; found[j] += 1; break; } } } for (j = 0; j < num_roles; j++) { if (found[j] != 1) { printf("role %s associated with user %s %d times\n", role_names[j], user_name, found[j]); CU_FAIL("user mapping failure\n"); } } free(found); CU_ASSERT_EQUAL(extra, 0); } void test_expander_user_mapping(void) { const char *roles1[] = { "user_check_1_1_r", "user_check_1_2_r" }; check_user_roles(&user_expanded, "user_check_1", roles1, 2); } libsepol-3.8.1/tests/test-expander-users.h000066400000000000000000000017721476211737200206120ustar00rootroot00000000000000/* * Author: Joshua Brindle * Author: Chris PeBenito * * Copyright (C) 2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __TEST_EXPANDER_USER_H__ #define __TEST_EXPANDER_USER_H__ void test_expander_user_mapping(void); #endif libsepol-3.8.1/tests/test-expander.c000066400000000000000000000154031476211737200174420ustar00rootroot00000000000000/* * Authors: Chad Sellers * Joshua Brindle * * Copyright (C) 2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* This is where the expander tests should go, including: * - check role, type, bool, user mapping * - add symbols declared in enabled optionals * - do not add symbols declared in disabled optionals * - add rules from enabled optionals * - do not add rules from disabled optionals * - verify attribute mapping * - check conditional expressions for correct mapping */ #include "test-expander.h" #include "parse_util.h" #include "helpers.h" #include "test-common.h" #include "test-expander-users.h" #include "test-expander-roles.h" #include "test-expander-attr-map.h" #include #include #include #include #include #include policydb_t role_expanded; policydb_t user_expanded; policydb_t base_expanded2; static policydb_t basemod; static policydb_t basemod2; static policydb_t mod2; static policydb_t base_expanded; static policydb_t base_only_mod; static policydb_t base_only_expanded; static policydb_t role_basemod; static policydb_t role_mod; static policydb_t user_basemod; static policydb_t user_mod; static policydb_t alias_basemod; static policydb_t alias_mod; static policydb_t alias_expanded; static uint32_t *typemap; extern int mls; /* Takes base, some number of modules, links them, and expands them reads source from myfiles array, which has the base string followed by each module string */ static int expander_policy_init(policydb_t * mybase, int num_modules, policydb_t ** mymodules, policydb_t * myexpanded, const char *const *myfiles) { char *filename[num_modules + 1]; int i; for (i = 0; i < num_modules + 1; i++) { filename[i] = calloc(PATH_MAX, sizeof(char)); if (snprintf(filename[i], PATH_MAX, "policies/test-expander/%s%s", myfiles[i], mls ? ".mls" : ".std") < 0) return -1; } if (policydb_init(mybase)) { fprintf(stderr, "out of memory!\n"); return -1; } for (i = 0; i < num_modules; i++) { if (policydb_init(mymodules[i])) { fprintf(stderr, "out of memory!\n"); return -1; } } if (policydb_init(myexpanded)) { fprintf(stderr, "out of memory!\n"); return -1; } mybase->policy_type = POLICY_BASE; mybase->mls = mls; if (read_source_policy(mybase, filename[0], myfiles[0])) { fprintf(stderr, "read source policy failed %s\n", filename[0]); return -1; } for (i = 1; i < num_modules + 1; i++) { mymodules[i - 1]->policy_type = POLICY_MOD; mymodules[i - 1]->mls = mls; if (read_source_policy(mymodules[i - 1], filename[i], myfiles[i])) { fprintf(stderr, "read source policy failed %s\n", filename[i]); return -1; } } if (link_modules(NULL, mybase, mymodules, num_modules, 0)) { fprintf(stderr, "link modules failed\n"); return -1; } if (expand_module(NULL, mybase, myexpanded, 0, 0)) { fprintf(stderr, "expand modules failed\n"); return -1; } for (i = 0; i < num_modules + 1; i++) { free(filename[i]); } return 0; } int expander_test_init(void) { const char *small_base_file = "small-base.conf"; const char *base_only_file = "base-base-only.conf"; int rc; policydb_t *mymod2; const char *files2[] = { "small-base.conf", "module.conf" }; const char *role_files[] = { "role-base.conf", "role-module.conf" }; const char *user_files[] = { "user-base.conf", "user-module.conf" }; const char *alias_files[] = { "alias-base.conf", "alias-module.conf" }; rc = expander_policy_init(&basemod, 0, NULL, &base_expanded, &small_base_file); if (rc != 0) return rc; mymod2 = &mod2; rc = expander_policy_init(&basemod2, 1, &mymod2, &base_expanded2, files2); if (rc != 0) return rc; rc = expander_policy_init(&base_only_mod, 0, NULL, &base_only_expanded, &base_only_file); if (rc != 0) return rc; mymod2 = &role_mod; rc = expander_policy_init(&role_basemod, 1, &mymod2, &role_expanded, role_files); if (rc != 0) return rc; /* Just init the base for now, until we figure out how to separate out mls and non-mls tests since users can't be used in mls module */ mymod2 = &user_mod; rc = expander_policy_init(&user_basemod, 0, NULL, &user_expanded, user_files); if (rc != 0) return rc; mymod2 = &alias_mod; rc = expander_policy_init(&alias_basemod, 1, &mymod2, &alias_expanded, alias_files); if (rc != 0) return rc; return 0; } int expander_test_cleanup(void) { policydb_destroy(&basemod); policydb_destroy(&base_expanded); policydb_destroy(&basemod2); policydb_destroy(&base_expanded2); policydb_destroy(&mod2); policydb_destroy(&base_only_mod); policydb_destroy(&base_only_expanded); policydb_destroy(&role_basemod); policydb_destroy(&role_expanded); policydb_destroy(&role_mod); policydb_destroy(&user_basemod); policydb_destroy(&user_expanded); policydb_destroy(&user_mod); policydb_destroy(&alias_basemod); policydb_destroy(&alias_expanded); policydb_destroy(&alias_mod); free(typemap); return 0; } static void test_expander_indexes(void) { test_policydb_indexes(&base_expanded); } static void test_expander_alias(void) { test_alias_datum(&alias_expanded, "alias_check_1_a", "alias_check_1_t", 1, 0); test_alias_datum(&alias_expanded, "alias_check_2_a", "alias_check_2_t", 1, 0); test_alias_datum(&alias_expanded, "alias_check_3_a", "alias_check_3_t", 1, 0); } int expander_add_tests(CU_pSuite suite) { if (NULL == CU_add_test(suite, "expander_indexes", test_expander_indexes)) { CU_cleanup_registry(); return CU_get_error(); } if (NULL == CU_add_test(suite, "expander_attr_mapping", test_expander_attr_mapping)) { CU_cleanup_registry(); return CU_get_error(); } if (NULL == CU_add_test(suite, "expander_role_mapping", test_expander_role_mapping)) { CU_cleanup_registry(); return CU_get_error(); } if (NULL == CU_add_test(suite, "expander_user_mapping", test_expander_user_mapping)) { CU_cleanup_registry(); return CU_get_error(); } if (NULL == CU_add_test(suite, "expander_alias", test_expander_alias)) { CU_cleanup_registry(); return CU_get_error(); } return 0; } libsepol-3.8.1/tests/test-expander.h000066400000000000000000000020321476211737200174410ustar00rootroot00000000000000/* * Author: Joshua Brindle * * Copyright (C) 2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __TEST_EXPANDER_H__ #define __TEST_EXPANDER_H__ #include int expander_test_init(void); int expander_test_cleanup(void); int expander_add_tests(CU_pSuite suite); #endif libsepol-3.8.1/tests/test-linker-cond-map.c000066400000000000000000000122131476211737200206100ustar00rootroot00000000000000/* * Author: Joshua Brindle * * Copyright (C) 2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "test-linker-cond-map.h" #include "parse_util.h" #include "helpers.h" #include "test-common.h" #include #include #include #include #include /* Tests for conditionals * Test each cond/bool for these * - boolean copied correctly (state is correct) * - conditional expression is correct * Tests: * - single boolean in base * - single boolean in module * - single boolean in base optional * - single boolean in module optional * - 2 booleans in base * - 2 booleans in module * - 2 booleans in base optional * - 2 booleans in module optional * - 2 booleans, base and module * - 2 booleans, base optional and module * - 2 booleans, base optional and module optional * - 3 booleans, base, base optional, module * - 4 boolean, base, base optional, module, module optional */ typedef struct test_cond_expr { const char *boolean; uint32_t expr_type; } test_cond_expr_t; static void test_cond_expr_mapping(policydb_t * p, avrule_decl_t * d, test_cond_expr_t * bools, int len) { int i; cond_expr_t *expr; CU_ASSERT_FATAL(d->cond_list != NULL); CU_ASSERT_FATAL(d->cond_list->expr != NULL); expr = d->cond_list->expr; for (i = 0; i < len; i++) { CU_ASSERT_FATAL(expr != NULL); CU_ASSERT(expr->expr_type == bools[i].expr_type); if (bools[i].boolean) { CU_ASSERT(strcmp(p->sym_val_to_name[SYM_BOOLS][expr->boolean - 1], bools[i].boolean) == 0); } expr = expr->next; } } static void test_bool_state(policydb_t * p, const char *boolean, int state) { cond_bool_datum_t *b; b = hashtab_search(p->p_bools.table, boolean); CU_ASSERT_FATAL(b != NULL); CU_ASSERT(b->state == state); } void base_cond_tests(policydb_t * base) { avrule_decl_t *d; unsigned int decls[1]; test_cond_expr_t bools[2]; /* these tests look at booleans and conditionals in the base only * to ensure that they aren't altered or removed during the link process */ /* bool existence and state, global scope */ d = test_find_decl_by_sym(base, SYM_TYPES, "tag_g_b"); decls[0] = d->decl_id; test_sym_presence(base, "g_b_bool_1", SYM_BOOLS, SCOPE_DECL, decls, 1); test_bool_state(base, "g_b_bool_1", 0); /* conditional expression mapped correctly */ bools[0].boolean = "g_b_bool_1"; bools[0].expr_type = COND_BOOL; test_cond_expr_mapping(base, d, bools, 1); /* bool existence and state, optional scope */ d = test_find_decl_by_sym(base, SYM_TYPES, "tag_o1_b"); decls[0] = d->decl_id; test_sym_presence(base, "o1_b_bool_1", SYM_BOOLS, SCOPE_DECL, decls, 1); test_bool_state(base, "o1_b_bool_1", 1); /* conditional expression mapped correctly */ bools[0].boolean = "o1_b_bool_1"; bools[0].expr_type = COND_BOOL; test_cond_expr_mapping(base, d, bools, 1); } void module_cond_tests(policydb_t * base) { avrule_decl_t *d; unsigned int decls[1]; test_cond_expr_t bools[3]; /* bool existence and state, module 1 global scope */ d = test_find_decl_by_sym(base, SYM_TYPES, "tag_g_m1"); decls[0] = d->decl_id; test_sym_presence(base, "g_m1_bool_1", SYM_BOOLS, SCOPE_DECL, decls, 1); test_bool_state(base, "g_m1_bool_1", 1); /* conditional expression mapped correctly */ bools[0].boolean = "g_m1_bool_1"; bools[0].expr_type = COND_BOOL; test_cond_expr_mapping(base, d, bools, 1); /* bool existence and state, module 1 optional scope */ d = test_find_decl_by_sym(base, SYM_TYPES, "tag_o1_m1"); decls[0] = d->decl_id; test_sym_presence(base, "o1_m1_bool_1", SYM_BOOLS, SCOPE_DECL, decls, 1); test_bool_state(base, "o1_m1_bool_1", 0); /* conditional expression mapped correctly */ bools[0].boolean = "o1_m1_bool_1"; bools[0].expr_type = COND_BOOL; test_cond_expr_mapping(base, d, bools, 1); /* bool existence and state, module 2 global scope */ d = test_find_decl_by_sym(base, SYM_TYPES, "tag_g_m2"); decls[0] = d->decl_id; test_sym_presence(base, "g_m2_bool_1", SYM_BOOLS, SCOPE_DECL, decls, 1); test_sym_presence(base, "g_m2_bool_2", SYM_BOOLS, SCOPE_DECL, decls, 1); test_bool_state(base, "g_m2_bool_1", 1); test_bool_state(base, "g_m2_bool_2", 0); /* conditional expression mapped correctly */ bools[0].boolean = "g_m2_bool_1"; bools[0].expr_type = COND_BOOL; bools[1].boolean = "g_m2_bool_2"; bools[1].expr_type = COND_BOOL; bools[2].boolean = NULL; bools[2].expr_type = COND_AND; test_cond_expr_mapping(base, d, bools, 3); } libsepol-3.8.1/tests/test-linker-cond-map.h000066400000000000000000000020561476211737200206210ustar00rootroot00000000000000/* * Author: Joshua Brindle * * Copyright (C) 2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __TEST_LINKER_COND_MAP_H__ #define __TEST_LINKER_COND_MAP_H__ #include extern void base_cond_tests(policydb_t * base); extern void module_cond_tests(policydb_t * base); #endif libsepol-3.8.1/tests/test-linker-roles.c000066400000000000000000000215131476211737200202410ustar00rootroot00000000000000/* * Author: Joshua Brindle * * Copyright (C) 2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "test-linker-roles.h" #include "parse_util.h" #include "helpers.h" #include "test-common.h" #include #include #include #include /* Tests for roles: * Test for each of these for * - role in appropriate symtab (global and decl) * - datum in the decl symtab has correct type_set * - scope datum has correct decl ids * - dominates bitmap is correct * Tests: * - role in base, no modules * - role in base optional, no modules * - role a in base, b in module * - role a in base and module (additive) * - role a in base and 2 module * - role a in base optional, b in module * - role a in base, b in module optional * - role a in base optional, b in module optional * - role a in base optional and module * - role a in base and module optional * - role a in base optional and module optional * - role a in base optional and 2 modules * - role a and b in base, b dom a, are types correct (TODO) */ /* this simply tests whether the passed in role only has its own * value in its dominates ebitmap */ static void only_dominates_self(policydb_t * p __attribute__ ((unused)), role_datum_t * role) { ebitmap_node_t *tnode; unsigned int i; int found = 0; ebitmap_for_each_positive_bit(&role->dominates, tnode, i) { found++; CU_ASSERT(i == role->s.value - 1); } CU_ASSERT(found == 1); } void base_role_tests(policydb_t * base) { avrule_decl_t *decl; role_datum_t *role; unsigned int decls[2]; const char *types[2]; /* These tests look at roles in the base only, the desire is to ensure that * roles are not destroyed or otherwise removed during the link process */ /**** test for g_b_role_1 in base and decl 1 (global) ****/ decls[0] = (test_find_decl_by_sym(base, SYM_TYPES, "tag_g_b"))->decl_id; test_sym_presence(base, "g_b_role_1", SYM_ROLES, SCOPE_DECL, decls, 1); /* make sure it has the correct type set (g_b_type_1, no negset, no flags) */ types[0] = "g_b_type_1"; role = test_role_type_set(base, "g_b_role_1", NULL, types, 1, 0); /* This role should only dominate itself */ only_dominates_self(base, role); /**** test for o1_b_role_1 in optional (decl 2) ****/ decl = test_find_decl_by_sym(base, SYM_TYPES, "tag_o1_b"); decls[0] = decl->decl_id; test_sym_presence(base, "o1_b_role_1", SYM_ROLES, SCOPE_DECL, decls, 1); /* make sure it has the correct type set (o1_b_type_1, no negset, no flags) */ types[0] = "o1_b_type_1"; role = test_role_type_set(base, "o1_b_role_1", decl, types, 1, 0); /* and only dominates itself */ only_dominates_self(base, role); } void module_role_tests(policydb_t * base) { role_datum_t *role; avrule_decl_t *decl; unsigned int decls[3]; const char *types[3]; /* These tests are run when the base is linked with 2 modules, * They should test whether the roles get copied correctly from the * modules into the base */ /**** test for role in module 1 (global) ****/ decls[0] = (test_find_decl_by_sym(base, SYM_TYPES, "tag_g_m1"))->decl_id; test_sym_presence(base, "g_m1_role_1", SYM_ROLES, SCOPE_DECL, decls, 1); /* make sure it has the correct type set (g_m1_type_1, no negset, no flags) */ types[0] = "g_m1_type_1"; role = test_role_type_set(base, "g_m1_role_1", NULL, types, 1, 0); /* and only dominates itself */ only_dominates_self(base, role); /**** test for role in module 1 (optional) ****/ decl = test_find_decl_by_sym(base, SYM_TYPES, "tag_o1_m1"); decls[0] = decl->decl_id; test_sym_presence(base, "o1_m1_role_1", SYM_ROLES, SCOPE_DECL, decls, 1); /* make sure it has the correct type set (o1_m1_type_1, no negset, no flags) */ types[0] = "o1_m1_type_1"; role = test_role_type_set(base, "o1_m1_role_1", decl, types, 1, 0); /* and only dominates itself */ only_dominates_self(base, role); /* These test whether the type sets are copied to the right place and * correctly unioned when they should be */ /**** test for type added to base role in module 1 (global) ****/ decls[0] = (test_find_decl_by_sym(base, SYM_TYPES, "tag_g_b"))->decl_id; test_sym_presence(base, "g_b_role_2", SYM_ROLES, SCOPE_DECL, decls, 1); /* make sure it has the correct type set (g_m1_type_1, no negset, no flags) */ types[0] = "g_b_type_2"; /* added in base when declared */ types[1] = "g_m1_type_1"; /* added in module */ role = test_role_type_set(base, "g_b_role_2", NULL, types, 2, 0); /* and only dominates itself */ only_dominates_self(base, role); /**** test for type added to base role in module 1 & 2 (global) ****/ decls[0] = (test_find_decl_by_sym(base, SYM_TYPES, "tag_g_b"))->decl_id; decls[1] = (test_find_decl_by_sym(base, SYM_TYPES, "tag_g_m1"))->decl_id; decls[2] = (test_find_decl_by_sym(base, SYM_TYPES, "tag_g_m2"))->decl_id; test_sym_presence(base, "g_b_role_3", SYM_ROLES, SCOPE_DECL, decls, 3); /* make sure it has the correct type set (g_b_type_2, g_m1_type_2, g_m2_type_2, no negset, no flags) */ types[0] = "g_b_type_2"; /* added in base when declared */ types[1] = "g_m1_type_2"; /* added in module 1 */ types[2] = "g_m2_type_2"; /* added in module 2 */ role = test_role_type_set(base, "g_b_role_3", NULL, types, 3, 0); /* and only dominates itself */ only_dominates_self(base, role); /**** test for role in base optional and module 1 (additive) ****/ decls[0] = (test_find_decl_by_sym(base, SYM_TYPES, "tag_o1_b"))->decl_id; decls[1] = (test_find_decl_by_sym(base, SYM_TYPES, "tag_g_m1"))->decl_id; test_sym_presence(base, "o1_b_role_2", SYM_ROLES, SCOPE_DECL, decls, 2); /* this one will have 2 type sets, one in the global symtab and one in the base optional 1 */ types[0] = "g_m1_type_1"; role = test_role_type_set(base, "o1_b_role_2", NULL, types, 1, 0); types[0] = "o1_b_type_1"; role = test_role_type_set(base, "o1_b_role_2", test_find_decl_by_sym(base, SYM_TYPES, "tag_o1_b"), types, 1, 0); /* and only dominates itself */ only_dominates_self(base, role); /**** test for role in base and module 1 optional (additive) ****/ decls[0] = (test_find_decl_by_sym(base, SYM_TYPES, "tag_g_b"))->decl_id; decls[1] = (test_find_decl_by_sym(base, SYM_TYPES, "tag_o2_m1"))->decl_id; test_sym_presence(base, "g_b_role_4", SYM_ROLES, SCOPE_DECL, decls, 2); /* this one will have 2 type sets, one in the global symtab and one in the base optional 1 */ types[0] = "g_b_type_2"; role = test_role_type_set(base, "g_b_role_4", NULL, types, 1, 0); types[0] = "g_m1_type_2"; role = test_role_type_set(base, "g_b_role_4", test_find_decl_by_sym(base, SYM_TYPES, "tag_o2_m1"), types, 1, 0); /* and only dominates itself */ only_dominates_self(base, role); /**** test for role in base and module 1 optional (additive) ****/ decls[0] = (test_find_decl_by_sym(base, SYM_TYPES, "tag_o3_b"))->decl_id; decls[1] = (test_find_decl_by_sym(base, SYM_TYPES, "tag_o3_m1"))->decl_id; test_sym_presence(base, "o3_b_role_1", SYM_ROLES, SCOPE_DECL, decls, 2); /* this one will have 2 type sets, one in the 3rd base optional and one in the 3rd module optional */ types[0] = "o3_b_type_1"; role = test_role_type_set(base, "o3_b_role_1", test_find_decl_by_sym(base, SYM_TYPES, "tag_o3_b"), types, 1, 0); types[0] = "o3_m1_type_1"; role = test_role_type_set(base, "o3_b_role_1", test_find_decl_by_sym(base, SYM_TYPES, "tag_o3_m1"), types, 1, 0); /* and only dominates itself */ only_dominates_self(base, role); /**** test for role in base and module 1 optional (additive) ****/ decls[0] = (test_find_decl_by_sym(base, SYM_TYPES, "tag_o4_b"))->decl_id; decls[1] = (test_find_decl_by_sym(base, SYM_TYPES, "tag_g_m1"))->decl_id; decls[2] = (test_find_decl_by_sym(base, SYM_TYPES, "tag_g_m2"))->decl_id; test_sym_presence(base, "o4_b_role_1", SYM_ROLES, SCOPE_DECL, decls, 3); /* this one will have 2 type sets, one in the global symtab (with both module types) and one in the 4th optional of base */ types[0] = "g_m1_type_1"; role = test_role_type_set(base, "o4_b_role_1", test_find_decl_by_sym(base, SYM_TYPES, "tag_o4_b"), types, 1, 0); types[0] = "g_m2_type_1"; types[1] = "g_m1_type_2"; role = test_role_type_set(base, "o4_b_role_1", NULL, types, 2, 0); /* and only dominates itself */ only_dominates_self(base, role); } libsepol-3.8.1/tests/test-linker-roles.h000066400000000000000000000020501476211737200202410ustar00rootroot00000000000000/* * Author: Joshua Brindle * * Copyright (C) 2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __TEST_LINKER_ROLES_H__ #define __TEST_LINKER_ROLES_H__ #include extern void base_role_tests(policydb_t * base); extern void module_role_tests(policydb_t * base); #endif libsepol-3.8.1/tests/test-linker-types.c000066400000000000000000000352641476211737200202710ustar00rootroot00000000000000/* * Author: Joshua Brindle * Chad Sellers * * Copyright (C) 2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "test-linker-types.h" #include "parse_util.h" #include "helpers.h" #include "test-common.h" #include #include #include #include /* Tests for types: * Test for each of these for * - type in appropriate symtab (global and decl) * - datum in the decl symtab has correct type bitmap (if attr) * - primary is set correctly * - scope datum has correct decl ids * Tests: * - type in base, no modules * - type in base optional, no modules * - type a in base, b in module * - type a in base optional, b in module * - type a in base, b in module optional * - type a in base optional, b in module optional * - attr in base, no modules * - attr in base optional, no modules * - attr a in base, b in module * - attr a in base optional, b in module * - attr a in base, b in module optional * - attr a in base optional, b in module optional * - attr a declared in base, added to in module * - attr a declared in base, added to in module optional * - attr a declared in base, added to in 2 modules * - attr a declared in base, added to in 2 modules (optional and global) * - attr a declared in base optional, added to in module * - attr a declared in base optional, added to in module optional * - attr a added to in base optional, declared in module * - attr a added to in base optional, declared in module optional * - attr a added to in base optional, declared in module, added to in other module * - attr a added to in base optional, declared in module optional, added to in other module * - attr a added to in base optional, declared in module , added to in other module optional * - attr a added to in base optional, declared in module optional, added to in other module optional * - alias in base of primary type in base, no modules * - alias in base optional of primary type in base, no modules * - alias in base optional of primary type in base optional * - alias in module of primary type in base * - alias in module optional of primary type in base * - alias in module optional of primary type in base optional * - alias in module of primary type in module * - alias in module optional of primary type in module * - alias in module optional of primary type in module optional * - alias a in base, b in module, primary type in base * - alias a in base, b in module, primary type in module * - alias a in base optional, b in module, primary type in base * - alias a in base optional, b in module, primary type in module * - alias a in base, b in module optional, primary type in base * - alias a in base, b in module optional, primary type in module * - alias a in base optional, b in module optional, primary type in base * - alias a in base optional, b in module optional, primary type in module * - alias a in base, required in module, primary type in base * - alias a in base, required in base optional, primary type in base * - alias a in base, required in module optional, primary type in base * - alias a in module, required in base optional, primary type in base * - alias a in module, required in module optional, primary type in base * - alias a in base optional, required in module, primary type in base * - alias a in base optional, required in different base optional, primary type in base * - alias a in base optional, required in module optional, primary type in base * - alias a in module optional, required in base optional, primary type in base * - alias a in module optional, required in module optional, primary type in base * - alias a in module, required in base optional, primary type in module * - alias a in module, required in module optional, primary type in module * - alias a in base optional, required in module, primary type in module * - alias a in base optional, required in different base optional, primary type in module * - alias a in base optional, required in module optional, primary type in module * - alias a in module optional, required in base optional, primary type in module * - alias a in module optional, required in module optional, primary type in module */ /* Don't pass in decls from global blocks since symbols aren't stored in their symtab */ static void test_type_datum(policydb_t * p, const char *id, unsigned int *decls, int len, unsigned int primary) { int i; unsigned int value; type_datum_t *type; /* just test the type datums for each decl to see if it is what we expect */ type = hashtab_search(p->p_types.table, id); CU_ASSERT_FATAL(type != NULL); CU_ASSERT(type->primary == primary); CU_ASSERT(type->flavor == TYPE_TYPE); value = type->s.value; for (i = 0; i < len; i++) { type = hashtab_search(p->decl_val_to_struct[decls[i] - 1]->p_types.table, id); CU_ASSERT_FATAL(type != NULL); CU_ASSERT(type->primary == primary); CU_ASSERT(type->flavor == TYPE_TYPE); CU_ASSERT(type->s.value == value); } } void base_type_tests(policydb_t * base) { unsigned int decls[2]; const char *types[2]; /* These tests look at types in the base only, the desire is to ensure that * types are not destroyed or otherwise removed during the link process. * if this happens these tests won't work anyway since we are using types to * mark blocks */ /**** test for g_b_type_1 in base and decl 1 (global) ****/ decls[0] = (test_find_decl_by_sym(base, SYM_TYPES, "tag_g_b"))->decl_id; test_sym_presence(base, "g_b_type_1", SYM_TYPES, SCOPE_DECL, decls, 1); test_type_datum(base, "g_b_type_1", NULL, 0, 1); /* this attr is in the same decl as the type */ test_sym_presence(base, "g_b_attr_1", SYM_TYPES, SCOPE_DECL, decls, 1); types[0] = "g_b_type_1"; test_attr_types(base, "g_b_attr_1", NULL, types, 1); /**** test for o1_b_type_1 in optional (decl 2) ****/ decls[0] = (test_find_decl_by_sym(base, SYM_TYPES, "tag_o1_b"))->decl_id; test_sym_presence(base, "o1_b_type_1", SYM_TYPES, SCOPE_DECL, decls, 1); test_type_datum(base, "o1_b_type_1", NULL, 0, 1); /* this attr is in the same decl as the type */ test_sym_presence(base, "o1_b_attr_1", SYM_TYPES, SCOPE_DECL, decls, 1); types[0] = "o1_b_type_1"; test_attr_types(base, "o1_b_attr_1", base->decl_val_to_struct[decls[0] - 1], types, 1); /* tests for aliases */ decls[0] = (test_find_decl_by_sym(base, SYM_TYPES, "tag_g_b"))->decl_id; test_sym_presence(base, "g_b_alias_1", SYM_TYPES, SCOPE_DECL, decls, 1); test_alias_datum(base, "g_b_alias_1", "g_b_type_3", 1, 0); decls[0] = (test_find_decl_by_sym(base, SYM_TYPES, "tag_o6_b"))->decl_id; test_sym_presence(base, "g_b_alias_2", SYM_TYPES, SCOPE_DECL, decls, 1); test_alias_datum(base, "g_b_alias_2", "g_b_type_3", 1, 0); } void module_type_tests(policydb_t * base) { unsigned int decls[2]; const char *types[2]; avrule_decl_t *d; /* These tests look at types that were copied from modules or attributes * that were modified and declared in modules and base. These apply to * declarations and modifications in and out of optionals. These tests * should ensure that types and attributes are correctly copied from modules * and that attribute type sets are correctly copied and mapped. */ /* note: scope for attributes is currently smashed if the attribute is declared * somewhere so the scope test only looks at global, the type bitmap test looks * at the appropriate decl symtab */ /* test for type in module 1 (global) */ decls[0] = (test_find_decl_by_sym(base, SYM_TYPES, "tag_g_m1"))->decl_id; test_sym_presence(base, "g_m1_type_1", SYM_TYPES, SCOPE_DECL, decls, 1); test_type_datum(base, "g_m1_type_1", NULL, 0, 1); /* attr has is in the same decl as the above type */ test_sym_presence(base, "g_m1_attr_1", SYM_TYPES, SCOPE_DECL, decls, 1); types[0] = "g_m1_type_1"; types[1] = "g_m1_type_2"; test_attr_types(base, "g_m1_attr_1", NULL, types, 2); /* test for type in module 1 (optional) */ decls[0] = (test_find_decl_by_sym(base, SYM_TYPES, "tag_o1_m1"))->decl_id; test_sym_presence(base, "o1_m1_type_1", SYM_TYPES, SCOPE_DECL, decls, 1); test_type_datum(base, "o1_m1_type_1", NULL, 0, 1); /* attr has is in the same decl as the above type */ test_sym_presence(base, "o1_m1_attr_1", SYM_TYPES, SCOPE_DECL, decls, 1); types[0] = "o1_m1_type_2"; test_attr_types(base, "o1_m1_attr_1", base->decl_val_to_struct[decls[0] - 1], types, 1); /* test for attr declared in base, added to in module (global). * Since these are both global it'll be merged in the main symtab */ decls[0] = (test_find_decl_by_sym(base, SYM_TYPES, "tag_g_b"))->decl_id; test_sym_presence(base, "g_b_attr_3", SYM_TYPES, SCOPE_DECL, decls, 1); types[0] = "g_m1_type_3"; test_attr_types(base, "g_b_attr_3", NULL, types, 1); /* test for attr declared in base, added to in module (optional). */ decls[0] = (test_find_decl_by_sym(base, SYM_TYPES, "tag_g_b"))->decl_id; test_sym_presence(base, "g_b_attr_4", SYM_TYPES, SCOPE_DECL, decls, 1); decls[0] = (test_find_decl_by_sym(base, SYM_TYPES, "tag_o1_m1"))->decl_id; types[0] = "o1_m1_type_3"; test_attr_types(base, "g_b_attr_4", base->decl_val_to_struct[decls[0] - 1], types, 1); /* test for attr declared in base, added to in 2 modules (global). (merged in main symtab) */ decls[0] = (test_find_decl_by_sym(base, SYM_TYPES, "tag_g_b"))->decl_id; test_sym_presence(base, "g_b_attr_5", SYM_TYPES, SCOPE_DECL, decls, 1); types[0] = "g_m1_type_4"; types[1] = "g_m2_type_4"; test_attr_types(base, "g_b_attr_5", NULL, types, 2); /* test for attr declared in base, added to in 2 modules (optional/global). */ decls[0] = (test_find_decl_by_sym(base, SYM_TYPES, "tag_g_b"))->decl_id; test_sym_presence(base, "g_b_attr_6", SYM_TYPES, SCOPE_DECL, decls, 1); /* module 2 was global to its type is in main symtab */ types[0] = "g_m2_type_5"; test_attr_types(base, "g_b_attr_6", NULL, types, 1); d = (test_find_decl_by_sym(base, SYM_TYPES, "tag_o3_m1")); types[0] = "o3_m1_type_2"; test_attr_types(base, "g_b_attr_6", d, types, 1); /* test for attr declared in base optional, added to in module (global). */ decls[0] = (test_find_decl_by_sym(base, SYM_TYPES, "tag_o4_b"))->decl_id; test_sym_presence(base, "o4_b_attr_1", SYM_TYPES, SCOPE_DECL, decls, 1); types[0] = "g_m1_type_5"; test_attr_types(base, "o4_b_attr_1", NULL, types, 1); /* test for attr declared in base optional, added to in module (optional). */ decls[0] = (test_find_decl_by_sym(base, SYM_TYPES, "tag_o1_b"))->decl_id; test_sym_presence(base, "o1_b_attr_2", SYM_TYPES, SCOPE_DECL, decls, 1); d = test_find_decl_by_sym(base, SYM_TYPES, "tag_o1_m1"); types[0] = "o1_m1_type_5"; test_attr_types(base, "o1_b_attr_2", d, types, 1); /* test for attr declared in module, added to in base optional */ decls[0] = (test_find_decl_by_sym(base, SYM_TYPES, "tag_g_m1"))->decl_id; test_sym_presence(base, "g_m1_attr_2", SYM_TYPES, SCOPE_DECL, decls, 1); d = test_find_decl_by_sym(base, SYM_TYPES, "tag_o1_b"); types[0] = "o1_b_type_2"; test_attr_types(base, "g_m1_attr_2", d, types, 1); /* test for attr declared in module optional, added to in base optional */ decls[0] = (test_find_decl_by_sym(base, SYM_TYPES, "tag_o3_m1"))->decl_id; test_sym_presence(base, "o3_m1_attr_1", SYM_TYPES, SCOPE_DECL, decls, 1); d = test_find_decl_by_sym(base, SYM_TYPES, "tag_o4_b"); types[0] = "o4_b_type_1"; test_attr_types(base, "o3_m1_attr_1", d, types, 1); /* attr a added to in base optional, declared/added to in module, added to in other module */ /* first the module declare/add and module 2 add (since its global it'll be in the main symtab */ decls[0] = (test_find_decl_by_sym(base, SYM_TYPES, "tag_g_m1"))->decl_id; test_sym_presence(base, "g_m1_attr_3", SYM_TYPES, SCOPE_DECL, decls, 1); types[0] = "g_m1_type_6"; types[1] = "g_m2_type_3"; test_attr_types(base, "g_m1_attr_3", NULL, types, 2); /* base add */ d = test_find_decl_by_sym(base, SYM_TYPES, "tag_o4_b"); types[0] = "o4_b_type_2"; test_attr_types(base, "g_m1_attr_3", d, types, 1); /* attr a added to in base optional, declared/added in module optional, added to in other module */ d = test_find_decl_by_sym(base, SYM_TYPES, "tag_o3_m1"); decls[0] = d->decl_id; test_sym_presence(base, "o3_m1_attr_2", SYM_TYPES, SCOPE_DECL, decls, 1); types[0] = "o3_m1_type_3"; test_attr_types(base, "o3_m1_attr_2", d, types, 1); /* module 2's type will be in the main symtab */ types[0] = "g_m2_type_6"; test_attr_types(base, "o3_m1_attr_2", NULL, types, 1); /* base add */ d = test_find_decl_by_sym(base, SYM_TYPES, "tag_o2_b"); types[0] = "o2_b_type_1"; test_attr_types(base, "o3_m1_attr_2", d, types, 1); /* attr a added to in base optional, declared/added in module , added to in other module optional */ decls[0] = (test_find_decl_by_sym(base, SYM_TYPES, "tag_g_m1"))->decl_id; test_sym_presence(base, "g_m1_attr_4", SYM_TYPES, SCOPE_DECL, decls, 1); types[0] = "g_m1_type_7"; test_attr_types(base, "g_m1_attr_4", NULL, types, 1); /* module 2 */ d = test_find_decl_by_sym(base, SYM_TYPES, "tag_o2_m2"); types[0] = "o2_m2_type_1"; test_attr_types(base, "g_m1_attr_4", d, types, 1); /* base add */ d = test_find_decl_by_sym(base, SYM_TYPES, "tag_o5_b"); types[0] = "o5_b_type_1"; test_attr_types(base, "g_m1_attr_4", d, types, 1); /* attr a added to in base optional, declared/added in module optional, added to in other module optional */ d = test_find_decl_by_sym(base, SYM_TYPES, "tag_o4_m1"); decls[0] = d->decl_id; test_sym_presence(base, "o4_m1_attr_1", SYM_TYPES, SCOPE_DECL, decls, 1); types[0] = "o4_m1_type_1"; test_attr_types(base, "o4_m1_attr_1", d, types, 1); /* module 2 */ d = test_find_decl_by_sym(base, SYM_TYPES, "tag_o2_m2"); types[0] = "o2_m2_type_2"; test_attr_types(base, "o4_m1_attr_1", d, types, 1); /* base add */ d = test_find_decl_by_sym(base, SYM_TYPES, "tag_o5_b"); types[0] = "o5_b_type_2"; test_attr_types(base, "o4_m1_attr_1", d, types, 1); /* tests for aliases */ decls[0] = (test_find_decl_by_sym(base, SYM_TYPES, "tag_g_m1"))->decl_id; test_sym_presence(base, "g_m_alias_1", SYM_TYPES, SCOPE_DECL, decls, 1); test_alias_datum(base, "g_m_alias_1", "g_b_type_3", 1, 0); } libsepol-3.8.1/tests/test-linker-types.h000066400000000000000000000020501476211737200202610ustar00rootroot00000000000000/* * Author: Joshua Brindle * * Copyright (C) 2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __TEST_LINKER_TYPES_H__ #define __TEST_LINKER_TYPES_H__ #include extern void base_type_tests(policydb_t * base); extern void module_type_tests(policydb_t * base); #endif libsepol-3.8.1/tests/test-linker.c000066400000000000000000000073331476211737200171230ustar00rootroot00000000000000/* * Author: Joshua Brindle * * Copyright (C) 2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* This is where the linker tests should go, including: * - check role, type, bool, user, attr mapping * - check for properly enabled optional * - check for properly disabled optional * - check for non-optional disabled blocks * - properly add symbols declared in optionals */ #include "test-linker.h" #include "parse_util.h" #include "helpers.h" #include "test-common.h" #include "test-linker-roles.h" #include "test-linker-types.h" #include "test-linker-cond-map.h" #include #include #include #include #include #include #define NUM_MODS 2 #define NUM_POLICIES NUM_MODS+1 #define BASEMOD NUM_MODS const char *policies[NUM_POLICIES] = { "module1.conf", "module2.conf", "small-base.conf", }; static policydb_t basenomods; static policydb_t linkedbase; static policydb_t *modules[NUM_MODS]; extern int mls; int linker_test_init(void) { int i; if (test_load_policy(&linkedbase, POLICY_BASE, mls, "test-linker", policies[BASEMOD])) return -1; if (test_load_policy(&basenomods, POLICY_BASE, mls, "test-linker", policies[BASEMOD])) return -1; for (i = 0; i < NUM_MODS; i++) { modules[i] = calloc(1, sizeof(*modules[i])); if (!modules[i]) { fprintf(stderr, "out of memory!\n"); return -1; } if (test_load_policy(modules[i], POLICY_MOD, mls, "test-linker", policies[i])) return -1; } if (link_modules(NULL, &linkedbase, modules, NUM_MODS, 0)) { fprintf(stderr, "link modules failed\n"); return -1; } if (link_modules(NULL, &basenomods, NULL, 0, 0)) { fprintf(stderr, "link modules failed\n"); return -1; } return 0; } int linker_test_cleanup(void) { int i; policydb_destroy(&basenomods); policydb_destroy(&linkedbase); for (i = 0; i < NUM_MODS; i++) { policydb_destroy(modules[i]); free(modules[i]); } return 0; } static void test_linker_indexes(void) { test_policydb_indexes(&linkedbase); } static void test_linker_roles(void) { base_role_tests(&basenomods); base_role_tests(&linkedbase); module_role_tests(&linkedbase); } static void test_linker_types(void) { base_type_tests(&basenomods); base_type_tests(&linkedbase); module_type_tests(&linkedbase); } static void test_linker_cond(void) { base_cond_tests(&basenomods); base_cond_tests(&linkedbase); module_cond_tests(&linkedbase); } int linker_add_tests(CU_pSuite suite) { if (NULL == CU_add_test(suite, "linker_indexes", test_linker_indexes)) { CU_cleanup_registry(); return CU_get_error(); } if (NULL == CU_add_test(suite, "linker_types", test_linker_types)) { CU_cleanup_registry(); return CU_get_error(); } if (NULL == CU_add_test(suite, "linker_roles", test_linker_roles)) { CU_cleanup_registry(); return CU_get_error(); } if (NULL == CU_add_test(suite, "linker_cond", test_linker_cond)) { CU_cleanup_registry(); return CU_get_error(); } return 0; } libsepol-3.8.1/tests/test-linker.h000066400000000000000000000020201476211737200171140ustar00rootroot00000000000000/* * Author: Joshua Brindle * * Copyright (C) 2006 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __TEST_LINKER_H__ #define __TEST_LINKER_H__ #include int linker_test_init(void); int linker_test_cleanup(void); int linker_add_tests(CU_pSuite suite); #endif libsepol-3.8.1/tests/test-neverallow.c000066400000000000000000000727171476211737200200250ustar00rootroot00000000000000#define _GNU_SOURCE /* vasprintf(3) */ #include "test-neverallow.h" #include "helpers.h" #include "test-common.h" #include #include #include #include #include extern int mls; int neverallow_test_init(void) { return 0; } int neverallow_test_cleanup(void) { return 0; } static struct msg_list { char *msg; struct msg_list *next; } *messages; static void messages_clean(void) { while (messages) { struct msg_list *n = messages->next; free(messages->msg); free(messages); messages = n; } } static void messages_check(unsigned count, const char *const expected[count]) { unsigned i; const struct msg_list *m = messages; for (i = 0; i < count; i++, m = m->next) { if (!m) { CU_FAIL("less messages than expected"); fprintf(stderr, "\n\n", count, i); return; } if (strcmp(expected[i], m->msg) != 0) { CU_FAIL("messages differ from expected"); fprintf(stderr, "\n\n", expected[i], m->msg); } } if (m) { CU_FAIL("more messages than expected"); fprintf(stderr, "\n\n", count, m->msg); } } __attribute__ ((format(printf, 3, 4))) static void msg_handler(void *varg __attribute__ ((unused)), sepol_handle_t * handle __attribute__ ((unused)), const char *fmt, ...) { char *msg; va_list ap; int r; va_start(ap, fmt); r = vasprintf(&msg, fmt, ap); if (r < 0) CU_FAIL_FATAL("oom"); va_end(ap); struct msg_list *new = malloc(sizeof(*new)); if (!new) CU_FAIL_FATAL("oom"); new->msg = msg; new->next = messages; messages = new; } #define ARRAY_SIZE(a) (sizeof(a) / sizeof(*a)) static void test_neverallow_basic(void) { policydb_t basemod, base_expanded; sepol_handle_t *handle; static const char *const expected_messages[] = { "30 neverallow failures occurred", "neverallow on line 53 of policies/test-neverallow/policy.conf.std (or line 53 of policies/test-neverallow/policy.conf.std) violated by allow test1_t test1_t:file { read };", "neverallow on line 60 of policies/test-neverallow/policy.conf.std (or line 60 of policies/test-neverallow/policy.conf.std) violated by allow test2_t test2_t:file { read write };", "neverallow on line 67 of policies/test-neverallow/policy.conf.std (or line 67 of policies/test-neverallow/policy.conf.std) violated by allow test3_t test3_t:file { read };", "neverallow on line 74 of policies/test-neverallow/policy.conf.std (or line 74 of policies/test-neverallow/policy.conf.std) violated by allow test4_t test4_t:file { read };", "neverallow on line 81 of policies/test-neverallow/policy.conf.std (or line 81 of policies/test-neverallow/policy.conf.std) violated by allow test5_t test5_t:file { read };", "neverallow on line 89 of policies/test-neverallow/policy.conf.std (or line 89 of policies/test-neverallow/policy.conf.std) violated by allow test6_1_t test6_1_t:file { read };", "neverallow on line 97 of policies/test-neverallow/policy.conf.std (or line 97 of policies/test-neverallow/policy.conf.std) violated by allow test7_1_t test7_1_t:file { read };", "neverallow on line 106 of policies/test-neverallow/policy.conf.std (or line 106 of policies/test-neverallow/policy.conf.std) violated by allow test8_t test8_t:file { read };", "neverallow on line 106 of policies/test-neverallow/policy.conf.std (or line 106 of policies/test-neverallow/policy.conf.std) violated by allow test8_t test8_t:file { write };", "neverallow on line 115 of policies/test-neverallow/policy.conf.std (or line 115 of policies/test-neverallow/policy.conf.std) violated by allow test9_t test9_t:file { write };", "neverallow on line 115 of policies/test-neverallow/policy.conf.std (or line 115 of policies/test-neverallow/policy.conf.std) violated by allow test9_t test9_t:file { read };", "neverallow on line 124 of policies/test-neverallow/policy.conf.std (or line 124 of policies/test-neverallow/policy.conf.std) violated by allow test10_1_t test10_1_t:file { read };", "neverallow on line 131 of policies/test-neverallow/policy.conf.std (or line 131 of policies/test-neverallow/policy.conf.std) violated by allow test11_t test11_t:process { dyntransition transition };", "neverallow on line 143 of policies/test-neverallow/policy.conf.std (or line 143 of policies/test-neverallow/policy.conf.std) violated by allow test12_3_t test12_1_t:file { getattr };", "neverallow on line 143 of policies/test-neverallow/policy.conf.std (or line 143 of policies/test-neverallow/policy.conf.std) violated by allow test12_3_t test12_2_t:file { getattr };", "neverallow on line 144 of policies/test-neverallow/policy.conf.std (or line 144 of policies/test-neverallow/policy.conf.std) violated by allow test12_3_t test12_1_t:file { open };", "neverallow on line 144 of policies/test-neverallow/policy.conf.std (or line 144 of policies/test-neverallow/policy.conf.std) violated by allow test12_2_t test12_1_t:file { open };", "neverallow on line 156 of policies/test-neverallow/policy.conf.std (or line 156 of policies/test-neverallow/policy.conf.std) violated by allow test13_1_t test13_1_t:file { read };", "neverallowxperm on line 174 of policies/test-neverallow/policy.conf.std (or line 174 of policies/test-neverallow/policy.conf.std) violated by\n allow test15_t test15_t:file { ioctl };", "neverallowxperm on line 182 of policies/test-neverallow/policy.conf.std (or line 182 of policies/test-neverallow/policy.conf.std) violated by\n allowxperm test16_t test16_t:file ioctl { 0x1111 };", "neverallowxperm on line 198 of policies/test-neverallow/policy.conf.std (or line 198 of policies/test-neverallow/policy.conf.std) violated by\n allowxperm test18_t test18_t:file ioctl { 0x1111 };", "neverallowxperm on line 206 of policies/test-neverallow/policy.conf.std (or line 206 of policies/test-neverallow/policy.conf.std) violated by\n allowxperm test19_t test19_t:file ioctl { 0x1111 };", "neverallowxperm on line 216 of policies/test-neverallow/policy.conf.std (or line 216 of policies/test-neverallow/policy.conf.std) violated by\n allowxperm test20_a test20_a:file ioctl { 0x1111 };", "neverallowxperm on line 227 of policies/test-neverallow/policy.conf.std (or line 227 of policies/test-neverallow/policy.conf.std) violated by\n allowxperm test21_1_a test21_2_a:file ioctl { 0x1111 };", "neverallowxperm on line 237 of policies/test-neverallow/policy.conf.std (or line 237 of policies/test-neverallow/policy.conf.std) violated by\n allowxperm test22_t test22_t:file ioctl { 0x1111 };", "neverallowxperm on line 247 of policies/test-neverallow/policy.conf.std (or line 247 of policies/test-neverallow/policy.conf.std) violated by\n allowxperm test23_t test23_t:file ioctl { 0x1111 };", "neverallowxperm on line 257 of policies/test-neverallow/policy.conf.std (or line 257 of policies/test-neverallow/policy.conf.std) violated by\n allowxperm test24_t test24_a:file ioctl { 0x1111 };", "neverallowxperm on line 267 of policies/test-neverallow/policy.conf.std (or line 267 of policies/test-neverallow/policy.conf.std) violated by\n allowxperm test25_t test25_t:file ioctl { 0x1111 };", "neverallowxperm on line 277 of policies/test-neverallow/policy.conf.std (or line 277 of policies/test-neverallow/policy.conf.std) violated by\n allowxperm test26_a test26_a:file ioctl { 0x1111 };", "neverallowxperm on line 277 of policies/test-neverallow/policy.conf.std (or line 277 of policies/test-neverallow/policy.conf.std) violated by\n allowxperm test26_a test26_a:file ioctl { 0x1111 };", }; if (policydb_init(&base_expanded)) CU_FAIL_FATAL("Failed to initialize policy"); if (test_load_policy(&basemod, POLICY_BASE, mls, "test-neverallow", "policy.conf")) CU_FAIL_FATAL("Failed to load policy"); if (link_modules(NULL, &basemod, NULL, 0, 0)) CU_FAIL_FATAL("Failed to link base module"); if (expand_module(NULL, &basemod, &base_expanded, 0, 0)) CU_FAIL_FATAL("Failed to expand policy"); if ((handle = sepol_handle_create()) == NULL) CU_FAIL_FATAL("Failed to initialize handle"); sepol_msg_set_callback(handle, msg_handler, NULL); if (check_assertions(handle, &base_expanded, base_expanded.global->branch_list->avrules) != -1) CU_FAIL("Assertions did not trigger"); messages_check(ARRAY_SIZE(expected_messages), expected_messages); sepol_handle_destroy(handle); messages_clean(); policydb_destroy(&basemod); policydb_destroy(&base_expanded); } static void test_neverallow_minus_self(void) { policydb_t basemod, base_expanded; sepol_handle_t *handle; static const char *const expected_messages[] = { "33 neverallow failures occurred", "neverallow on line 77 of policies/test-neverallow/policy_minus_self.conf.std (or line 77 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test3_1_t test3_2_t:file { read };", "neverallow on line 85 of policies/test-neverallow/policy_minus_self.conf.std (or line 85 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test4_1_t test4_2_t:file { read };", "neverallow on line 93 of policies/test-neverallow/policy_minus_self.conf.std (or line 93 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test5_2_t test5_1_t:class5 { perm };", "neverallow on line 93 of policies/test-neverallow/policy_minus_self.conf.std (or line 93 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test5_1_t test5_2_t:class5 { perm };", "neverallow on line 101 of policies/test-neverallow/policy_minus_self.conf.std (or line 101 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test6_1_t test6_2_t:class6 { perm };", "neverallow on line 118 of policies/test-neverallow/policy_minus_self.conf.std (or line 118 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test8_1_t test8_2_t:file { read };", "neverallow on line 127 of policies/test-neverallow/policy_minus_self.conf.std (or line 127 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test9_1_t test9_2_t:file { read };", "neverallow on line 137 of policies/test-neverallow/policy_minus_self.conf.std (or line 137 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test10_1_t test10_2_t:file { read };", "neverallow on line 157 of policies/test-neverallow/policy_minus_self.conf.std (or line 157 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test12_1_t test12_2_t:file { read };", "neverallow on line 166 of policies/test-neverallow/policy_minus_self.conf.std (or line 166 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test13_1_t test13_2_t:file { read };", "neverallow on line 175 of policies/test-neverallow/policy_minus_self.conf.std (or line 175 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test14_2_t test14_1_t:file { read };", "neverallow on line 175 of policies/test-neverallow/policy_minus_self.conf.std (or line 175 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test14_1_t test14_2_t:file { read };", "neverallow on line 193 of policies/test-neverallow/policy_minus_self.conf.std (or line 193 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test16_2_t test16_1_t:file { read };", "neverallow on line 193 of policies/test-neverallow/policy_minus_self.conf.std (or line 193 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test16_1_t test16_2_t:file { read };", "neverallowxperm on line 201 of policies/test-neverallow/policy_minus_self.conf.std (or line 201 of policies/test-neverallow/policy_minus_self.conf.std) violated by\n allow test17_1_t test17_2_t:class17 { ioctl };", "neverallowxperm on line 219 of policies/test-neverallow/policy_minus_self.conf.std (or line 219 of policies/test-neverallow/policy_minus_self.conf.std) violated by\n allowxperm test19_2_t test19_1_t:file ioctl { 0x101-0x102 };", "neverallowxperm on line 231 of policies/test-neverallow/policy_minus_self.conf.std (or line 231 of policies/test-neverallow/policy_minus_self.conf.std) violated by\n allowxperm test20_2_t test20_1_t:file ioctl { 0x103 };", "neverallowxperm on line 231 of policies/test-neverallow/policy_minus_self.conf.std (or line 231 of policies/test-neverallow/policy_minus_self.conf.std) violated by\n allowxperm test20_1_t test20_2_t:file ioctl { 0x102 };", "neverallowxperm on line 261 of policies/test-neverallow/policy_minus_self.conf.std (or line 261 of policies/test-neverallow/policy_minus_self.conf.std) violated by\n allowxperm test23_1_t test23_2_t:file ioctl { 0x9511 };", "neverallowxperm on line 272 of policies/test-neverallow/policy_minus_self.conf.std (or line 272 of policies/test-neverallow/policy_minus_self.conf.std) violated by\n allowxperm test24_1_t test24_a:file ioctl { 0x9511 };", "neverallowxperm on line 283 of policies/test-neverallow/policy_minus_self.conf.std (or line 283 of policies/test-neverallow/policy_minus_self.conf.std) violated by\n allowxperm test25_a test25_a:file ioctl { 0x9511 };", "neverallowxperm on line 295 of policies/test-neverallow/policy_minus_self.conf.std (or line 295 of policies/test-neverallow/policy_minus_self.conf.std) violated by\n allowxperm test26_1_a test26_2_a:file ioctl { 0x9511 };", "neverallowxperm on line 295 of policies/test-neverallow/policy_minus_self.conf.std (or line 295 of policies/test-neverallow/policy_minus_self.conf.std) violated by\n allowxperm test26_1_a test26_2_a:file ioctl { 0x9511 };", "neverallowxperm on line 295 of policies/test-neverallow/policy_minus_self.conf.std (or line 295 of policies/test-neverallow/policy_minus_self.conf.std) violated by\n allowxperm test26_1_a test26_2_a:file ioctl { 0x9511 };", "neverallowxperm on line 295 of policies/test-neverallow/policy_minus_self.conf.std (or line 295 of policies/test-neverallow/policy_minus_self.conf.std) violated by\n allowxperm test26_1_a test26_2_a:file ioctl { 0x9511 };", "neverallowxperm on line 317 of policies/test-neverallow/policy_minus_self.conf.std (or line 317 of policies/test-neverallow/policy_minus_self.conf.std) violated by\n allow test28_2_t test28_1_t:file { ioctl };", "neverallowxperm on line 317 of policies/test-neverallow/policy_minus_self.conf.std (or line 317 of policies/test-neverallow/policy_minus_self.conf.std) violated by\n allowxperm test28_1_t test28_2_t:file ioctl { 0x9521 };", "neverallowxperm on line 327 of policies/test-neverallow/policy_minus_self.conf.std (or line 327 of policies/test-neverallow/policy_minus_self.conf.std) violated by\n allow test29_2_t test29_1_t:file { ioctl };", "neverallowxperm on line 327 of policies/test-neverallow/policy_minus_self.conf.std (or line 327 of policies/test-neverallow/policy_minus_self.conf.std) violated by\n allowxperm test29_1_t test29_a:file ioctl { 0x9521 };", "neverallowxperm on line 337 of policies/test-neverallow/policy_minus_self.conf.std (or line 337 of policies/test-neverallow/policy_minus_self.conf.std) violated by\n allowxperm test30_a test30_a:file ioctl { 0x9521 };", "neverallowxperm on line 337 of policies/test-neverallow/policy_minus_self.conf.std (or line 337 of policies/test-neverallow/policy_minus_self.conf.std) violated by\n allowxperm test30_a test30_a:file ioctl { 0x9521 };", "neverallowxperm on line 348 of policies/test-neverallow/policy_minus_self.conf.std (or line 348 of policies/test-neverallow/policy_minus_self.conf.std) violated by\n allowxperm test31_1_a test31_2_a:file ioctl { 0x9521 };", "neverallowxperm on line 348 of policies/test-neverallow/policy_minus_self.conf.std (or line 348 of policies/test-neverallow/policy_minus_self.conf.std) violated by\n allowxperm test31_1_a test31_2_a:file ioctl { 0x9521 };", }; if (policydb_init(&base_expanded)) CU_FAIL_FATAL("Failed to initialize policy"); if (test_load_policy(&basemod, POLICY_BASE, mls, "test-neverallow", "policy_minus_self.conf")) CU_FAIL_FATAL("Failed to load policy"); if (link_modules(NULL, &basemod, NULL, 0, 0)) CU_FAIL_FATAL("Failed to link base module"); if (expand_module(NULL, &basemod, &base_expanded, 0, 0)) CU_FAIL_FATAL("Failed to expand policy"); if ((handle = sepol_handle_create()) == NULL) CU_FAIL_FATAL("Failed to initialize handle"); sepol_msg_set_callback(handle, msg_handler, NULL); if (check_assertions(handle, &base_expanded, base_expanded.global->branch_list->avrules) != -1) CU_FAIL("Assertions did not trigger"); messages_check(ARRAY_SIZE(expected_messages), expected_messages); sepol_handle_destroy(handle); messages_clean(); policydb_destroy(&basemod); policydb_destroy(&base_expanded); } static void test_neverallow_not_self(void) { policydb_t basemod, base_expanded; sepol_handle_t *handle; static const char *const expected_messages[] = { "34 neverallow failures occurred", "neverallow on line 78 of policies/test-neverallow/policy_not_self.conf.std (or line 78 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test3_1_t test3_2_t:file { read };", "neverallow on line 86 of policies/test-neverallow/policy_not_self.conf.std (or line 86 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test4_1_t test4_2_t:file { read };", "neverallow on line 94 of policies/test-neverallow/policy_not_self.conf.std (or line 94 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test5_2_t test5_1_t:class5 { perm };", "neverallow on line 94 of policies/test-neverallow/policy_not_self.conf.std (or line 94 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test5_1_t test5_2_t:class5 { perm };", "neverallow on line 102 of policies/test-neverallow/policy_not_self.conf.std (or line 102 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test6_1_t test6_2_t:class6 { perm };", "neverallow on line 119 of policies/test-neverallow/policy_not_self.conf.std (or line 119 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test8_1_t test8_2_t:file { read };", "neverallow on line 128 of policies/test-neverallow/policy_not_self.conf.std (or line 128 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test9_1_t test9_2_t:file { read };", "neverallow on line 138 of policies/test-neverallow/policy_not_self.conf.std (or line 138 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test10_1_t test10_2_t:file { read };", "neverallow on line 158 of policies/test-neverallow/policy_not_self.conf.std (or line 158 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test12_1_t test12_2_t:file { read };", "neverallow on line 167 of policies/test-neverallow/policy_not_self.conf.std (or line 167 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test13_1_t test13_2_t:file { read };", "neverallow on line 176 of policies/test-neverallow/policy_not_self.conf.std (or line 176 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test14_2_t test14_1_t:file { read };", "neverallow on line 176 of policies/test-neverallow/policy_not_self.conf.std (or line 176 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test14_1_t test14_2_t:file { read };", "neverallow on line 185 of policies/test-neverallow/policy_not_self.conf.std (or line 185 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test13_1_t test13_2_t:file { read };", "neverallow on line 194 of policies/test-neverallow/policy_not_self.conf.std (or line 194 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test16_2_t test16_1_t:file { read };", "neverallow on line 194 of policies/test-neverallow/policy_not_self.conf.std (or line 194 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test16_1_t test16_2_t:file { read };", "neverallowxperm on line 202 of policies/test-neverallow/policy_not_self.conf.std (or line 202 of policies/test-neverallow/policy_not_self.conf.std) violated by\n allow test17_1_t test17_2_t:class17 { ioctl };", "neverallowxperm on line 220 of policies/test-neverallow/policy_not_self.conf.std (or line 220 of policies/test-neverallow/policy_not_self.conf.std) violated by\n allowxperm test19_2_t test19_1_t:file ioctl { 0x101-0x102 };", "neverallowxperm on line 232 of policies/test-neverallow/policy_not_self.conf.std (or line 232 of policies/test-neverallow/policy_not_self.conf.std) violated by\n allowxperm test20_2_t test20_1_t:file ioctl { 0x103 };", "neverallowxperm on line 232 of policies/test-neverallow/policy_not_self.conf.std (or line 232 of policies/test-neverallow/policy_not_self.conf.std) violated by\n allowxperm test20_1_t test20_2_t:file ioctl { 0x102 };", "neverallowxperm on line 262 of policies/test-neverallow/policy_not_self.conf.std (or line 262 of policies/test-neverallow/policy_not_self.conf.std) violated by\n allowxperm test23_1_t test23_2_t:file ioctl { 0x9511 };", "neverallowxperm on line 273 of policies/test-neverallow/policy_not_self.conf.std (or line 273 of policies/test-neverallow/policy_not_self.conf.std) violated by\n allowxperm test24_1_t test24_a:file ioctl { 0x9511 };", "neverallowxperm on line 284 of policies/test-neverallow/policy_not_self.conf.std (or line 284 of policies/test-neverallow/policy_not_self.conf.std) violated by\n allowxperm test25_a test25_a:file ioctl { 0x9511 };", "neverallowxperm on line 296 of policies/test-neverallow/policy_not_self.conf.std (or line 296 of policies/test-neverallow/policy_not_self.conf.std) violated by\n allowxperm test26_1_a test26_2_a:file ioctl { 0x9511 };", "neverallowxperm on line 296 of policies/test-neverallow/policy_not_self.conf.std (or line 296 of policies/test-neverallow/policy_not_self.conf.std) violated by\n allowxperm test26_1_a test26_2_a:file ioctl { 0x9511 };", "neverallowxperm on line 296 of policies/test-neverallow/policy_not_self.conf.std (or line 296 of policies/test-neverallow/policy_not_self.conf.std) violated by\n allowxperm test26_1_a test26_2_a:file ioctl { 0x9511 };", "neverallowxperm on line 296 of policies/test-neverallow/policy_not_self.conf.std (or line 296 of policies/test-neverallow/policy_not_self.conf.std) violated by\n allowxperm test26_1_a test26_2_a:file ioctl { 0x9511 };", "neverallowxperm on line 318 of policies/test-neverallow/policy_not_self.conf.std (or line 318 of policies/test-neverallow/policy_not_self.conf.std) violated by\n allow test28_2_t test28_1_t:file { ioctl };", "neverallowxperm on line 318 of policies/test-neverallow/policy_not_self.conf.std (or line 318 of policies/test-neverallow/policy_not_self.conf.std) violated by\n allowxperm test28_1_t test28_2_t:file ioctl { 0x9521 };", "neverallowxperm on line 328 of policies/test-neverallow/policy_not_self.conf.std (or line 328 of policies/test-neverallow/policy_not_self.conf.std) violated by\n allow test29_2_t test29_1_t:file { ioctl };", "neverallowxperm on line 328 of policies/test-neverallow/policy_not_self.conf.std (or line 328 of policies/test-neverallow/policy_not_self.conf.std) violated by\n allowxperm test29_1_t test29_a:file ioctl { 0x9521 };", "neverallowxperm on line 338 of policies/test-neverallow/policy_not_self.conf.std (or line 338 of policies/test-neverallow/policy_not_self.conf.std) violated by\n allowxperm test30_a test30_a:file ioctl { 0x9521 };", "neverallowxperm on line 338 of policies/test-neverallow/policy_not_self.conf.std (or line 338 of policies/test-neverallow/policy_not_self.conf.std) violated by\n allowxperm test30_a test30_a:file ioctl { 0x9521 };", "neverallowxperm on line 349 of policies/test-neverallow/policy_not_self.conf.std (or line 349 of policies/test-neverallow/policy_not_self.conf.std) violated by\n allowxperm test31_1_a test31_2_a:file ioctl { 0x9521 };", "neverallowxperm on line 349 of policies/test-neverallow/policy_not_self.conf.std (or line 349 of policies/test-neverallow/policy_not_self.conf.std) violated by\n allowxperm test31_1_a test31_2_a:file ioctl { 0x9521 };", }; if (policydb_init(&base_expanded)) CU_FAIL_FATAL("Failed to initialize policy"); if (test_load_policy(&basemod, POLICY_BASE, mls, "test-neverallow", "policy_not_self.conf")) CU_FAIL_FATAL("Failed to load policy"); if (link_modules(NULL, &basemod, NULL, 0, 0)) CU_FAIL_FATAL("Failed to link base module"); if (expand_module(NULL, &basemod, &base_expanded, 0, 0)) CU_FAIL_FATAL("Failed to expand policy"); if ((handle = sepol_handle_create()) == NULL) CU_FAIL_FATAL("Failed to initialize handle"); sepol_msg_set_callback(handle, msg_handler, NULL); if (check_assertions(handle, &base_expanded, base_expanded.global->branch_list->avrules) != -1) CU_FAIL("Assertions did not trigger"); messages_check(ARRAY_SIZE(expected_messages), expected_messages); sepol_handle_destroy(handle); messages_clean(); policydb_destroy(&basemod); policydb_destroy(&base_expanded); } static void test_neverallow_cond(void) { policydb_t basemod, base_expanded; sepol_handle_t *handle; static const char *const expected_messages[] = { "16 neverallow failures occurred", "neverallow on line 58 of policies/test-neverallow/policy_cond.conf.std (or line 58 of policies/test-neverallow/policy_cond.conf.std) violated by allow test1_t test1_t:file { read };", "neverallow on line 70 of policies/test-neverallow/policy_cond.conf.std (or line 70 of policies/test-neverallow/policy_cond.conf.std) violated by allow test2_1_t test2_1_t:file { write };", "neverallowxperm on line 81 of policies/test-neverallow/policy_cond.conf.std (or line 81 of policies/test-neverallow/policy_cond.conf.std) violated by\n allow test3_t test3_t:file { ioctl };", "neverallowxperm on line 93 of policies/test-neverallow/policy_cond.conf.std (or line 93 of policies/test-neverallow/policy_cond.conf.std) violated by\n allow test4_t test4_t:file { ioctl };", "neverallowxperm on line 117 of policies/test-neverallow/policy_cond.conf.std (or line 117 of policies/test-neverallow/policy_cond.conf.std) violated by\n allowxperm test6_t test6_t:file ioctl { 0x1 };", "neverallowxperm on line 130 of policies/test-neverallow/policy_cond.conf.std (or line 130 of policies/test-neverallow/policy_cond.conf.std) violated by\n allowxperm test7_t test7_t:file ioctl { 0x2 };", "neverallowxperm on line 130 of policies/test-neverallow/policy_cond.conf.std (or line 130 of policies/test-neverallow/policy_cond.conf.std) violated by\n allowxperm test7_t test7_t:file ioctl { 0x1 };", "neverallowxperm on line 130 of policies/test-neverallow/policy_cond.conf.std (or line 130 of policies/test-neverallow/policy_cond.conf.std) violated by\n allowxperm test7_t test7_t:file ioctl { 0x2 };", "neverallowxperm on line 130 of policies/test-neverallow/policy_cond.conf.std (or line 130 of policies/test-neverallow/policy_cond.conf.std) violated by\n allowxperm test7_t test7_t:file ioctl { 0x1 };", "neverallowxperm on line 155 of policies/test-neverallow/policy_cond.conf.std (or line 155 of policies/test-neverallow/policy_cond.conf.std) violated by\n allow test9_t test9_t:file { ioctl };", "neverallowxperm on line 191 of policies/test-neverallow/policy_cond.conf.std (or line 191 of policies/test-neverallow/policy_cond.conf.std) violated by\n allow test12_t test12_t:file { ioctl };", "neverallowxperm on line 204 of policies/test-neverallow/policy_cond.conf.std (or line 204 of policies/test-neverallow/policy_cond.conf.std) violated by\n allowxperm test13_t test13_t:file ioctl { 0x1 };", "neverallowxperm on line 204 of policies/test-neverallow/policy_cond.conf.std (or line 204 of policies/test-neverallow/policy_cond.conf.std) violated by\n allow test13_t test13_t:file { ioctl };", "neverallowxperm on line 204 of policies/test-neverallow/policy_cond.conf.std (or line 204 of policies/test-neverallow/policy_cond.conf.std) violated by\n allowxperm test13_t test13_t:file ioctl { 0x1 };", "neverallowxperm on line 217 of policies/test-neverallow/policy_cond.conf.std (or line 217 of policies/test-neverallow/policy_cond.conf.std) violated by\n allow test14_t test14_t:file { ioctl };", "neverallowxperm on line 230 of policies/test-neverallow/policy_cond.conf.std (or line 230 of policies/test-neverallow/policy_cond.conf.std) violated by\n allow test15_t test15_t:file { ioctl };", }; if (policydb_init(&base_expanded)) CU_FAIL_FATAL("Failed to initialize policy"); if (test_load_policy(&basemod, POLICY_BASE, mls, "test-neverallow", "policy_cond.conf")) CU_FAIL_FATAL("Failed to load policy"); if (link_modules(NULL, &basemod, NULL, 0, 0)) CU_FAIL_FATAL("Failed to link base module"); if (expand_module(NULL, &basemod, &base_expanded, 0, 0)) CU_FAIL_FATAL("Failed to expand policy"); if ((handle = sepol_handle_create()) == NULL) CU_FAIL_FATAL("Failed to initialize handle"); sepol_msg_set_callback(handle, msg_handler, NULL); if (check_assertions(handle, &base_expanded, base_expanded.global->branch_list->avrules) != -1) CU_FAIL("Assertions did not trigger"); messages_check(ARRAY_SIZE(expected_messages), expected_messages); sepol_handle_destroy(handle); messages_clean(); policydb_destroy(&basemod); policydb_destroy(&base_expanded); } int neverallow_add_tests(CU_pSuite suite) { /* * neverallow rules operate only on types and are unaffected by MLS * (avoid adjusting the messages for std and mls) */ if (mls) return 0; if (NULL == CU_add_test(suite, "neverallow_basic", test_neverallow_basic)) { CU_cleanup_registry(); return CU_get_error(); } if (NULL == CU_add_test(suite, "neverallow_not_self", test_neverallow_not_self)) { CU_cleanup_registry(); return CU_get_error(); } if (NULL == CU_add_test(suite, "neverallow_minus_self", test_neverallow_minus_self)) { CU_cleanup_registry(); return CU_get_error(); } if (NULL == CU_add_test(suite, "neverallow_cond", test_neverallow_cond)) { CU_cleanup_registry(); return CU_get_error(); } return 0; } libsepol-3.8.1/tests/test-neverallow.h000066400000000000000000000003441476211737200200150ustar00rootroot00000000000000#ifndef TEST_NEVERALLOW_H__ #define TEST_NEVERALLOW_H__ #include int neverallow_test_init(void); int neverallow_test_cleanup(void); int neverallow_add_tests(CU_pSuite suite); #endif /* TEST_NEVERALLOW_H__ */ libsepol-3.8.1/utils/000077500000000000000000000000001476211737200145065ustar00rootroot00000000000000libsepol-3.8.1/utils/Makefile000066400000000000000000000006621476211737200161520ustar00rootroot00000000000000# Installation directories. PREFIX ?= /usr BINDIR ?= $(PREFIX)/bin CFLAGS ?= -Wall -Werror override CFLAGS += -I../include override LDFLAGS += -L../src override LDLIBS += -lsepol TARGETS=$(patsubst %.c,%,$(sort $(wildcard *.c))) all: $(TARGETS) install: all -mkdir -p $(DESTDIR)$(BINDIR) install -m 755 $(TARGETS) $(DESTDIR)$(BINDIR) clean: -rm -f $(TARGETS) *.o indent: ../../scripts/Lindent $(wildcard *.[ch]) relabel: libsepol-3.8.1/utils/chkcon.c000066400000000000000000000014421476211737200161200ustar00rootroot00000000000000#include #include #include #include #include #include #include void usage(char*) __attribute__((noreturn)); void usage(char *progname) { printf("usage: %s policy context\n", progname); exit(1); } int main(int argc, char **argv) { FILE *fp; if (argc != 3) usage(argv[0]); fp = fopen(argv[1], "r"); if (!fp) { fprintf(stderr, "Can't open '%s': %s\n", argv[1], strerror(errno)); exit(1); } if (sepol_set_policydb_from_file(fp) < 0) { fprintf(stderr, "Error while processing %s: %s\n", argv[1], strerror(errno)); exit(1); } fclose(fp); if (sepol_check_context(argv[2]) < 0) { fprintf(stderr, "%s is not valid\n", argv[2]); exit(1); } printf("%s is valid\n", argv[2]); exit(0); } libsepol-3.8.1/utils/sepol_check_access.c000066400000000000000000000054351476211737200204610ustar00rootroot00000000000000#include #include #include #include #include #include int main(int argc, char *argv[]) { FILE *fp; sepol_security_id_t ssid, tsid; sepol_security_class_t tclass; const char *permlist; sepol_access_vector_t av; struct sepol_av_decision avd; unsigned int reason; char *reason_buf; int i; if (argc != 6) { printf("usage: %s policy source_context target_context class permission[,permission2[,...]]\n", argv[0]); return 1; } fp = fopen(argv[1], "r"); if (!fp) { fprintf(stderr, "Can't open policy %s: %s\n", argv[1], strerror(errno)); return 1; } if (sepol_set_policydb_from_file(fp) < 0) { fprintf(stderr, "Error while processing policy %s: %s\n", argv[1], strerror(errno)); fclose(fp); return 1; } fclose(fp); if (sepol_context_to_sid(argv[2], strlen(argv[2]), &ssid) < 0) { fprintf(stderr, "Invalid source context %s\n", argv[2]); return 1; } if (sepol_context_to_sid(argv[3], strlen(argv[3]), &tsid) < 0) { fprintf(stderr, "Invalid target context %s\n", argv[3]); return 1; } if (sepol_string_to_security_class(argv[4], &tclass) < 0) { fprintf(stderr, "Invalid security class %s\n", argv[4]); return 1; } permlist = argv[5]; do { char *tmp = NULL; const char *perm; const char *delim = strchr(permlist, ','); if (delim) { tmp = strndup(permlist, delim - permlist); if (!tmp) { fprintf(stderr, "Failed to allocate memory: %s\n", strerror(errno)); return 1; } } perm = tmp ? tmp : permlist; if (sepol_string_to_av_perm(tclass, perm, &av) < 0) { fprintf(stderr, "Invalid permission %s for security class %s: %s\n", perm, argv[4], strerror(errno)); free(tmp); return 1; } free(tmp); permlist = strchr(permlist, ','); } while (permlist++); if (av == 0) { fprintf(stderr, "Empty permission set computed from %s\n", argv[5]); return 1; } if (sepol_compute_av_reason_buffer(ssid, tsid, tclass, av, &avd, &reason, &reason_buf, 0) < 0) { fprintf(stderr, "Failed to compute av decision: %s\n", strerror(errno)); return 1; } if ((avd.allowed & av) == av) { printf("requested permission %s allowed\n", argv[5]); free(reason_buf); return 0; } printf("requested permission %s denied by ", argv[5]); i = 0; if (reason & SEPOL_COMPUTEAV_TE) { printf("te-rule"); i++; } if (reason & SEPOL_COMPUTEAV_CONS) { if (i > 0) printf(", "); printf("constraint"); i++; } if (reason & SEPOL_COMPUTEAV_RBAC) { if (i > 0) printf(", "); printf("role-transition"); i++; } if (reason & SEPOL_COMPUTEAV_BOUNDS) { if (i > 0) printf(", "); printf("type-bound"); //i++; } if ((reason & SEPOL_COMPUTEAV_CONS) && reason_buf) printf("; reason:\n%s", reason_buf); free(reason_buf); printf("\n"); return 7; } libsepol-3.8.1/utils/sepol_compute_av.c000066400000000000000000000031701476211737200202170ustar00rootroot00000000000000#include #include #include #include #include #include int main(int argc, char *argv[]) { FILE *fp; sepol_security_id_t ssid, tsid; sepol_security_class_t tclass; struct sepol_av_decision avd; int rc; if (argc != 5) { printf("usage: %s policy scontext tcontext tclass\n", argv[0]); return 1; } fp = fopen(argv[1], "r"); if (!fp) { fprintf(stderr, "Can't open policy %s: %s\n", argv[1], strerror(errno)); return 1; } if (sepol_set_policydb_from_file(fp) < 0) { fprintf(stderr, "Error while processing policy %s: %s\n", argv[1], strerror(errno)); fclose(fp); return 1; } fclose(fp); if (sepol_context_to_sid(argv[2], strlen(argv[2]), &ssid) < 0) { fprintf(stderr, "Invalid source context %s\n", argv[2]); return 1; } if (sepol_context_to_sid(argv[3], strlen(argv[3]), &tsid) < 0) { fprintf(stderr, "Invalid target context %s\n", argv[3]); return 1; } if (sepol_string_to_security_class(argv[4], &tclass) < 0) { fprintf(stderr, "Invalid security class %s\n", argv[4]); return 1; } rc = sepol_compute_av(ssid, tsid, tclass, 0, &avd); switch (rc) { case 0: printf("allowed: %s\n", sepol_av_perm_to_string(tclass, avd.allowed)); printf("decided: %s\n", sepol_av_perm_to_string(tclass, avd.decided)); printf("auditallow: %s\n", sepol_av_perm_to_string(tclass, avd.auditallow)); printf("auditdeny: %s\n", sepol_av_perm_to_string(tclass, avd.auditdeny)); break; case -EINVAL: printf("Invalid request\n"); break; default: printf("Failed to compute av decision: %d\n", rc); } return rc != 0; } libsepol-3.8.1/utils/sepol_compute_member.c000066400000000000000000000027261476211737200210660ustar00rootroot00000000000000#include #include #include #include #include #include int main(int argc, char *argv[]) { FILE *fp; sepol_security_id_t ssid, tsid, out_sid; sepol_security_class_t tclass; char *context; size_t context_len; if (argc != 5) { printf("usage: %s policy scontext tcontext tclass\n", argv[0]); return 1; } fp = fopen(argv[1], "r"); if (!fp) { fprintf(stderr, "Can't open policy %s: %s\n", argv[1], strerror(errno)); return 1; } if (sepol_set_policydb_from_file(fp) < 0) { fprintf(stderr, "Error while processing policy %s: %s\n", argv[1], strerror(errno)); fclose(fp); return 1; } fclose(fp); if (sepol_context_to_sid(argv[2], strlen(argv[2]), &ssid) < 0) { fprintf(stderr, "Invalid source context %s\n", argv[2]); return 1; } if (sepol_context_to_sid(argv[3], strlen(argv[3]), &tsid) < 0) { fprintf(stderr, "Invalid target context %s\n", argv[3]); return 1; } if (sepol_string_to_security_class(argv[4], &tclass) < 0) { fprintf(stderr, "Invalid security class %s\n", argv[4]); return 1; } if (sepol_member_sid(ssid, tsid, tclass, &out_sid) < 0) { fprintf(stderr, "Failed to compute member sid: %s\n", strerror(errno)); return 1; } if (sepol_sid_to_context(out_sid, &context, &context_len) < 0) { fprintf(stderr, "Failed to convert sid %u: %s\n", out_sid, strerror(errno)); return 1; } printf("%s\n", context); free(context); return 0; } libsepol-3.8.1/utils/sepol_compute_relabel.c000066400000000000000000000027271476211737200212260ustar00rootroot00000000000000#include #include #include #include #include #include int main(int argc, char *argv[]) { FILE *fp; sepol_security_id_t ssid, tsid, out_sid; sepol_security_class_t tclass; char *context; size_t context_len; if (argc != 5) { printf("usage: %s policy scontext tcontext tclass\n", argv[0]); return 1; } fp = fopen(argv[1], "r"); if (!fp) { fprintf(stderr, "Can't open policy %s: %s\n", argv[1], strerror(errno)); return 1; } if (sepol_set_policydb_from_file(fp) < 0) { fprintf(stderr, "Error while processing policy %s: %s\n", argv[1], strerror(errno)); fclose(fp); return 1; } fclose(fp); if (sepol_context_to_sid(argv[2], strlen(argv[2]), &ssid) < 0) { fprintf(stderr, "Invalid source context %s\n", argv[2]); return 1; } if (sepol_context_to_sid(argv[3], strlen(argv[3]), &tsid) < 0) { fprintf(stderr, "Invalid target context %s\n", argv[3]); return 1; } if (sepol_string_to_security_class(argv[4], &tclass) < 0) { fprintf(stderr, "Invalid security class %s\n", argv[4]); return 1; } if (sepol_change_sid(ssid, tsid, tclass, &out_sid) < 0) { fprintf(stderr, "Failed to compute changed sid: %s\n", strerror(errno)); return 1; } if (sepol_sid_to_context(out_sid, &context, &context_len) < 0) { fprintf(stderr, "Failed to convert sid %u: %s\n", out_sid, strerror(errno)); return 1; } printf("%s\n", context); free(context); return 0; } libsepol-3.8.1/utils/sepol_validate_transition.c000066400000000000000000000033001476211737200221130ustar00rootroot00000000000000#include #include #include #include #include #include int main(int argc, char *argv[]) { FILE *fp; sepol_security_id_t oldsid, newsid, tasksid; sepol_security_class_t tclass; char *reason = NULL; int ret; if (argc != 6) { printf("usage: %s policy oldcontext newcontext tclass taskcontext\n", argv[0]); return 1; } fp = fopen(argv[1], "r"); if (!fp) { fprintf(stderr, "Can't open policy %s: %s\n", argv[1], strerror(errno)); return 1; } if (sepol_set_policydb_from_file(fp) < 0) { fprintf(stderr, "Error while processing policy %s: %s\n", argv[1], strerror(errno)); fclose(fp); return 1; } fclose(fp); if (sepol_context_to_sid(argv[2], strlen(argv[2]), &oldsid) < 0) { fprintf(stderr, "Invalid old context %s\n", argv[2]); return 1; } if (sepol_context_to_sid(argv[3], strlen(argv[3]), &newsid) < 0) { fprintf(stderr, "Invalid new context %s\n", argv[3]); return 1; } if (sepol_string_to_security_class(argv[4], &tclass) < 0) { fprintf(stderr, "Invalid security class %s\n", argv[4]); return 1; } if (sepol_context_to_sid(argv[5], strlen(argv[5]), &tasksid) < 0) { fprintf(stderr, "Invalid task context %s\n", argv[5]); return 1; } ret = sepol_validate_transition_reason_buffer(oldsid, newsid, tasksid, tclass, &reason, SHOW_GRANTED); switch (ret) { case 0: printf("allowed\n"); ret = 0; break; case -EPERM: printf("denied\n"); printf("%s\n", reason ? reason : "unknown - possible BUG()"); ret = 7; break; default: printf("sepol_validate_transition_reason_buffer returned %d errno: %s\n", ret, strerror(errno)); ret = 1; } free(reason); return ret; }