Basic policy representation
PATCH 1/1 Basic policy representation
Add support for the basic policy object model and the sepol_policy and sepol_module objects to libsepol. This version has significant changes from the last posted version:
1) sepol_handle is passed everywhere
2) public and private interfaces to the object system are correctly split (into policy.[c,h] and policy_internal.[c,h].
3) object ouput has been converted from writing to a FILE to returning allocated strings. This will help integrate better with scripting languages.
4) Basic documentation is included for the base objects.
5) Enums are used instead of defines - this is a change from the style for libsepol, but it makes documenting the enums much easier.
This version includes updates based on comments from Josh Brindle, Stephen Smalley, James Antill, and Jason Tang.
---
8 files changed, 1750 insertions(+) libsepol/include/sepol/policy.h | 541 ++++++++++++++++++++++++++++++ libsepol/src/libsepol.map | 4 libsepol/src/policy.c | 690 +++++++++++++++++++++++++++++++++++++++ libsepol/src/policy_internal.c | 103 +++++ libsepol/src/policy_internal.h | 281 +++++++++++++++ libsepol/tests/libsepol-tests.c | 2 libsepol/tests/test-policy.c | 117 ++++++ libsepol/tests/test-policy.h | 12
libsepol/include/sepol/policy.h +541 -0
@@ -0,0 +1,541 @@ +/* Author : Karl MacMillan <[email protected]> */ + +#ifndef __sepol_policy_h__ +#define __sepol_policy_h__ + +#include <sepol/handle.h> + +#include <sepol/objpool.h> +#include <sepol/objset.h> +#include <sepol/list.h> + +#include <sys/types.h> +#include <stdint.h> +#include <stdio.h> + +/** +* \defgroup sepol_policy sepol_policy: policy representation +* Introduction to the policy object system +* +* +* The policy is represented as a tree of objects that loosely +* resemble an abstract syntax tree or intermediate representation +* commonly found in compilers. This tree representation is used as +* the output of the policy parser the format for selinux policy +* modules. The data structures are also intended to be flexible +* enough to represent an selinux policy for syntax/semantic checking, +* analysis, generation, and storage. +* +* The basic structure is that of a tree holding selinux policy +* language components (e.g., type declarations, rules, conditional +* blocks, etc.). To implement this tree structure in a form that can +* be processed easily, a basic object orientied structure is +* implemented in C. +* +* The object oriented system allows the use of polymorphic functions, +* making it possible to process objects in the tree with only limited +* informatio about the specific types (e.g., it is possible to +* traverse the tree and output all of the objects as strings without +* the traversal function knowing detailed type information about each +* object - it simple class sepol_object_strout on each object). +* +* See sepol_object and sepol_parent for more information on this object +* oriented type system. +* +*/ + +/** +* \ingroup sepol_policy +* +* Every type in the policy object system is identified +* by a numberic typeid. +*/ +enum sepol_typeid { +SEPOL_TYPEID_NONE ,/** special typeid representing no type */ +SEPOL_TYPEID_OBJECT ,/** typeid for base class of all objects */ +SEPOL_TYPEID_PARENT ,/** typeid for base class of objects that contain other objects */ +SEPOL_TYPEID_POLICY ,/** typeid for policy object */ +SEPOL_TYPEID_MODULE ,/** typeid for the module object */ +SEPOL_TYPEID_BLOCK ,/** tyepid for the block object */ +SEPOL_TYPEID_COND ,/** typeid for the cond object */ +SEPOL_TYPEID_OPTIONAL ,/** typeid for the optional object */ +SEPOL_TYPEID_TYPE ,/** typed for the type object */ +SEPOL_TYPEID_CLASS ,/** typeid for the class object */ +SEPOL_TYPEID_ATTRIBUTE ,/** typeid for the attribute object */ +SEPOL_TYPEID_TYPEALIAS ,/** typeid for the typealias object */ +SEPOL_TYPEID_BOOL ,/** typeid for the bool object */ +SEPOL_TYPEID_AVRULE ,/** typeid for the avrule object */ +SEPOL_TYPEID_TYPERULE ,/** typeid for the typerule object */ +SEPOL_TYPEID_SECURITY_CONTEXT ,/** typeid for the securit context object */ +SEPOL_TYPEID_ISID ,/** typeid for the isid object */ +SEPOL_TYPEID_TYPEATTRIBUTE ,/** typeid for the typeattribute object */ +SEPOL_TYPEID_COND_EXPR ,/** typeid for the cond expr object */ +SEPOL_TYPEID_SENS ,/** typeid for the sends object */ +SEPOL_TYPEID_DOMINANCE ,/** typeid for the dominance object */ +SEPOL_TYPEID_CATEGORY ,/** typeid for the category object */ +SEPOL_TYPEID_ROLE_DOMINANCE ,/** typeid for the role dominance object */ +SEPOL_TYPEID_ROLE /** typeid for the role object */ +}; + +/** +* \ingroup sepol_policy +* +* Convert a typeid to a string representation. The returned string +* is constant and should not be altered or freed. +* +* @param typeid typeid to convert to string +* +* \retval string string representing the typeid +*/ +const char *sepol_typeid_tostring (enum sepol_typeid typeid); + +/** +* \ingroup sepol_policy +* \struct sepol_object +* +* sepol_object is the base class of all objects in this type system. +* There is no way to directly create an sepol_object - it is an +* abstract base class. +* +* The type system works by: +* - mandating that sepol_object (or one of its subclasses) be the +* first entry in every struct. This allows the structs to be +* freely cast to an sepol_object or any of the other objects +* in the hierarchy of that struct. +* - Storing information about the types in the form of IDs. This +* allows callers to determine type information at runtime. +* - Storing function pointers to class specific function +* implementations in each object instance. This allows functions +* to have a limited form of polymorphism. +* +* sepol_object is also the parent class of all objects that are +* exclusively leaves in the tree (i.e., objects that cannot contain +* other objects). +* +* Properties that all sepol_objects share: +* - string pool (strpool): [optional] an objpool for storing +* strings stored in the objects. The object may be the owner of +* the string pool (see sepol_object_is_strpool_owner), reference +* the string pool of another object (usually the root of a policy +* tree), or not have a string pool at all. +* - type identifier (typeid): The sepol_typeid for this object. +*/ +struct sepol_object ; + +/** +* \ingroup sepol_policy +* +* Convert an object to an sepol_object +* +* @param x object +*/ +#define SEPOL_OBJECT (x) ((struct sepol_object *)x) + +/** +* \ingroup sepol_policy +* +* Free an sepol_object. This can be called for any +* subclass of sepol_object. +* +* @param n object to free +* +* \retval SEPOL_OK success +* \retval <0 error +*/ +extern void sepol_object_free (struct sepol_object *o); + +/** +* \ingroup sepol_policy +* +* Return the typeid for the object. +* +* @param o object from which to return the type id. +* +* \retval >0 typeid for the object +*/ +extern uint32_t sepol_object_get_typeid (struct sepol_object *o); + +/** +* \ingroup sepol_policy +* +* Determine whether the object is an instance of the object type +* represented by a typeid. This function checks both the specific +* object type (as returned by sepol_object_get_typeid) and the +* parent type for the object. +* +* @param o object to check +* @param typeid typeid +* +* \retval 0 object is not an instance of the type +* \retval 1 object is an instance of the type +*/ +extern int sepol_object_isinstance (struct sepol_object *o,uint32_t typeid); + +/** +* \ingroup sepol_policy +* +* Make this object the owner of a string pool. See sepol_object for +* more information on string pools. +* +* @param o object to which to add string pool +* +* \retval SEPOL_OK success +* \retval SEPOL_ENOMEM out of memory +*/ +extern int sepol_object_create_strpool (struct sepol_handle *h,struct sepol_object *o); + +/** +* \ingroup sepol_policy +* +* Return the strpool for this object if any. +* +* @param o object from which to return string pool. +* +* \retval non-NULL string pool this object is using. +* \retval NULL object does not use string pool. +*/ +extern struct sepol_objpool *sepol_object_get_strpool (struct sepol_object *o); + +/** +* \ingroup sepol_policy +* +* Determine whether the object is the owner of its string pool (if +* it has one). +* +* @param o object to check +* +* \retval 0 object does not own or does not have a string pool +* \retval 1 object owns its string pool +*/ +extern int sepol_object_is_strpool_owner (struct sepol_object *o); + +/** +* \ingroup sepol_policy +* +* Return the parent of this object (if any). +* +* @param o object for which to return parent +* +* \retval non-NULL pointer to parent object +* \retval NULL object has no parent +*/ +extern struct sepol_parent *sepol_object_get_parent (struct sepol_object *o); + +/** +* \ingroup sepol_policy +* +* Specify the output for various sepol_*_tostring functions. +*/ +enum sepol_tostring_style { +SEPOL_TOSTRING_RAW ,/** raw policy language */ +SEPOL_TOSTRING_REFPOL ,/** refpol style output */ +SEPOL_TOSTRING_DEBUG /** debugging output */ +}; + +/** +* \ingroup sepol_policy +* +* Convert an sepol_object into a string representation. If the +* returned string is of 0 length (return is 0), str will be an +* allocated, 0 length string that should be freed by the caller. +* +* @param h sepol_handle (may be NULL) +* @param o object to convert to a string +* @param style style of the output - see sepol_tostring_style +* @param str output string - this string is allocated by the function +* and should be freed by the caller using free() +* +* \retval >=0 Success - the size of the string is returned +* \retval <0 Failure - str will be undefined and does not need to be freed. +*/ +extern int sepol_object_tostring (struct sepol_handle *h,struct sepol_object *o, +enum sepol_tostring_style style,char **str); + +/** +* \ingroup sepol_policy +* +* Convert an sepol_object into a string representation for the +* closure of that object. Some objects - typically that contain +* other objects - need a string to represent the beginning _and_ +* the end of that object. For example: +* +* \code +* if (foo) { +* allow foo bar : file read; +* } +* \endcode +* +* In this example "if (foo) }" would be printed by +* sepol_object_tostring and "}} printed by +* sepol_object_tostring_close on the same conditional object. If the +* returned string is of 0 length (return is 0), str will be an +* allocated, 0 length string that should be freed by the caller. +* +* @param h sepol_handle (may be NULL) +* @param o object to convert to a string +* @param style style of the output - see sepol_tostring_style +* @param str output string - this string is allocated by the function +* and should be freed by the caller using free() +* +* \retval >=0 Success - the size of the string is returned +* \retval <0 Failure - str will be undefined and does not need to be freed. +*/ +extern int sepol_object_tostring_close (struct sepol_handle *h,struct sepol_object *o, +enum sepol_tostring_style style,char **str); + +/** +* \ingroup sepol_policy +* \struct sepol_parent +* +* sepol_parent is the parent class of all objects that can contain +* other objects in the tree. Having a single base class for all parent +* objects allows writing functions that can traverse the tree without +* knowing the details about most of the objects in the tree. +*/ +struct sepol_parent ; + +/** +* \ingroup sepol_policy +* +* Convert an object to an sepol_parent +* +* @param x object +*/ +#define SEPOL_PARENT (x) ((struct sepol_parent *)x) + +/** +* \ingroup sepol_policy +* +* Free a parent object and all of its children (if any). This +* function traverses a policy tree starting at the parent node passed +* in destroy each object it encounters (by (calling +* sepol_object_free). +* +* @param h sepol_handle (may be NULL) +* @param p sepol_parent object +* +* \retval SEPOL_OK success +* \retval SEPOL_ENOMEM out of memory +*/ +extern void sepol_parent_free_tree (struct sepol_parent *p); + +/** +* \ingroup sepol_policy +* +* Append an object as a child of this parent. An object can only +* be the child of a single parent - to move an object from one +* part of the tree to another (and change the parent), remove the +* child from the current parent first before appending to the new +* parent. +* +* @param h sepol_handle (may be NULL) +* @param p sepol_parent to which to append child object +* @param o object to append (parent will be set) +* +* \retval SEPOL_OK success +* \retval SEPOL_EEXIST object is already a child of another parent +* \retval SEPOL_ENOMEM out of memory +*/ +extern int sepol_parent_append (struct sepol_handle *h,struct sepol_parent *p, +struct sepol_object *o); + +/** +* \ingroup sepol_policy +* +* Extend the children of an sepol_parent with the objects returned by +* an iterator. Each object will be appended using +* sepol_parent_append. If there is an error from adding any of the +* children some of the objects may have been added. The iterator will +* be left in the position of the object that caused an error. +* +* @param h sepol_handle (may be NULL) +* @param p sepol_parent to which to add children +* @param iter iterator from which to add children +* +* \retval SEPOL_OK success +* \retval SEPOL_EEXIST object is already a child of another parent +* \retval SEPOL_ENOMEM out of memory +*/ +extern int sepol_parent_extend (struct sepol_handle *h,struct sepol_parent *p, +struct sepol_iter *iter); + +/** +* \ingroup sepol_policy +* +* Convenience function similar to sepol_parent_extend that takes a +* list instead of an interator. +* +* @param h sepol_handle (may be NULL) +* @param p sepol_parent to which to add objects +* @param list sepol_list from which to add objects +* +* \retval SEPOL_OK success +* \retval SEPOL_EEXIST object is already a child of another parent +* \retval SEPOL_ENOMEM out of memory +*/ +extern int sepol_parent_extend_list (struct sepol_handle *h,struct sepol_parent *p, +struct sepol_list *list); + +/** +* \ingroup sepol_policy +* +* Delete a child object from the sepol_parent. Like sepol_list_del, +* the iterator will not be valid after a call to this function. +* +* @param h sepol_handle (may be NULL) +* @param p sepol_parent from which to delete child +* @param iter iterator pointing to a child object of p +* +* \retval SEPOL_OK success +*/ +extern void sepol_parent_del (struct sepol_parent *p,struct sepol_iter *iter); + +/** +* \ingroup sepol_policy +* +* Insert a child object into the list of children for the +* sepol_parent. See sepol_list_insert for more information on the +* semantics of this insert. +* +* @param h sepol_handle (may be NULL) +* @param p sepol_parent to which to insert child object +* @param iter iterator representing the position to insert the child object +* @param o child object to insert +* +* \retval SEPOL_OK success +* \retval SEPOL_EEXIST object is already a child of another parent +* \retval SEPOL_ENOMEM out of memory +*/ +extern int sepol_parent_insert (struct sepol_handle *h,struct sepol_parent *p, +struct sepol_iter *iter,struct sepol_object *o); + +/** +* \ingroup sepol_policy +* +* Set an iterator to iterate over the children of an sepol_parent. +* +* @param h sepol_handle (may be NULL) +* @param p sepol_parent +* @param iter iterator to set to iterate over children +* +* \retval SEPOL_OK success +* \retval SEPOL_ENOMEM out of memory +*/ +extern int sepol_parent_children_begin (struct sepol_handle *h,struct sepol_parent *p, +struct sepol_iter *iter); + +/** +* \ingroup sepol_policy +* +* Return the list containing the children of the sepol_parent +* object. This is the actual list used to store children of the +* object, so changes will be reflected in the sepol_parent. It is +* important that deletions and insertions use sepol_parent_del and +* sepol_parent_insert or that the parent property of the objects +* is properly set. +* +* @param p sepol_parent +* +* \retval non-NULL pointer to the list of children +*/ +struct sepol_list *sepol_parent_get_children (struct sepol_parent *parent); + + +/** +* \ingroup sepol_policy +* +* Traversal of a policy tree rooted at a sepol_parent can take many +* forms. This enumeration is used to set the traversal strategy. See +* http://en.wikipedia.org/wiki/Tree_traversal for more information. +* +* The hybrid strategy combines both preorder and postorder +* traversal. This means that each parent node will be visited twice: +* once before its children are traversed and once afterward. The +* second traversal can be detected by checking the flag indicating +* that the parent has been visited (see sepol_parent_isvisited). +*/ +enum sepol_parent_traverse_strategy { +SEPOL_TRAVERSE_POSTORDER ,/** traverse the tree in postorder */ +SEPOL_TRAVERSE_PREORDER ,/** traverse the tree in preorder */ +SEPOL_TRAVERSE_HYBRID /** traverse the tree combining preorder and postorder */ +}; + +/** +* \ingroup sepol_policy +* +* Traverse a policy tree using parent as the root node of the tree. The traversal +* strategy is controlled by sepol_parent_traverse_strategy. +* +* @param h sepol_handle (may be null) +* @param parent sepol_parent +* @param iter iterator to represent traversal state +* @param strategy traversal strategy - see sepol_parent_traverse_strategy +* +* \retval SEPOL_OK success +* \retval SEPOL_ENOMEM out of memory +*/ +extern int sepol_parent_traverse (struct sepol_handle *h,struct sepol_parent *parent, +struct sepol_iter *iter,int strategy); + +/** +* \ingroup sepol_policy +* +* Return whether an object has already been visited before during this tree +* traversal. See sepol_parent_traverse_strategy for more information. +* +* @param iter iterator +* +* \retval 0 object has not been previously visited +* \retval 1 object has been previously visited +*/ +int sepol_parent_isvisited (struct sepol_iter *iter); + +/** +* \ingroup sepol_policy +* +* Output a formatted, string representation of a policy tree +* to a file descriptor. +* +* @param h sepol_handle (may be null) +* @param p root of policy tree to output +* @param style output style +* @param fp file point to which to output +* +* \retval SEPOL_OK success +* \retval SEPOL_ENOMEM out of memory +*/ +int sepol_parent_output_tree (struct sepol_handle *h,struct sepol_parent *p, +int style,FILE *fp); + +struct sepol_policy ; + +extern void sepol_policy_free (struct sepol_policy *o); +extern int sepol_policy_create (struct sepol_handle *h, +struct sepol_policy **policy); + +extern int sepol_policy_get_ismls (struct sepol_policy *o); +extern int sepol_policy_set_ismls (struct sepol_handle *h,struct sepol_policy *o, +int mls); + +struct sepol_module ; + +extern void sepol_module_free (struct sepol_module *o); +extern int sepol_module_create (struct sepol_handle *h, +struct sepol_module **module); +extern int sepol_module_create_tree (struct sepol_handle *h, +struct sepol_module **module, +struct sepol_parent *root); + +int sepol_module_set_name (struct sepol_handle *h,struct sepol_module *module, +char *name); +const char *sepol_module_get_name (struct sepol_module *module); + +int sepol_module_set_version (struct sepol_handle *h,struct sepol_module *module, +char *version); +const char *sepol_module_get_version (struct sepol_module *module); + +int sepol_module_set_isbase (struct sepol_handle *h,struct sepol_module *module, +int isbase); +int sepol_module_get_isbase (struct sepol_module *module); + +#endif
libsepol/src/libsepol.map +4 -0
@@ -12,5 +12,9 @@ LIBSEPOL_2.0 { sepol_policydb_*; sepol_set_policydb_from_file; sepol_policy_kern_*; sepol_policy_file_*; + sepol_object_*; + sepol_parent_*; + sepol_policy_*; + sepol_module_*; local: *; };
libsepol/src/policy.c +690 -0
690 lines not on this page · raw message
libsepol/src/policy_internal.c +103 -0
103 lines not on this page · raw message
libsepol/src/policy_internal.h +281 -0
281 lines not on this page · raw message
libsepol/tests/libsepol-tests.c +2 -0
@@ -26,6 +26,7 @@#include "test-hashtab.h" #include "test-objpool.h" #include "test-objset.h" +#include "test-policy.h" #include <CUnit/Basic.h> #include <CUnit/Console.h>
@@ -69,6 +70,7 @@ static int do_tests(int interactive, intDECLARE_SUITE (hashtab);DECLARE_SUITE (objpool);DECLARE_SUITE (objset); +DECLARE_SUITE (policy);if (verbose)CU_basic_set_mode (CU_BRM_VERBOSE );
libsepol/tests/test-policy.c +117 -0
117 lines not on this page · raw message
libsepol/tests/test-policy.h +12 -0
@@ -0,0 +1,12 @@ +/* Author : Karl MacMillan <[email protected]> */ + +#ifndef __test_policy_h__ +#define __test_policy_h__ + +#include <CUnit/Basic.h> + +int policy_test_init (void ); +int policy_test_cleanup (void ); +int policy_add_tests (CU_pSuite suite); + +#endif
--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.