All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] secilc: Add support for unordered classes
@ 2015-11-10 15:58 ykhodorkovskiy
  2015-11-10 16:08 ` Dominick Grift
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: ykhodorkovskiy @ 2015-11-10 15:58 UTC (permalink / raw)
  To: selinux

From: Yuli Khodorkovskiy <ykhodorkovskiy@tresys.com>

Resolves https://github.com/SELinuxProject/cil/issues/3

An 'unordered' keyword provides the ability to append classes to the current
list of ordered classes. This allows users to not need knowledge of existing
classes when creating a class and fixes dependencies on classes when removing a
module. This enables userspace object managers with custom objects to be
modularized.

If a class is declared in both an unordered and ordered statement, then the
ordered statement will supercede the unordered declaration.

Example usage:

    ; Appends new_class to the existing list of classes
    (class new_class ())
    (classorder (unordered new_class))

Signed-off-by: Yuli Khodorkovskiy <ykhodorkovskiy@tresys.com>
---
 libsepol/cil/src/cil.c                             |  1 +
 libsepol/cil/src/cil_build_ast.c                   | 52 ++++++++++++
 libsepol/cil/src/cil_internal.h                    |  1 +
 libsepol/cil/src/cil_list.c                        | 13 +++
 libsepol/cil/src/cil_list.h                        |  1 +
 libsepol/cil/src/cil_resolve_ast.c                 | 98 +++++++++++++++++++---
 .../docs/cil_class_and_permission_statements.xml   | 16 ++++
 secilc/test/policy.cil                             | 15 +++-
 8 files changed, 184 insertions(+), 13 deletions(-)

diff --git a/libsepol/cil/src/cil.c b/libsepol/cil/src/cil.c
index 8716deb..e6e553b 100644
--- a/libsepol/cil/src/cil.c
+++ b/libsepol/cil/src/cil.c
@@ -230,6 +230,7 @@ static void cil_init_keys(void)
 	CIL_KEY_DONTAUDITX = cil_strpool_add("dontauditx");
 	CIL_KEY_PERMISSIONX = cil_strpool_add("permissionx");
 	CIL_KEY_IOCTL = cil_strpool_add("ioctl");
+	CIL_KEY_UNORDERED = cil_strpool_add("unordered");
 }
 
 void cil_db_init(struct cil_db **db)
diff --git a/libsepol/cil/src/cil_build_ast.c b/libsepol/cil/src/cil_build_ast.c
index 861b606..0407d20 100644
--- a/libsepol/cil/src/cil_build_ast.c
+++ b/libsepol/cil/src/cil_build_ast.c
@@ -365,6 +365,11 @@ int cil_gen_class(__attribute__((unused)) struct cil_db *db, struct cil_tree_nod
 	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) {
@@ -410,6 +415,8 @@ int cil_gen_classorder(__attribute__((unused)) struct cil_db *db, struct cil_tre
 	};
 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
 	struct cil_classorder *classorder = NULL;
+	struct cil_list_item *curr = NULL;
+	struct cil_list_item *head = NULL;
 	int rc = SEPOL_ERR;
 
 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
@@ -427,6 +434,22 @@ int cil_gen_classorder(__attribute__((unused)) struct cil_db *db, struct cil_tre
 	if (rc != SEPOL_OK) {
 		goto exit;
 	}
+
+	head = classorder->class_list_str->head;
+	cil_list_for_each(curr, classorder->class_list_str) {
+		if (curr->data == CIL_KEY_UNORDERED) {
+			if (curr == head && curr->next == NULL) {
+				cil_log(CIL_ERR, "Classorder 'unordered' keyword must be followed by one or more class.\n");
+				rc = SEPOL_ERR;
+				goto exit;
+			} else if (curr != head) {
+				cil_log(CIL_ERR, "Classorder can only use 'unordered' keyword as the first item in the list.\n");
+				rc = SEPOL_ERR;
+				goto exit;
+			}
+		}
+	}
+
 	ast_node->data = classorder;
 	ast_node->flavor = CIL_CLASSORDER;
 
@@ -1107,6 +1130,7 @@ int cil_gen_sidorder(__attribute__((unused)) struct cil_db *db, struct cil_tree_
 	};
 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
 	struct cil_sidorder *sidorder = NULL;
+	struct cil_list_item *curr = NULL;
 	int rc = SEPOL_ERR;
 
 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
@@ -1124,6 +1148,15 @@ int cil_gen_sidorder(__attribute__((unused)) struct cil_db *db, struct cil_tree_
 	if (rc != SEPOL_OK) {
 		goto exit;
 	}
+
+	cil_list_for_each(curr, sidorder->sid_list_str) {
+		if (curr->data == CIL_KEY_UNORDERED) {
+			cil_log(CIL_ERR, "Sidorder cannot be unordered.\n");
+			rc = SEPOL_ERR;
+			goto exit;
+		}
+	}
+
 	ast_node->data = sidorder;
 	ast_node->flavor = CIL_SIDORDER;
 
@@ -3553,6 +3586,7 @@ int cil_gen_catorder(__attribute__((unused)) struct cil_db *db, struct cil_tree_
 	};
 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
 	struct cil_catorder *catorder = NULL;
+	struct cil_list_item *curr = NULL;
 	int rc = SEPOL_ERR;
 
 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
@@ -3570,6 +3604,15 @@ int cil_gen_catorder(__attribute__((unused)) struct cil_db *db, struct cil_tree_
 	if (rc != SEPOL_OK) {
 		goto exit;
 	}
+
+	cil_list_for_each(curr, catorder->cat_list_str) {
+		if (curr->data == CIL_KEY_UNORDERED) {
+			cil_log(CIL_ERR, "Category order cannot be unordered.\n");
+			rc = SEPOL_ERR;
+			goto exit;
+		}
+	}
+
 	ast_node->data = catorder;
 	ast_node->flavor = CIL_CATORDER;
 
@@ -3604,6 +3647,7 @@ int cil_gen_sensitivityorder(__attribute__((unused)) struct cil_db *db, struct c
 	};
 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
 	struct cil_sensorder *sensorder = NULL;
+	struct cil_list_item *curr = NULL;
 	int rc = SEPOL_ERR;
 
 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
@@ -3622,6 +3666,14 @@ int cil_gen_sensitivityorder(__attribute__((unused)) struct cil_db *db, struct c
 		goto exit;
 	}
 
+	cil_list_for_each(curr, sensorder->sens_list_str) {
+		if (curr->data == CIL_KEY_UNORDERED) {
+			cil_log(CIL_ERR, "Sensitivy order cannot be unordered.\n");
+			rc = SEPOL_ERR;
+			goto exit;
+		}
+	}
+
 	ast_node->data = sensorder;
 	ast_node->flavor = CIL_SENSITIVITYORDER;
 
diff --git a/libsepol/cil/src/cil_internal.h b/libsepol/cil/src/cil_internal.h
index a736eff..7f718d0 100644
--- a/libsepol/cil/src/cil_internal.h
+++ b/libsepol/cil/src/cil_internal.h
@@ -223,6 +223,7 @@ char *CIL_KEY_AUDITALLOWX;
 char *CIL_KEY_DONTAUDITX;
 char *CIL_KEY_PERMISSIONX;
 char *CIL_KEY_IOCTL;
+char *CIL_KEY_UNORDERED;
 
 /*
 	Symbol Table Array Indices
diff --git a/libsepol/cil/src/cil_list.c b/libsepol/cil/src/cil_list.c
index 766985e..dbd554c 100644
--- a/libsepol/cil/src/cil_list.c
+++ b/libsepol/cil/src/cil_list.c
@@ -246,3 +246,16 @@ void cil_list_remove(struct cil_list *list, enum cil_flavor flavor, void *data,
 		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;
+}
diff --git a/libsepol/cil/src/cil_list.h b/libsepol/cil/src/cil_list.h
index 16d743c..a028036 100644
--- a/libsepol/cil/src/cil_list.h
+++ b/libsepol/cil/src/cil_list.h
@@ -58,5 +58,6 @@ void cil_list_remove(struct cil_list *list, enum cil_flavor flavor, void *data,
 struct cil_list_item *cil_list_insert(struct cil_list *list, struct cil_list_item *curr, enum cil_flavor flavor, void *data);
 void cil_list_append_item(struct cil_list *list, struct cil_list_item *item);
 void cil_list_prepend_item(struct cil_list *list, struct cil_list_item *item);
+int cil_list_contains(struct cil_list *list, void *data);
 
 #endif
diff --git a/libsepol/cil/src/cil_resolve_ast.c b/libsepol/cil/src/cil_resolve_ast.c
index 0df5c63..deb3d38 100644
--- a/libsepol/cil/src/cil_resolve_ast.c
+++ b/libsepol/cil/src/cil_resolve_ast.c
@@ -59,6 +59,7 @@ struct cil_args_resolve {
 	struct cil_tree_node *blockstack;
 	struct cil_list *sidorder_lists;
 	struct cil_list *classorder_lists;
+	struct cil_list *unordered_classorder_lists;
 	struct cil_list *catorder_lists;
 	struct cil_list *sensitivityorder_lists;
 	struct cil_list *in_list;
@@ -1176,7 +1177,7 @@ void __cil_ordered_lists_destroy(struct cil_list **ordered_lists)
 {
 	struct cil_list_item *item = NULL;
 
-	if (*ordered_lists == NULL) {
+	if (ordered_lists == NULL || *ordered_lists == NULL) {
 		return;
 	}
 
@@ -1351,7 +1352,42 @@ int __cil_ordered_lists_merge(struct cil_list *old, struct cil_list *new)
 	return SEPOL_OK;
 }
 
-struct cil_list *__cil_ordered_lists_merge_all(struct cil_list **ordered_lists)
+static int insert_unordered(struct cil_list *merged, struct cil_list *unordered)
+{
+	struct cil_list_item *curr = NULL;
+	struct cil_ordered_list *unordered_list = NULL;
+	struct cil_list_item *item = NULL;
+	struct cil_list_item *ret = NULL;
+	int rc = SEPOL_ERR;
+
+	cil_list_for_each(curr, unordered) {
+		unordered_list = curr->data;
+
+		cil_list_for_each(item, unordered_list->list) {
+			if (cil_list_contains(merged, item->data)) {
+				/* item was declared in an ordered statement, which supercedes
+				 * all unordered statements */
+				if (item->flavor == CIL_CLASS) {
+					cil_log(CIL_WARN, "Ignoring '%s' as it has already been declared in classorder.\n", ((struct cil_class*)(item->data))->datum.name);
+				}
+				continue;
+			}
+
+			ret = __cil_ordered_item_insert(merged, merged->tail, item);
+			if (ret == NULL) {
+				rc = SEPOL_ERR;
+				goto exit;
+			}
+		}
+	}
+
+	rc = SEPOL_OK;
+
+exit:
+	return rc;
+}
+
+struct cil_list *__cil_ordered_lists_merge_all(struct cil_list **ordered_lists, struct cil_list **unordered_lists)
 {
 	struct cil_list *composite = NULL;
 	struct cil_list_item *curr = NULL;
@@ -1388,11 +1424,21 @@ struct cil_list *__cil_ordered_lists_merge_all(struct cil_list **ordered_lists)
 		}
 	}
 
+	if (unordered_lists != NULL) {
+		rc = insert_unordered(composite, *unordered_lists);
+		if (rc != SEPOL_OK) {
+			goto exit;
+		}
+	}
+
 	__cil_ordered_lists_destroy(ordered_lists);
+	__cil_ordered_lists_destroy(unordered_lists);
 
 	return composite;
 
 exit:
+	__cil_ordered_lists_destroy(ordered_lists);
+	__cil_ordered_lists_destroy(unordered_lists);
 	cil_list_destroy(&composite, CIL_FALSE);
 	return NULL;
 }
@@ -1401,16 +1447,23 @@ int cil_resolve_classorder(struct cil_tree_node *current, void *extra_args)
 {
 	struct cil_args_resolve *args = extra_args;
 	struct cil_list *classorder_list = args->classorder_lists;
+	struct cil_list *unordered_classorder_list = args->unordered_classorder_lists;
 	struct cil_classorder *classorder = current->data;
 	struct cil_list *new = NULL;
 	struct cil_list_item *curr = NULL;
 	struct cil_symtab_datum *datum = NULL;
-	struct cil_ordered_list *ordered = NULL;
+	struct cil_ordered_list *class_list = NULL;
 	int rc = SEPOL_ERR;
+	int unordered = CIL_FALSE;
 
 	cil_list_init(&new, CIL_CLASSORDER);
 
 	cil_list_for_each(curr, classorder->class_list_str) {
+		if (curr->data == CIL_KEY_UNORDERED) {
+			unordered = CIL_TRUE;
+			continue;
+		}
+
 		rc = cil_resolve_name(current, (char *)curr->data, CIL_SYM_CLASSES, extra_args, &datum);
 		if (rc != SEPOL_OK) {
 			cil_log(CIL_ERR, "Failed to resolve class %s in classorder\n", (char *)curr->data);
@@ -1419,10 +1472,14 @@ int cil_resolve_classorder(struct cil_tree_node *current, void *extra_args)
 		cil_list_append(new, CIL_CLASS, datum);
 	}
 
-	__cil_ordered_list_init(&ordered);
-	ordered->list = new;
-	ordered->node = current;
-	cil_list_append(classorder_list, CIL_CLASSORDER, ordered);
+	__cil_ordered_list_init(&class_list);
+	class_list->list = new;
+	class_list->node = current;
+	if (unordered) {
+		cil_list_append(unordered_classorder_list, CIL_CLASSORDER, class_list);
+	} else {
+		cil_list_append(classorder_list, CIL_CLASSORDER, class_list);
+	}
 
 	return SEPOL_OK;
 
@@ -3651,6 +3708,7 @@ int cil_resolve_ast(struct cil_db *db, struct cil_tree_node *current)
 	extra_args.macro = NULL;
 	extra_args.sidorder_lists = NULL;
 	extra_args.classorder_lists = NULL;
+	extra_args.unordered_classorder_lists = NULL;
 	extra_args.catorder_lists = NULL;
 	extra_args.sensitivityorder_lists = NULL;
 	extra_args.in_list = NULL;
@@ -3658,6 +3716,7 @@ int cil_resolve_ast(struct cil_db *db, struct cil_tree_node *current)
 
 	cil_list_init(&extra_args.sidorder_lists, CIL_LIST_ITEM);
 	cil_list_init(&extra_args.classorder_lists, CIL_LIST_ITEM);
+	cil_list_init(&extra_args.unordered_classorder_lists, CIL_LIST_ITEM);
 	cil_list_init(&extra_args.catorder_lists, CIL_LIST_ITEM);
 	cil_list_init(&extra_args.sensitivityorder_lists, CIL_LIST_ITEM);
 	cil_list_init(&extra_args.in_list, CIL_IN);
@@ -3678,11 +3737,27 @@ int cil_resolve_ast(struct cil_db *db, struct cil_tree_node *current)
 		}
 
 		if (pass == CIL_PASS_MISC1) {
-			db->sidorder = __cil_ordered_lists_merge_all(&extra_args.sidorder_lists);
-			db->classorder = __cil_ordered_lists_merge_all(&extra_args.classorder_lists);
-			db->catorder = __cil_ordered_lists_merge_all(&extra_args.catorder_lists);
+			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);
+			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) {
@@ -3718,6 +3793,7 @@ int cil_resolve_ast(struct cil_db *db, struct cil_tree_node *current)
 			if (pass >= CIL_PASS_MISC1) {
 				__cil_ordered_lists_reset(&extra_args.sidorder_lists);
 				__cil_ordered_lists_reset(&extra_args.classorder_lists);
+				__cil_ordered_lists_reset(&extra_args.unordered_classorder_lists);
 				__cil_ordered_lists_reset(&extra_args.catorder_lists);
 				__cil_ordered_lists_reset(&extra_args.sensitivityorder_lists);
 				cil_list_destroy(&db->sidorder, CIL_FALSE);
diff --git a/secilc/docs/cil_class_and_permission_statements.xml b/secilc/docs/cil_class_and_permission_statements.xml
index 2926d7c..20c3eb7 100644
--- a/secilc/docs/cil_class_and_permission_statements.xml
+++ b/secilc/docs/cil_class_and_permission_statements.xml
@@ -198,6 +198,22 @@
 (classorder (file dir))
 (classorder (dir process))]]>
       </programlisting>
+         <para><emphasis role="bold">Unordered Classorder Statement:</emphasis></para>
+         <para>If users do not have knowledge of the existing classorder, the <literal>unordered</literal> keyword may be used in a <literal>classorder</literal> statement. The <link linkend="class">class</link>es in an unordered statement are appended to the existing classorder. A class in an ordered statement always supercedes the class redeclaration in an unordered statement. The <literal>unordered</literal> keyword must be the first item in the classorder listing.</para>
+         <para><emphasis role="bold">Example:</emphasis></para>
+         <para>This will produce an ordered list of "<literal>file dir foo a bar baz</literal>"</para>
+         <programlisting><![CDATA[
+(class file)
+(class dir)
+(class foo)
+(class bar)
+(class baz)
+(class a)
+(classorder (file dir))
+(classorder (dir foo))
+(classorder (unordered a))
+(classorder (unordered bar foo baz))]]>
+      </programlisting>
       </sect2>
      <sect2 id="classpermission">
          <title>classpermission</title>
diff --git a/secilc/test/policy.cil b/secilc/test/policy.cil
index 69103d1..884d2dc 100644
--- a/secilc/test/policy.cil
+++ b/secilc/test/policy.cil
@@ -46,8 +46,13 @@
 (levelrange lh4 ((s0) (s1)))
 
 (block policy
-	(classorder (file char dir))
-	(class file (execute_no_trans entrypoint execmod open audit_access))
+	(class file (execute_no_trans entrypoint execmod open audit_access a b c d e))
+	; order should be: file char b c a dir d e f
+	(classorder (file char))
+	(classorder (unordered dir))
+	(classorder (unordered c a b d e f))
+	(classorder (char b c a))
+
 	(common file (ioctl read write create getattr setattr lock relabelfrom
 			relabelto append unlink link rename execute swapon
 			quotaon mounton))
@@ -67,6 +72,12 @@
 	(classcommon char file)
 
 	(class dir ())
+	(class a ())
+	(class b ())
+	(class c ())
+	(class d ())
+	(class e ())
+	(class f ())
 	(classcommon dir file)
 
 	(classpermission char_w)
-- 
2.4.3

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH] secilc: Add support for unordered classes
  2015-11-10 15:58 [PATCH] secilc: Add support for unordered classes ykhodorkovskiy
@ 2015-11-10 16:08 ` Dominick Grift
  2015-11-10 16:21 ` Dominick Grift
  2015-11-13 15:18 ` James Carter
  2 siblings, 0 replies; 4+ messages in thread
From: Dominick Grift @ 2015-11-10 16:08 UTC (permalink / raw)
  To: ykhodorkovskiy; +Cc: selinux

[-- Attachment #1: Type: text/plain, Size: 18453 bytes --]

On Tue, Nov 10, 2015 at 10:58:20AM -0500, ykhodorkovskiy@tresys.com wrote:
> From: Yuli Khodorkovskiy <ykhodorkovskiy@tresys.com>
> 
> Resolves https://github.com/SELinuxProject/cil/issues/3

Nice , thanks. By the way also a late thank you for the user attribute
functionality. I have not yet tested that because i now use RBACSEP
instead of UBAC but it's good to have.



> 
> An 'unordered' keyword provides the ability to append classes to the current
> list of ordered classes. This allows users to not need knowledge of existing
> classes when creating a class and fixes dependencies on classes when removing a
> module. This enables userspace object managers with custom objects to be
> modularized.
> 
> If a class is declared in both an unordered and ordered statement, then the
> ordered statement will supercede the unordered declaration.
> 
> Example usage:
> 
>     ; Appends new_class to the existing list of classes
>     (class new_class ())
>     (classorder (unordered new_class))
> 
> Signed-off-by: Yuli Khodorkovskiy <ykhodorkovskiy@tresys.com>
> ---
>  libsepol/cil/src/cil.c                             |  1 +
>  libsepol/cil/src/cil_build_ast.c                   | 52 ++++++++++++
>  libsepol/cil/src/cil_internal.h                    |  1 +
>  libsepol/cil/src/cil_list.c                        | 13 +++
>  libsepol/cil/src/cil_list.h                        |  1 +
>  libsepol/cil/src/cil_resolve_ast.c                 | 98 +++++++++++++++++++---
>  .../docs/cil_class_and_permission_statements.xml   | 16 ++++
>  secilc/test/policy.cil                             | 15 +++-
>  8 files changed, 184 insertions(+), 13 deletions(-)
> 
> diff --git a/libsepol/cil/src/cil.c b/libsepol/cil/src/cil.c
> index 8716deb..e6e553b 100644
> --- a/libsepol/cil/src/cil.c
> +++ b/libsepol/cil/src/cil.c
> @@ -230,6 +230,7 @@ static void cil_init_keys(void)
>  	CIL_KEY_DONTAUDITX = cil_strpool_add("dontauditx");
>  	CIL_KEY_PERMISSIONX = cil_strpool_add("permissionx");
>  	CIL_KEY_IOCTL = cil_strpool_add("ioctl");
> +	CIL_KEY_UNORDERED = cil_strpool_add("unordered");
>  }
>  
>  void cil_db_init(struct cil_db **db)
> diff --git a/libsepol/cil/src/cil_build_ast.c b/libsepol/cil/src/cil_build_ast.c
> index 861b606..0407d20 100644
> --- a/libsepol/cil/src/cil_build_ast.c
> +++ b/libsepol/cil/src/cil_build_ast.c
> @@ -365,6 +365,11 @@ int cil_gen_class(__attribute__((unused)) struct cil_db *db, struct cil_tree_nod
>  	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) {
> @@ -410,6 +415,8 @@ int cil_gen_classorder(__attribute__((unused)) struct cil_db *db, struct cil_tre
>  	};
>  	int syntax_len = sizeof(syntax)/sizeof(*syntax);
>  	struct cil_classorder *classorder = NULL;
> +	struct cil_list_item *curr = NULL;
> +	struct cil_list_item *head = NULL;
>  	int rc = SEPOL_ERR;
>  
>  	if (db == NULL || parse_current == NULL || ast_node == NULL) {
> @@ -427,6 +434,22 @@ int cil_gen_classorder(__attribute__((unused)) struct cil_db *db, struct cil_tre
>  	if (rc != SEPOL_OK) {
>  		goto exit;
>  	}
> +
> +	head = classorder->class_list_str->head;
> +	cil_list_for_each(curr, classorder->class_list_str) {
> +		if (curr->data == CIL_KEY_UNORDERED) {
> +			if (curr == head && curr->next == NULL) {
> +				cil_log(CIL_ERR, "Classorder 'unordered' keyword must be followed by one or more class.\n");
> +				rc = SEPOL_ERR;
> +				goto exit;
> +			} else if (curr != head) {
> +				cil_log(CIL_ERR, "Classorder can only use 'unordered' keyword as the first item in the list.\n");
> +				rc = SEPOL_ERR;
> +				goto exit;
> +			}
> +		}
> +	}
> +
>  	ast_node->data = classorder;
>  	ast_node->flavor = CIL_CLASSORDER;
>  
> @@ -1107,6 +1130,7 @@ int cil_gen_sidorder(__attribute__((unused)) struct cil_db *db, struct cil_tree_
>  	};
>  	int syntax_len = sizeof(syntax)/sizeof(*syntax);
>  	struct cil_sidorder *sidorder = NULL;
> +	struct cil_list_item *curr = NULL;
>  	int rc = SEPOL_ERR;
>  
>  	if (db == NULL || parse_current == NULL || ast_node == NULL) {
> @@ -1124,6 +1148,15 @@ int cil_gen_sidorder(__attribute__((unused)) struct cil_db *db, struct cil_tree_
>  	if (rc != SEPOL_OK) {
>  		goto exit;
>  	}
> +
> +	cil_list_for_each(curr, sidorder->sid_list_str) {
> +		if (curr->data == CIL_KEY_UNORDERED) {
> +			cil_log(CIL_ERR, "Sidorder cannot be unordered.\n");
> +			rc = SEPOL_ERR;
> +			goto exit;
> +		}
> +	}
> +
>  	ast_node->data = sidorder;
>  	ast_node->flavor = CIL_SIDORDER;
>  
> @@ -3553,6 +3586,7 @@ int cil_gen_catorder(__attribute__((unused)) struct cil_db *db, struct cil_tree_
>  	};
>  	int syntax_len = sizeof(syntax)/sizeof(*syntax);
>  	struct cil_catorder *catorder = NULL;
> +	struct cil_list_item *curr = NULL;
>  	int rc = SEPOL_ERR;
>  
>  	if (db == NULL || parse_current == NULL || ast_node == NULL) {
> @@ -3570,6 +3604,15 @@ int cil_gen_catorder(__attribute__((unused)) struct cil_db *db, struct cil_tree_
>  	if (rc != SEPOL_OK) {
>  		goto exit;
>  	}
> +
> +	cil_list_for_each(curr, catorder->cat_list_str) {
> +		if (curr->data == CIL_KEY_UNORDERED) {
> +			cil_log(CIL_ERR, "Category order cannot be unordered.\n");
> +			rc = SEPOL_ERR;
> +			goto exit;
> +		}
> +	}
> +
>  	ast_node->data = catorder;
>  	ast_node->flavor = CIL_CATORDER;
>  
> @@ -3604,6 +3647,7 @@ int cil_gen_sensitivityorder(__attribute__((unused)) struct cil_db *db, struct c
>  	};
>  	int syntax_len = sizeof(syntax)/sizeof(*syntax);
>  	struct cil_sensorder *sensorder = NULL;
> +	struct cil_list_item *curr = NULL;
>  	int rc = SEPOL_ERR;
>  
>  	if (db == NULL || parse_current == NULL || ast_node == NULL) {
> @@ -3622,6 +3666,14 @@ int cil_gen_sensitivityorder(__attribute__((unused)) struct cil_db *db, struct c
>  		goto exit;
>  	}
>  
> +	cil_list_for_each(curr, sensorder->sens_list_str) {
> +		if (curr->data == CIL_KEY_UNORDERED) {
> +			cil_log(CIL_ERR, "Sensitivy order cannot be unordered.\n");
> +			rc = SEPOL_ERR;
> +			goto exit;
> +		}
> +	}
> +
>  	ast_node->data = sensorder;
>  	ast_node->flavor = CIL_SENSITIVITYORDER;
>  
> diff --git a/libsepol/cil/src/cil_internal.h b/libsepol/cil/src/cil_internal.h
> index a736eff..7f718d0 100644
> --- a/libsepol/cil/src/cil_internal.h
> +++ b/libsepol/cil/src/cil_internal.h
> @@ -223,6 +223,7 @@ char *CIL_KEY_AUDITALLOWX;
>  char *CIL_KEY_DONTAUDITX;
>  char *CIL_KEY_PERMISSIONX;
>  char *CIL_KEY_IOCTL;
> +char *CIL_KEY_UNORDERED;
>  
>  /*
>  	Symbol Table Array Indices
> diff --git a/libsepol/cil/src/cil_list.c b/libsepol/cil/src/cil_list.c
> index 766985e..dbd554c 100644
> --- a/libsepol/cil/src/cil_list.c
> +++ b/libsepol/cil/src/cil_list.c
> @@ -246,3 +246,16 @@ void cil_list_remove(struct cil_list *list, enum cil_flavor flavor, void *data,
>  		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;
> +}
> diff --git a/libsepol/cil/src/cil_list.h b/libsepol/cil/src/cil_list.h
> index 16d743c..a028036 100644
> --- a/libsepol/cil/src/cil_list.h
> +++ b/libsepol/cil/src/cil_list.h
> @@ -58,5 +58,6 @@ void cil_list_remove(struct cil_list *list, enum cil_flavor flavor, void *data,
>  struct cil_list_item *cil_list_insert(struct cil_list *list, struct cil_list_item *curr, enum cil_flavor flavor, void *data);
>  void cil_list_append_item(struct cil_list *list, struct cil_list_item *item);
>  void cil_list_prepend_item(struct cil_list *list, struct cil_list_item *item);
> +int cil_list_contains(struct cil_list *list, void *data);
>  
>  #endif
> diff --git a/libsepol/cil/src/cil_resolve_ast.c b/libsepol/cil/src/cil_resolve_ast.c
> index 0df5c63..deb3d38 100644
> --- a/libsepol/cil/src/cil_resolve_ast.c
> +++ b/libsepol/cil/src/cil_resolve_ast.c
> @@ -59,6 +59,7 @@ struct cil_args_resolve {
>  	struct cil_tree_node *blockstack;
>  	struct cil_list *sidorder_lists;
>  	struct cil_list *classorder_lists;
> +	struct cil_list *unordered_classorder_lists;
>  	struct cil_list *catorder_lists;
>  	struct cil_list *sensitivityorder_lists;
>  	struct cil_list *in_list;
> @@ -1176,7 +1177,7 @@ void __cil_ordered_lists_destroy(struct cil_list **ordered_lists)
>  {
>  	struct cil_list_item *item = NULL;
>  
> -	if (*ordered_lists == NULL) {
> +	if (ordered_lists == NULL || *ordered_lists == NULL) {
>  		return;
>  	}
>  
> @@ -1351,7 +1352,42 @@ int __cil_ordered_lists_merge(struct cil_list *old, struct cil_list *new)
>  	return SEPOL_OK;
>  }
>  
> -struct cil_list *__cil_ordered_lists_merge_all(struct cil_list **ordered_lists)
> +static int insert_unordered(struct cil_list *merged, struct cil_list *unordered)
> +{
> +	struct cil_list_item *curr = NULL;
> +	struct cil_ordered_list *unordered_list = NULL;
> +	struct cil_list_item *item = NULL;
> +	struct cil_list_item *ret = NULL;
> +	int rc = SEPOL_ERR;
> +
> +	cil_list_for_each(curr, unordered) {
> +		unordered_list = curr->data;
> +
> +		cil_list_for_each(item, unordered_list->list) {
> +			if (cil_list_contains(merged, item->data)) {
> +				/* item was declared in an ordered statement, which supercedes
> +				 * all unordered statements */
> +				if (item->flavor == CIL_CLASS) {
> +					cil_log(CIL_WARN, "Ignoring '%s' as it has already been declared in classorder.\n", ((struct cil_class*)(item->data))->datum.name);
> +				}
> +				continue;
> +			}
> +
> +			ret = __cil_ordered_item_insert(merged, merged->tail, item);
> +			if (ret == NULL) {
> +				rc = SEPOL_ERR;
> +				goto exit;
> +			}
> +		}
> +	}
> +
> +	rc = SEPOL_OK;
> +
> +exit:
> +	return rc;
> +}
> +
> +struct cil_list *__cil_ordered_lists_merge_all(struct cil_list **ordered_lists, struct cil_list **unordered_lists)
>  {
>  	struct cil_list *composite = NULL;
>  	struct cil_list_item *curr = NULL;
> @@ -1388,11 +1424,21 @@ struct cil_list *__cil_ordered_lists_merge_all(struct cil_list **ordered_lists)
>  		}
>  	}
>  
> +	if (unordered_lists != NULL) {
> +		rc = insert_unordered(composite, *unordered_lists);
> +		if (rc != SEPOL_OK) {
> +			goto exit;
> +		}
> +	}
> +
>  	__cil_ordered_lists_destroy(ordered_lists);
> +	__cil_ordered_lists_destroy(unordered_lists);
>  
>  	return composite;
>  
>  exit:
> +	__cil_ordered_lists_destroy(ordered_lists);
> +	__cil_ordered_lists_destroy(unordered_lists);
>  	cil_list_destroy(&composite, CIL_FALSE);
>  	return NULL;
>  }
> @@ -1401,16 +1447,23 @@ int cil_resolve_classorder(struct cil_tree_node *current, void *extra_args)
>  {
>  	struct cil_args_resolve *args = extra_args;
>  	struct cil_list *classorder_list = args->classorder_lists;
> +	struct cil_list *unordered_classorder_list = args->unordered_classorder_lists;
>  	struct cil_classorder *classorder = current->data;
>  	struct cil_list *new = NULL;
>  	struct cil_list_item *curr = NULL;
>  	struct cil_symtab_datum *datum = NULL;
> -	struct cil_ordered_list *ordered = NULL;
> +	struct cil_ordered_list *class_list = NULL;
>  	int rc = SEPOL_ERR;
> +	int unordered = CIL_FALSE;
>  
>  	cil_list_init(&new, CIL_CLASSORDER);
>  
>  	cil_list_for_each(curr, classorder->class_list_str) {
> +		if (curr->data == CIL_KEY_UNORDERED) {
> +			unordered = CIL_TRUE;
> +			continue;
> +		}
> +
>  		rc = cil_resolve_name(current, (char *)curr->data, CIL_SYM_CLASSES, extra_args, &datum);
>  		if (rc != SEPOL_OK) {
>  			cil_log(CIL_ERR, "Failed to resolve class %s in classorder\n", (char *)curr->data);
> @@ -1419,10 +1472,14 @@ int cil_resolve_classorder(struct cil_tree_node *current, void *extra_args)
>  		cil_list_append(new, CIL_CLASS, datum);
>  	}
>  
> -	__cil_ordered_list_init(&ordered);
> -	ordered->list = new;
> -	ordered->node = current;
> -	cil_list_append(classorder_list, CIL_CLASSORDER, ordered);
> +	__cil_ordered_list_init(&class_list);
> +	class_list->list = new;
> +	class_list->node = current;
> +	if (unordered) {
> +		cil_list_append(unordered_classorder_list, CIL_CLASSORDER, class_list);
> +	} else {
> +		cil_list_append(classorder_list, CIL_CLASSORDER, class_list);
> +	}
>  
>  	return SEPOL_OK;
>  
> @@ -3651,6 +3708,7 @@ int cil_resolve_ast(struct cil_db *db, struct cil_tree_node *current)
>  	extra_args.macro = NULL;
>  	extra_args.sidorder_lists = NULL;
>  	extra_args.classorder_lists = NULL;
> +	extra_args.unordered_classorder_lists = NULL;
>  	extra_args.catorder_lists = NULL;
>  	extra_args.sensitivityorder_lists = NULL;
>  	extra_args.in_list = NULL;
> @@ -3658,6 +3716,7 @@ int cil_resolve_ast(struct cil_db *db, struct cil_tree_node *current)
>  
>  	cil_list_init(&extra_args.sidorder_lists, CIL_LIST_ITEM);
>  	cil_list_init(&extra_args.classorder_lists, CIL_LIST_ITEM);
> +	cil_list_init(&extra_args.unordered_classorder_lists, CIL_LIST_ITEM);
>  	cil_list_init(&extra_args.catorder_lists, CIL_LIST_ITEM);
>  	cil_list_init(&extra_args.sensitivityorder_lists, CIL_LIST_ITEM);
>  	cil_list_init(&extra_args.in_list, CIL_IN);
> @@ -3678,11 +3737,27 @@ int cil_resolve_ast(struct cil_db *db, struct cil_tree_node *current)
>  		}
>  
>  		if (pass == CIL_PASS_MISC1) {
> -			db->sidorder = __cil_ordered_lists_merge_all(&extra_args.sidorder_lists);
> -			db->classorder = __cil_ordered_lists_merge_all(&extra_args.classorder_lists);
> -			db->catorder = __cil_ordered_lists_merge_all(&extra_args.catorder_lists);
> +			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);
> +			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) {
> @@ -3718,6 +3793,7 @@ int cil_resolve_ast(struct cil_db *db, struct cil_tree_node *current)
>  			if (pass >= CIL_PASS_MISC1) {
>  				__cil_ordered_lists_reset(&extra_args.sidorder_lists);
>  				__cil_ordered_lists_reset(&extra_args.classorder_lists);
> +				__cil_ordered_lists_reset(&extra_args.unordered_classorder_lists);
>  				__cil_ordered_lists_reset(&extra_args.catorder_lists);
>  				__cil_ordered_lists_reset(&extra_args.sensitivityorder_lists);
>  				cil_list_destroy(&db->sidorder, CIL_FALSE);
> diff --git a/secilc/docs/cil_class_and_permission_statements.xml b/secilc/docs/cil_class_and_permission_statements.xml
> index 2926d7c..20c3eb7 100644
> --- a/secilc/docs/cil_class_and_permission_statements.xml
> +++ b/secilc/docs/cil_class_and_permission_statements.xml
> @@ -198,6 +198,22 @@
>  (classorder (file dir))
>  (classorder (dir process))]]>
>        </programlisting>
> +         <para><emphasis role="bold">Unordered Classorder Statement:</emphasis></para>
> +         <para>If users do not have knowledge of the existing classorder, the <literal>unordered</literal> keyword may be used in a <literal>classorder</literal> statement. The <link linkend="class">class</link>es in an unordered statement are appended to the existing classorder. A class in an ordered statement always supercedes the class redeclaration in an unordered statement. The <literal>unordered</literal> keyword must be the first item in the classorder listing.</para>
> +         <para><emphasis role="bold">Example:</emphasis></para>
> +         <para>This will produce an ordered list of "<literal>file dir foo a bar baz</literal>"</para>
> +         <programlisting><![CDATA[
> +(class file)
> +(class dir)
> +(class foo)
> +(class bar)
> +(class baz)
> +(class a)
> +(classorder (file dir))
> +(classorder (dir foo))
> +(classorder (unordered a))
> +(classorder (unordered bar foo baz))]]>
> +      </programlisting>
>        </sect2>
>       <sect2 id="classpermission">
>           <title>classpermission</title>
> diff --git a/secilc/test/policy.cil b/secilc/test/policy.cil
> index 69103d1..884d2dc 100644
> --- a/secilc/test/policy.cil
> +++ b/secilc/test/policy.cil
> @@ -46,8 +46,13 @@
>  (levelrange lh4 ((s0) (s1)))
>  
>  (block policy
> -	(classorder (file char dir))
> -	(class file (execute_no_trans entrypoint execmod open audit_access))
> +	(class file (execute_no_trans entrypoint execmod open audit_access a b c d e))
> +	; order should be: file char b c a dir d e f
> +	(classorder (file char))
> +	(classorder (unordered dir))
> +	(classorder (unordered c a b d e f))
> +	(classorder (char b c a))
> +
>  	(common file (ioctl read write create getattr setattr lock relabelfrom
>  			relabelto append unlink link rename execute swapon
>  			quotaon mounton))
> @@ -67,6 +72,12 @@
>  	(classcommon char file)
>  
>  	(class dir ())
> +	(class a ())
> +	(class b ())
> +	(class c ())
> +	(class d ())
> +	(class e ())
> +	(class f ())
>  	(classcommon dir file)
>  
>  	(classpermission char_w)
> -- 
> 2.4.3
> 
> _______________________________________________
> Selinux mailing list
> Selinux@tycho.nsa.gov
> To unsubscribe, send email to Selinux-leave@tycho.nsa.gov.
> To get help, send an email containing "help" to Selinux-request@tycho.nsa.gov.

-- 
02DFF788
4D30 903A 1CF3 B756 FB48  1514 3148 83A2 02DF F788
https://sks-keyservers.net/pks/lookup?op=get&search=0x314883A202DFF788
Dominick Grift

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 648 bytes --]

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] secilc: Add support for unordered classes
  2015-11-10 15:58 [PATCH] secilc: Add support for unordered classes ykhodorkovskiy
  2015-11-10 16:08 ` Dominick Grift
@ 2015-11-10 16:21 ` Dominick Grift
  2015-11-13 15:18 ` James Carter
  2 siblings, 0 replies; 4+ messages in thread
From: Dominick Grift @ 2015-11-10 16:21 UTC (permalink / raw)
  To: ykhodorkovskiy; +Cc: selinux

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512

On Tue, Nov 10, 2015 at 10:58:20AM -0500, ykhodorkovskiy@tresys.com wrote:
> From: Yuli Khodorkovskiy <ykhodorkovskiy@tresys.com>
> 
> Resolves https://github.com/SELinuxProject/cil/issues/3
> 
> An 'unordered' keyword provides the ability to append classes to the current
> list of ordered classes. This allows users to not need knowledge of existing
> classes when creating a class and fixes dependencies on classes when removing a
> module. This enables userspace object managers with custom objects to be
> modularized.
> 
> If a class is declared in both an unordered and ordered statement, then the
> ordered statement will supercede the unordered declaration.

Now if only the systemd object manager code is fixed properly (it is in
a dire state currently)

1. (long standing issue) associates it access vector permissions with the system Linux object class 
2. (rawhide) removed various important checks (enabling and disabling units)
3. (rawhide) the systemd object manager works/not works inconsistently in some
scenario's (just yesterday it took me 6 reboots to make the systemd
object manager work)

> 
> Example usage:
> 
>     ; Appends new_class to the existing list of classes
>     (class new_class ())
>     (classorder (unordered new_class))
> 
> Signed-off-by: Yuli Khodorkovskiy <ykhodorkovskiy@tresys.com>
> ---
>  libsepol/cil/src/cil.c                             |  1 +
>  libsepol/cil/src/cil_build_ast.c                   | 52 ++++++++++++
>  libsepol/cil/src/cil_internal.h                    |  1 +
>  libsepol/cil/src/cil_list.c                        | 13 +++
>  libsepol/cil/src/cil_list.h                        |  1 +
>  libsepol/cil/src/cil_resolve_ast.c                 | 98 +++++++++++++++++++---
>  .../docs/cil_class_and_permission_statements.xml   | 16 ++++
>  secilc/test/policy.cil                             | 15 +++-
>  8 files changed, 184 insertions(+), 13 deletions(-)
> 
> diff --git a/libsepol/cil/src/cil.c b/libsepol/cil/src/cil.c
> index 8716deb..e6e553b 100644
> --- a/libsepol/cil/src/cil.c
> +++ b/libsepol/cil/src/cil.c
> @@ -230,6 +230,7 @@ static void cil_init_keys(void)
>  	CIL_KEY_DONTAUDITX = cil_strpool_add("dontauditx");
>  	CIL_KEY_PERMISSIONX = cil_strpool_add("permissionx");
>  	CIL_KEY_IOCTL = cil_strpool_add("ioctl");
> +	CIL_KEY_UNORDERED = cil_strpool_add("unordered");
>  }
>  
>  void cil_db_init(struct cil_db **db)
> diff --git a/libsepol/cil/src/cil_build_ast.c b/libsepol/cil/src/cil_build_ast.c
> index 861b606..0407d20 100644
> --- a/libsepol/cil/src/cil_build_ast.c
> +++ b/libsepol/cil/src/cil_build_ast.c
> @@ -365,6 +365,11 @@ int cil_gen_class(__attribute__((unused)) struct cil_db *db, struct cil_tree_nod
>  	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) {
> @@ -410,6 +415,8 @@ int cil_gen_classorder(__attribute__((unused)) struct cil_db *db, struct cil_tre
>  	};
>  	int syntax_len = sizeof(syntax)/sizeof(*syntax);
>  	struct cil_classorder *classorder = NULL;
> +	struct cil_list_item *curr = NULL;
> +	struct cil_list_item *head = NULL;
>  	int rc = SEPOL_ERR;
>  
>  	if (db == NULL || parse_current == NULL || ast_node == NULL) {
> @@ -427,6 +434,22 @@ int cil_gen_classorder(__attribute__((unused)) struct cil_db *db, struct cil_tre
>  	if (rc != SEPOL_OK) {
>  		goto exit;
>  	}
> +
> +	head = classorder->class_list_str->head;
> +	cil_list_for_each(curr, classorder->class_list_str) {
> +		if (curr->data == CIL_KEY_UNORDERED) {
> +			if (curr == head && curr->next == NULL) {
> +				cil_log(CIL_ERR, "Classorder 'unordered' keyword must be followed by one or more class.\n");
> +				rc = SEPOL_ERR;
> +				goto exit;
> +			} else if (curr != head) {
> +				cil_log(CIL_ERR, "Classorder can only use 'unordered' keyword as the first item in the list.\n");
> +				rc = SEPOL_ERR;
> +				goto exit;
> +			}
> +		}
> +	}
> +
>  	ast_node->data = classorder;
>  	ast_node->flavor = CIL_CLASSORDER;
>  
> @@ -1107,6 +1130,7 @@ int cil_gen_sidorder(__attribute__((unused)) struct cil_db *db, struct cil_tree_
>  	};
>  	int syntax_len = sizeof(syntax)/sizeof(*syntax);
>  	struct cil_sidorder *sidorder = NULL;
> +	struct cil_list_item *curr = NULL;
>  	int rc = SEPOL_ERR;
>  
>  	if (db == NULL || parse_current == NULL || ast_node == NULL) {
> @@ -1124,6 +1148,15 @@ int cil_gen_sidorder(__attribute__((unused)) struct cil_db *db, struct cil_tree_
>  	if (rc != SEPOL_OK) {
>  		goto exit;
>  	}
> +
> +	cil_list_for_each(curr, sidorder->sid_list_str) {
> +		if (curr->data == CIL_KEY_UNORDERED) {
> +			cil_log(CIL_ERR, "Sidorder cannot be unordered.\n");
> +			rc = SEPOL_ERR;
> +			goto exit;
> +		}
> +	}
> +
>  	ast_node->data = sidorder;
>  	ast_node->flavor = CIL_SIDORDER;
>  
> @@ -3553,6 +3586,7 @@ int cil_gen_catorder(__attribute__((unused)) struct cil_db *db, struct cil_tree_
>  	};
>  	int syntax_len = sizeof(syntax)/sizeof(*syntax);
>  	struct cil_catorder *catorder = NULL;
> +	struct cil_list_item *curr = NULL;
>  	int rc = SEPOL_ERR;
>  
>  	if (db == NULL || parse_current == NULL || ast_node == NULL) {
> @@ -3570,6 +3604,15 @@ int cil_gen_catorder(__attribute__((unused)) struct cil_db *db, struct cil_tree_
>  	if (rc != SEPOL_OK) {
>  		goto exit;
>  	}
> +
> +	cil_list_for_each(curr, catorder->cat_list_str) {
> +		if (curr->data == CIL_KEY_UNORDERED) {
> +			cil_log(CIL_ERR, "Category order cannot be unordered.\n");
> +			rc = SEPOL_ERR;
> +			goto exit;
> +		}
> +	}
> +
>  	ast_node->data = catorder;
>  	ast_node->flavor = CIL_CATORDER;
>  
> @@ -3604,6 +3647,7 @@ int cil_gen_sensitivityorder(__attribute__((unused)) struct cil_db *db, struct c
>  	};
>  	int syntax_len = sizeof(syntax)/sizeof(*syntax);
>  	struct cil_sensorder *sensorder = NULL;
> +	struct cil_list_item *curr = NULL;
>  	int rc = SEPOL_ERR;
>  
>  	if (db == NULL || parse_current == NULL || ast_node == NULL) {
> @@ -3622,6 +3666,14 @@ int cil_gen_sensitivityorder(__attribute__((unused)) struct cil_db *db, struct c
>  		goto exit;
>  	}
>  
> +	cil_list_for_each(curr, sensorder->sens_list_str) {
> +		if (curr->data == CIL_KEY_UNORDERED) {
> +			cil_log(CIL_ERR, "Sensitivy order cannot be unordered.\n");
> +			rc = SEPOL_ERR;
> +			goto exit;
> +		}
> +	}
> +
>  	ast_node->data = sensorder;
>  	ast_node->flavor = CIL_SENSITIVITYORDER;
>  
> diff --git a/libsepol/cil/src/cil_internal.h b/libsepol/cil/src/cil_internal.h
> index a736eff..7f718d0 100644
> --- a/libsepol/cil/src/cil_internal.h
> +++ b/libsepol/cil/src/cil_internal.h
> @@ -223,6 +223,7 @@ char *CIL_KEY_AUDITALLOWX;
>  char *CIL_KEY_DONTAUDITX;
>  char *CIL_KEY_PERMISSIONX;
>  char *CIL_KEY_IOCTL;
> +char *CIL_KEY_UNORDERED;
>  
>  /*
>  	Symbol Table Array Indices
> diff --git a/libsepol/cil/src/cil_list.c b/libsepol/cil/src/cil_list.c
> index 766985e..dbd554c 100644
> --- a/libsepol/cil/src/cil_list.c
> +++ b/libsepol/cil/src/cil_list.c
> @@ -246,3 +246,16 @@ void cil_list_remove(struct cil_list *list, enum cil_flavor flavor, void *data,
>  		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;
> +}
> diff --git a/libsepol/cil/src/cil_list.h b/libsepol/cil/src/cil_list.h
> index 16d743c..a028036 100644
> --- a/libsepol/cil/src/cil_list.h
> +++ b/libsepol/cil/src/cil_list.h
> @@ -58,5 +58,6 @@ void cil_list_remove(struct cil_list *list, enum cil_flavor flavor, void *data,
>  struct cil_list_item *cil_list_insert(struct cil_list *list, struct cil_list_item *curr, enum cil_flavor flavor, void *data);
>  void cil_list_append_item(struct cil_list *list, struct cil_list_item *item);
>  void cil_list_prepend_item(struct cil_list *list, struct cil_list_item *item);
> +int cil_list_contains(struct cil_list *list, void *data);
>  
>  #endif
> diff --git a/libsepol/cil/src/cil_resolve_ast.c b/libsepol/cil/src/cil_resolve_ast.c
> index 0df5c63..deb3d38 100644
> --- a/libsepol/cil/src/cil_resolve_ast.c
> +++ b/libsepol/cil/src/cil_resolve_ast.c
> @@ -59,6 +59,7 @@ struct cil_args_resolve {
>  	struct cil_tree_node *blockstack;
>  	struct cil_list *sidorder_lists;
>  	struct cil_list *classorder_lists;
> +	struct cil_list *unordered_classorder_lists;
>  	struct cil_list *catorder_lists;
>  	struct cil_list *sensitivityorder_lists;
>  	struct cil_list *in_list;
> @@ -1176,7 +1177,7 @@ void __cil_ordered_lists_destroy(struct cil_list **ordered_lists)
>  {
>  	struct cil_list_item *item = NULL;
>  
> -	if (*ordered_lists == NULL) {
> +	if (ordered_lists == NULL || *ordered_lists == NULL) {
>  		return;
>  	}
>  
> @@ -1351,7 +1352,42 @@ int __cil_ordered_lists_merge(struct cil_list *old, struct cil_list *new)
>  	return SEPOL_OK;
>  }
>  
> -struct cil_list *__cil_ordered_lists_merge_all(struct cil_list **ordered_lists)
> +static int insert_unordered(struct cil_list *merged, struct cil_list *unordered)
> +{
> +	struct cil_list_item *curr = NULL;
> +	struct cil_ordered_list *unordered_list = NULL;
> +	struct cil_list_item *item = NULL;
> +	struct cil_list_item *ret = NULL;
> +	int rc = SEPOL_ERR;
> +
> +	cil_list_for_each(curr, unordered) {
> +		unordered_list = curr->data;
> +
> +		cil_list_for_each(item, unordered_list->list) {
> +			if (cil_list_contains(merged, item->data)) {
> +				/* item was declared in an ordered statement, which supercedes
> +				 * all unordered statements */
> +				if (item->flavor == CIL_CLASS) {
> +					cil_log(CIL_WARN, "Ignoring '%s' as it has already been declared in classorder.\n", ((struct cil_class*)(item->data))->datum.name);
> +				}
> +				continue;
> +			}
> +
> +			ret = __cil_ordered_item_insert(merged, merged->tail, item);
> +			if (ret == NULL) {
> +				rc = SEPOL_ERR;
> +				goto exit;
> +			}
> +		}
> +	}
> +
> +	rc = SEPOL_OK;
> +
> +exit:
> +	return rc;
> +}
> +
> +struct cil_list *__cil_ordered_lists_merge_all(struct cil_list **ordered_lists, struct cil_list **unordered_lists)
>  {
>  	struct cil_list *composite = NULL;
>  	struct cil_list_item *curr = NULL;
> @@ -1388,11 +1424,21 @@ struct cil_list *__cil_ordered_lists_merge_all(struct cil_list **ordered_lists)
>  		}
>  	}
>  
> +	if (unordered_lists != NULL) {
> +		rc = insert_unordered(composite, *unordered_lists);
> +		if (rc != SEPOL_OK) {
> +			goto exit;
> +		}
> +	}
> +
>  	__cil_ordered_lists_destroy(ordered_lists);
> +	__cil_ordered_lists_destroy(unordered_lists);
>  
>  	return composite;
>  
>  exit:
> +	__cil_ordered_lists_destroy(ordered_lists);
> +	__cil_ordered_lists_destroy(unordered_lists);
>  	cil_list_destroy(&composite, CIL_FALSE);
>  	return NULL;
>  }
> @@ -1401,16 +1447,23 @@ int cil_resolve_classorder(struct cil_tree_node *current, void *extra_args)
>  {
>  	struct cil_args_resolve *args = extra_args;
>  	struct cil_list *classorder_list = args->classorder_lists;
> +	struct cil_list *unordered_classorder_list = args->unordered_classorder_lists;
>  	struct cil_classorder *classorder = current->data;
>  	struct cil_list *new = NULL;
>  	struct cil_list_item *curr = NULL;
>  	struct cil_symtab_datum *datum = NULL;
> -	struct cil_ordered_list *ordered = NULL;
> +	struct cil_ordered_list *class_list = NULL;
>  	int rc = SEPOL_ERR;
> +	int unordered = CIL_FALSE;
>  
>  	cil_list_init(&new, CIL_CLASSORDER);
>  
>  	cil_list_for_each(curr, classorder->class_list_str) {
> +		if (curr->data == CIL_KEY_UNORDERED) {
> +			unordered = CIL_TRUE;
> +			continue;
> +		}
> +
>  		rc = cil_resolve_name(current, (char *)curr->data, CIL_SYM_CLASSES, extra_args, &datum);
>  		if (rc != SEPOL_OK) {
>  			cil_log(CIL_ERR, "Failed to resolve class %s in classorder\n", (char *)curr->data);
> @@ -1419,10 +1472,14 @@ int cil_resolve_classorder(struct cil_tree_node *current, void *extra_args)
>  		cil_list_append(new, CIL_CLASS, datum);
>  	}
>  
> -	__cil_ordered_list_init(&ordered);
> -	ordered->list = new;
> -	ordered->node = current;
> -	cil_list_append(classorder_list, CIL_CLASSORDER, ordered);
> +	__cil_ordered_list_init(&class_list);
> +	class_list->list = new;
> +	class_list->node = current;
> +	if (unordered) {
> +		cil_list_append(unordered_classorder_list, CIL_CLASSORDER, class_list);
> +	} else {
> +		cil_list_append(classorder_list, CIL_CLASSORDER, class_list);
> +	}
>  
>  	return SEPOL_OK;
>  
> @@ -3651,6 +3708,7 @@ int cil_resolve_ast(struct cil_db *db, struct cil_tree_node *current)
>  	extra_args.macro = NULL;
>  	extra_args.sidorder_lists = NULL;
>  	extra_args.classorder_lists = NULL;
> +	extra_args.unordered_classorder_lists = NULL;
>  	extra_args.catorder_lists = NULL;
>  	extra_args.sensitivityorder_lists = NULL;
>  	extra_args.in_list = NULL;
> @@ -3658,6 +3716,7 @@ int cil_resolve_ast(struct cil_db *db, struct cil_tree_node *current)
>  
>  	cil_list_init(&extra_args.sidorder_lists, CIL_LIST_ITEM);
>  	cil_list_init(&extra_args.classorder_lists, CIL_LIST_ITEM);
> +	cil_list_init(&extra_args.unordered_classorder_lists, CIL_LIST_ITEM);
>  	cil_list_init(&extra_args.catorder_lists, CIL_LIST_ITEM);
>  	cil_list_init(&extra_args.sensitivityorder_lists, CIL_LIST_ITEM);
>  	cil_list_init(&extra_args.in_list, CIL_IN);
> @@ -3678,11 +3737,27 @@ int cil_resolve_ast(struct cil_db *db, struct cil_tree_node *current)
>  		}
>  
>  		if (pass == CIL_PASS_MISC1) {
> -			db->sidorder = __cil_ordered_lists_merge_all(&extra_args.sidorder_lists);
> -			db->classorder = __cil_ordered_lists_merge_all(&extra_args.classorder_lists);
> -			db->catorder = __cil_ordered_lists_merge_all(&extra_args.catorder_lists);
> +			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);
> +			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) {
> @@ -3718,6 +3793,7 @@ int cil_resolve_ast(struct cil_db *db, struct cil_tree_node *current)
>  			if (pass >= CIL_PASS_MISC1) {
>  				__cil_ordered_lists_reset(&extra_args.sidorder_lists);
>  				__cil_ordered_lists_reset(&extra_args.classorder_lists);
> +				__cil_ordered_lists_reset(&extra_args.unordered_classorder_lists);
>  				__cil_ordered_lists_reset(&extra_args.catorder_lists);
>  				__cil_ordered_lists_reset(&extra_args.sensitivityorder_lists);
>  				cil_list_destroy(&db->sidorder, CIL_FALSE);
> diff --git a/secilc/docs/cil_class_and_permission_statements.xml b/secilc/docs/cil_class_and_permission_statements.xml
> index 2926d7c..20c3eb7 100644
> --- a/secilc/docs/cil_class_and_permission_statements.xml
> +++ b/secilc/docs/cil_class_and_permission_statements.xml
> @@ -198,6 +198,22 @@
>  (classorder (file dir))
>  (classorder (dir process))]]>
>        </programlisting>
> +         <para><emphasis role="bold">Unordered Classorder Statement:</emphasis></para>
> +         <para>If users do not have knowledge of the existing classorder, the <literal>unordered</literal> keyword may be used in a <literal>classorder</literal> statement. The <link linkend="class">class</link>es in an unordered statement are appended to the existing classorder. A class in an ordered statement always supercedes the class redeclaration in an unordered statement. The <literal>unordered</literal> keyword must be the first item in the classorder listing.</para>
> +         <para><emphasis role="bold">Example:</emphasis></para>
> +         <para>This will produce an ordered list of "<literal>file dir foo a bar baz</literal>"</para>
> +         <programlisting><![CDATA[
> +(class file)
> +(class dir)
> +(class foo)
> +(class bar)
> +(class baz)
> +(class a)
> +(classorder (file dir))
> +(classorder (dir foo))
> +(classorder (unordered a))
> +(classorder (unordered bar foo baz))]]>
> +      </programlisting>
>        </sect2>
>       <sect2 id="classpermission">
>           <title>classpermission</title>
> diff --git a/secilc/test/policy.cil b/secilc/test/policy.cil
> index 69103d1..884d2dc 100644
> --- a/secilc/test/policy.cil
> +++ b/secilc/test/policy.cil
> @@ -46,8 +46,13 @@
>  (levelrange lh4 ((s0) (s1)))
>  
>  (block policy
> -	(classorder (file char dir))
> -	(class file (execute_no_trans entrypoint execmod open audit_access))
> +	(class file (execute_no_trans entrypoint execmod open audit_access a b c d e))
> +	; order should be: file char b c a dir d e f
> +	(classorder (file char))
> +	(classorder (unordered dir))
> +	(classorder (unordered c a b d e f))
> +	(classorder (char b c a))
> +
>  	(common file (ioctl read write create getattr setattr lock relabelfrom
>  			relabelto append unlink link rename execute swapon
>  			quotaon mounton))
> @@ -67,6 +72,12 @@
>  	(classcommon char file)
>  
>  	(class dir ())
> +	(class a ())
> +	(class b ())
> +	(class c ())
> +	(class d ())
> +	(class e ())
> +	(class f ())
>  	(classcommon dir file)
>  
>  	(classpermission char_w)
> -- 
> 2.4.3
> 
> _______________________________________________
> Selinux mailing list
> Selinux@tycho.nsa.gov
> To unsubscribe, send email to Selinux-leave@tycho.nsa.gov.
> To get help, send an email containing "help" to Selinux-request@tycho.nsa.gov.

- -- 
02DFF788
4D30 903A 1CF3 B756 FB48  1514 3148 83A2 02DF F788
https://sks-keyservers.net/pks/lookup?op=get&search=0x314883A202DFF788
Dominick Grift
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2

iQGcBAEBCgAGBQJWQhmIAAoJENAR6kfG5xmcqU4L/0WrOdXtGfR8dGR8H/peIMSQ
pxUW2zVyHAKG9Hc7O2XC1ktIDf91esKopfhC7F97ikXheWWM8Z9AjfLr9E7TKJJ1
JDI/8O2ihumJ1woGIKxpo5eUu+VhRrh7gJHJmWZuQXJL1CAGNZbjEbV5zBQ4t6gj
u1ylHSBNGu2+awtNDg6uxl3d1QyyP6drQO8kKI1djS4bZ9jfVHm4mPcYitFUi6rb
RHN2CGyVP1yP/LaTJgjtY5E3jX8gPU8DEjjiuCGrZIuieQXh+8sOlXCSQ+0n2Gk0
Gp7CL2ZCBVXAJMMJxinLs/6iD4R2cstBiAWAoxhO374B5sCOB6UWimatfwniZw0V
9dCFVbwWcSkNZuUGln1YIh9LdCqkE/77q2mDrDh7pUrnAQqFEXD8tnMPEF1U5RKa
5h2I2mYKIhMrwSHSEYs0fw40FUlEAMY4Ejoo5QlV9LrrKJ7ztgfdY4H9LcUvBjJo
mlmrgdtSlwmopRNJVjKf4BtGmQlAFYk2yasQ/a5AzA==
=15AE
-----END PGP SIGNATURE-----

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] secilc: Add support for unordered classes
  2015-11-10 15:58 [PATCH] secilc: Add support for unordered classes ykhodorkovskiy
  2015-11-10 16:08 ` Dominick Grift
  2015-11-10 16:21 ` Dominick Grift
@ 2015-11-13 15:18 ` James Carter
  2 siblings, 0 replies; 4+ messages in thread
From: James Carter @ 2015-11-13 15:18 UTC (permalink / raw)
  To: ykhodorkovskiy, selinux

On 11/10/2015 10:58 AM, ykhodorkovskiy@tresys.com wrote:
> From: Yuli Khodorkovskiy <ykhodorkovskiy@tresys.com>
>
> Resolves https://github.com/SELinuxProject/cil/issues/3
>
> An 'unordered' keyword provides the ability to append classes to the current
> list of ordered classes. This allows users to not need knowledge of existing
> classes when creating a class and fixes dependencies on classes when removing a
> module. This enables userspace object managers with custom objects to be
> modularized.
>
> If a class is declared in both an unordered and ordered statement, then the
> ordered statement will supercede the unordered declaration.
>
> Example usage:
>
>      ; Appends new_class to the existing list of classes
>      (class new_class ())
>      (classorder (unordered new_class))
>
> Signed-off-by: Yuli Khodorkovskiy <ykhodorkovskiy@tresys.com>

Applied.

Thanks,
Jim

> ---
>   libsepol/cil/src/cil.c                             |  1 +
>   libsepol/cil/src/cil_build_ast.c                   | 52 ++++++++++++
>   libsepol/cil/src/cil_internal.h                    |  1 +
>   libsepol/cil/src/cil_list.c                        | 13 +++
>   libsepol/cil/src/cil_list.h                        |  1 +
>   libsepol/cil/src/cil_resolve_ast.c                 | 98 +++++++++++++++++++---
>   .../docs/cil_class_and_permission_statements.xml   | 16 ++++
>   secilc/test/policy.cil                             | 15 +++-
>   8 files changed, 184 insertions(+), 13 deletions(-)
>
> diff --git a/libsepol/cil/src/cil.c b/libsepol/cil/src/cil.c
> index 8716deb..e6e553b 100644
> --- a/libsepol/cil/src/cil.c
> +++ b/libsepol/cil/src/cil.c
> @@ -230,6 +230,7 @@ static void cil_init_keys(void)
>   	CIL_KEY_DONTAUDITX = cil_strpool_add("dontauditx");
>   	CIL_KEY_PERMISSIONX = cil_strpool_add("permissionx");
>   	CIL_KEY_IOCTL = cil_strpool_add("ioctl");
> +	CIL_KEY_UNORDERED = cil_strpool_add("unordered");
>   }
>
>   void cil_db_init(struct cil_db **db)
> diff --git a/libsepol/cil/src/cil_build_ast.c b/libsepol/cil/src/cil_build_ast.c
> index 861b606..0407d20 100644
> --- a/libsepol/cil/src/cil_build_ast.c
> +++ b/libsepol/cil/src/cil_build_ast.c
> @@ -365,6 +365,11 @@ int cil_gen_class(__attribute__((unused)) struct cil_db *db, struct cil_tree_nod
>   	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) {
> @@ -410,6 +415,8 @@ int cil_gen_classorder(__attribute__((unused)) struct cil_db *db, struct cil_tre
>   	};
>   	int syntax_len = sizeof(syntax)/sizeof(*syntax);
>   	struct cil_classorder *classorder = NULL;
> +	struct cil_list_item *curr = NULL;
> +	struct cil_list_item *head = NULL;
>   	int rc = SEPOL_ERR;
>
>   	if (db == NULL || parse_current == NULL || ast_node == NULL) {
> @@ -427,6 +434,22 @@ int cil_gen_classorder(__attribute__((unused)) struct cil_db *db, struct cil_tre
>   	if (rc != SEPOL_OK) {
>   		goto exit;
>   	}
> +
> +	head = classorder->class_list_str->head;
> +	cil_list_for_each(curr, classorder->class_list_str) {
> +		if (curr->data == CIL_KEY_UNORDERED) {
> +			if (curr == head && curr->next == NULL) {
> +				cil_log(CIL_ERR, "Classorder 'unordered' keyword must be followed by one or more class.\n");
> +				rc = SEPOL_ERR;
> +				goto exit;
> +			} else if (curr != head) {
> +				cil_log(CIL_ERR, "Classorder can only use 'unordered' keyword as the first item in the list.\n");
> +				rc = SEPOL_ERR;
> +				goto exit;
> +			}
> +		}
> +	}
> +
>   	ast_node->data = classorder;
>   	ast_node->flavor = CIL_CLASSORDER;
>
> @@ -1107,6 +1130,7 @@ int cil_gen_sidorder(__attribute__((unused)) struct cil_db *db, struct cil_tree_
>   	};
>   	int syntax_len = sizeof(syntax)/sizeof(*syntax);
>   	struct cil_sidorder *sidorder = NULL;
> +	struct cil_list_item *curr = NULL;
>   	int rc = SEPOL_ERR;
>
>   	if (db == NULL || parse_current == NULL || ast_node == NULL) {
> @@ -1124,6 +1148,15 @@ int cil_gen_sidorder(__attribute__((unused)) struct cil_db *db, struct cil_tree_
>   	if (rc != SEPOL_OK) {
>   		goto exit;
>   	}
> +
> +	cil_list_for_each(curr, sidorder->sid_list_str) {
> +		if (curr->data == CIL_KEY_UNORDERED) {
> +			cil_log(CIL_ERR, "Sidorder cannot be unordered.\n");
> +			rc = SEPOL_ERR;
> +			goto exit;
> +		}
> +	}
> +
>   	ast_node->data = sidorder;
>   	ast_node->flavor = CIL_SIDORDER;
>
> @@ -3553,6 +3586,7 @@ int cil_gen_catorder(__attribute__((unused)) struct cil_db *db, struct cil_tree_
>   	};
>   	int syntax_len = sizeof(syntax)/sizeof(*syntax);
>   	struct cil_catorder *catorder = NULL;
> +	struct cil_list_item *curr = NULL;
>   	int rc = SEPOL_ERR;
>
>   	if (db == NULL || parse_current == NULL || ast_node == NULL) {
> @@ -3570,6 +3604,15 @@ int cil_gen_catorder(__attribute__((unused)) struct cil_db *db, struct cil_tree_
>   	if (rc != SEPOL_OK) {
>   		goto exit;
>   	}
> +
> +	cil_list_for_each(curr, catorder->cat_list_str) {
> +		if (curr->data == CIL_KEY_UNORDERED) {
> +			cil_log(CIL_ERR, "Category order cannot be unordered.\n");
> +			rc = SEPOL_ERR;
> +			goto exit;
> +		}
> +	}
> +
>   	ast_node->data = catorder;
>   	ast_node->flavor = CIL_CATORDER;
>
> @@ -3604,6 +3647,7 @@ int cil_gen_sensitivityorder(__attribute__((unused)) struct cil_db *db, struct c
>   	};
>   	int syntax_len = sizeof(syntax)/sizeof(*syntax);
>   	struct cil_sensorder *sensorder = NULL;
> +	struct cil_list_item *curr = NULL;
>   	int rc = SEPOL_ERR;
>
>   	if (db == NULL || parse_current == NULL || ast_node == NULL) {
> @@ -3622,6 +3666,14 @@ int cil_gen_sensitivityorder(__attribute__((unused)) struct cil_db *db, struct c
>   		goto exit;
>   	}
>
> +	cil_list_for_each(curr, sensorder->sens_list_str) {
> +		if (curr->data == CIL_KEY_UNORDERED) {
> +			cil_log(CIL_ERR, "Sensitivy order cannot be unordered.\n");
> +			rc = SEPOL_ERR;
> +			goto exit;
> +		}
> +	}
> +
>   	ast_node->data = sensorder;
>   	ast_node->flavor = CIL_SENSITIVITYORDER;
>
> diff --git a/libsepol/cil/src/cil_internal.h b/libsepol/cil/src/cil_internal.h
> index a736eff..7f718d0 100644
> --- a/libsepol/cil/src/cil_internal.h
> +++ b/libsepol/cil/src/cil_internal.h
> @@ -223,6 +223,7 @@ char *CIL_KEY_AUDITALLOWX;
>   char *CIL_KEY_DONTAUDITX;
>   char *CIL_KEY_PERMISSIONX;
>   char *CIL_KEY_IOCTL;
> +char *CIL_KEY_UNORDERED;
>
>   /*
>   	Symbol Table Array Indices
> diff --git a/libsepol/cil/src/cil_list.c b/libsepol/cil/src/cil_list.c
> index 766985e..dbd554c 100644
> --- a/libsepol/cil/src/cil_list.c
> +++ b/libsepol/cil/src/cil_list.c
> @@ -246,3 +246,16 @@ void cil_list_remove(struct cil_list *list, enum cil_flavor flavor, void *data,
>   		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;
> +}
> diff --git a/libsepol/cil/src/cil_list.h b/libsepol/cil/src/cil_list.h
> index 16d743c..a028036 100644
> --- a/libsepol/cil/src/cil_list.h
> +++ b/libsepol/cil/src/cil_list.h
> @@ -58,5 +58,6 @@ void cil_list_remove(struct cil_list *list, enum cil_flavor flavor, void *data,
>   struct cil_list_item *cil_list_insert(struct cil_list *list, struct cil_list_item *curr, enum cil_flavor flavor, void *data);
>   void cil_list_append_item(struct cil_list *list, struct cil_list_item *item);
>   void cil_list_prepend_item(struct cil_list *list, struct cil_list_item *item);
> +int cil_list_contains(struct cil_list *list, void *data);
>
>   #endif
> diff --git a/libsepol/cil/src/cil_resolve_ast.c b/libsepol/cil/src/cil_resolve_ast.c
> index 0df5c63..deb3d38 100644
> --- a/libsepol/cil/src/cil_resolve_ast.c
> +++ b/libsepol/cil/src/cil_resolve_ast.c
> @@ -59,6 +59,7 @@ struct cil_args_resolve {
>   	struct cil_tree_node *blockstack;
>   	struct cil_list *sidorder_lists;
>   	struct cil_list *classorder_lists;
> +	struct cil_list *unordered_classorder_lists;
>   	struct cil_list *catorder_lists;
>   	struct cil_list *sensitivityorder_lists;
>   	struct cil_list *in_list;
> @@ -1176,7 +1177,7 @@ void __cil_ordered_lists_destroy(struct cil_list **ordered_lists)
>   {
>   	struct cil_list_item *item = NULL;
>
> -	if (*ordered_lists == NULL) {
> +	if (ordered_lists == NULL || *ordered_lists == NULL) {
>   		return;
>   	}
>
> @@ -1351,7 +1352,42 @@ int __cil_ordered_lists_merge(struct cil_list *old, struct cil_list *new)
>   	return SEPOL_OK;
>   }
>
> -struct cil_list *__cil_ordered_lists_merge_all(struct cil_list **ordered_lists)
> +static int insert_unordered(struct cil_list *merged, struct cil_list *unordered)
> +{
> +	struct cil_list_item *curr = NULL;
> +	struct cil_ordered_list *unordered_list = NULL;
> +	struct cil_list_item *item = NULL;
> +	struct cil_list_item *ret = NULL;
> +	int rc = SEPOL_ERR;
> +
> +	cil_list_for_each(curr, unordered) {
> +		unordered_list = curr->data;
> +
> +		cil_list_for_each(item, unordered_list->list) {
> +			if (cil_list_contains(merged, item->data)) {
> +				/* item was declared in an ordered statement, which supercedes
> +				 * all unordered statements */
> +				if (item->flavor == CIL_CLASS) {
> +					cil_log(CIL_WARN, "Ignoring '%s' as it has already been declared in classorder.\n", ((struct cil_class*)(item->data))->datum.name);
> +				}
> +				continue;
> +			}
> +
> +			ret = __cil_ordered_item_insert(merged, merged->tail, item);
> +			if (ret == NULL) {
> +				rc = SEPOL_ERR;
> +				goto exit;
> +			}
> +		}
> +	}
> +
> +	rc = SEPOL_OK;
> +
> +exit:
> +	return rc;
> +}
> +
> +struct cil_list *__cil_ordered_lists_merge_all(struct cil_list **ordered_lists, struct cil_list **unordered_lists)
>   {
>   	struct cil_list *composite = NULL;
>   	struct cil_list_item *curr = NULL;
> @@ -1388,11 +1424,21 @@ struct cil_list *__cil_ordered_lists_merge_all(struct cil_list **ordered_lists)
>   		}
>   	}
>
> +	if (unordered_lists != NULL) {
> +		rc = insert_unordered(composite, *unordered_lists);
> +		if (rc != SEPOL_OK) {
> +			goto exit;
> +		}
> +	}
> +
>   	__cil_ordered_lists_destroy(ordered_lists);
> +	__cil_ordered_lists_destroy(unordered_lists);
>
>   	return composite;
>
>   exit:
> +	__cil_ordered_lists_destroy(ordered_lists);
> +	__cil_ordered_lists_destroy(unordered_lists);
>   	cil_list_destroy(&composite, CIL_FALSE);
>   	return NULL;
>   }
> @@ -1401,16 +1447,23 @@ int cil_resolve_classorder(struct cil_tree_node *current, void *extra_args)
>   {
>   	struct cil_args_resolve *args = extra_args;
>   	struct cil_list *classorder_list = args->classorder_lists;
> +	struct cil_list *unordered_classorder_list = args->unordered_classorder_lists;
>   	struct cil_classorder *classorder = current->data;
>   	struct cil_list *new = NULL;
>   	struct cil_list_item *curr = NULL;
>   	struct cil_symtab_datum *datum = NULL;
> -	struct cil_ordered_list *ordered = NULL;
> +	struct cil_ordered_list *class_list = NULL;
>   	int rc = SEPOL_ERR;
> +	int unordered = CIL_FALSE;
>
>   	cil_list_init(&new, CIL_CLASSORDER);
>
>   	cil_list_for_each(curr, classorder->class_list_str) {
> +		if (curr->data == CIL_KEY_UNORDERED) {
> +			unordered = CIL_TRUE;
> +			continue;
> +		}
> +
>   		rc = cil_resolve_name(current, (char *)curr->data, CIL_SYM_CLASSES, extra_args, &datum);
>   		if (rc != SEPOL_OK) {
>   			cil_log(CIL_ERR, "Failed to resolve class %s in classorder\n", (char *)curr->data);
> @@ -1419,10 +1472,14 @@ int cil_resolve_classorder(struct cil_tree_node *current, void *extra_args)
>   		cil_list_append(new, CIL_CLASS, datum);
>   	}
>
> -	__cil_ordered_list_init(&ordered);
> -	ordered->list = new;
> -	ordered->node = current;
> -	cil_list_append(classorder_list, CIL_CLASSORDER, ordered);
> +	__cil_ordered_list_init(&class_list);
> +	class_list->list = new;
> +	class_list->node = current;
> +	if (unordered) {
> +		cil_list_append(unordered_classorder_list, CIL_CLASSORDER, class_list);
> +	} else {
> +		cil_list_append(classorder_list, CIL_CLASSORDER, class_list);
> +	}
>
>   	return SEPOL_OK;
>
> @@ -3651,6 +3708,7 @@ int cil_resolve_ast(struct cil_db *db, struct cil_tree_node *current)
>   	extra_args.macro = NULL;
>   	extra_args.sidorder_lists = NULL;
>   	extra_args.classorder_lists = NULL;
> +	extra_args.unordered_classorder_lists = NULL;
>   	extra_args.catorder_lists = NULL;
>   	extra_args.sensitivityorder_lists = NULL;
>   	extra_args.in_list = NULL;
> @@ -3658,6 +3716,7 @@ int cil_resolve_ast(struct cil_db *db, struct cil_tree_node *current)
>
>   	cil_list_init(&extra_args.sidorder_lists, CIL_LIST_ITEM);
>   	cil_list_init(&extra_args.classorder_lists, CIL_LIST_ITEM);
> +	cil_list_init(&extra_args.unordered_classorder_lists, CIL_LIST_ITEM);
>   	cil_list_init(&extra_args.catorder_lists, CIL_LIST_ITEM);
>   	cil_list_init(&extra_args.sensitivityorder_lists, CIL_LIST_ITEM);
>   	cil_list_init(&extra_args.in_list, CIL_IN);
> @@ -3678,11 +3737,27 @@ int cil_resolve_ast(struct cil_db *db, struct cil_tree_node *current)
>   		}
>
>   		if (pass == CIL_PASS_MISC1) {
> -			db->sidorder = __cil_ordered_lists_merge_all(&extra_args.sidorder_lists);
> -			db->classorder = __cil_ordered_lists_merge_all(&extra_args.classorder_lists);
> -			db->catorder = __cil_ordered_lists_merge_all(&extra_args.catorder_lists);
> +			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);
> +			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) {
> @@ -3718,6 +3793,7 @@ int cil_resolve_ast(struct cil_db *db, struct cil_tree_node *current)
>   			if (pass >= CIL_PASS_MISC1) {
>   				__cil_ordered_lists_reset(&extra_args.sidorder_lists);
>   				__cil_ordered_lists_reset(&extra_args.classorder_lists);
> +				__cil_ordered_lists_reset(&extra_args.unordered_classorder_lists);
>   				__cil_ordered_lists_reset(&extra_args.catorder_lists);
>   				__cil_ordered_lists_reset(&extra_args.sensitivityorder_lists);
>   				cil_list_destroy(&db->sidorder, CIL_FALSE);
> diff --git a/secilc/docs/cil_class_and_permission_statements.xml b/secilc/docs/cil_class_and_permission_statements.xml
> index 2926d7c..20c3eb7 100644
> --- a/secilc/docs/cil_class_and_permission_statements.xml
> +++ b/secilc/docs/cil_class_and_permission_statements.xml
> @@ -198,6 +198,22 @@
>   (classorder (file dir))
>   (classorder (dir process))]]>
>         </programlisting>
> +         <para><emphasis role="bold">Unordered Classorder Statement:</emphasis></para>
> +         <para>If users do not have knowledge of the existing classorder, the <literal>unordered</literal> keyword may be used in a <literal>classorder</literal> statement. The <link linkend="class">class</link>es in an unordered statement are appended to the existing classorder. A class in an ordered statement always supercedes the class redeclaration in an unordered statement. The <literal>unordered</literal> keyword must be the first item in the classorder listing.</para>
> +         <para><emphasis role="bold">Example:</emphasis></para>
> +         <para>This will produce an ordered list of "<literal>file dir foo a bar baz</literal>"</para>
> +         <programlisting><![CDATA[
> +(class file)
> +(class dir)
> +(class foo)
> +(class bar)
> +(class baz)
> +(class a)
> +(classorder (file dir))
> +(classorder (dir foo))
> +(classorder (unordered a))
> +(classorder (unordered bar foo baz))]]>
> +      </programlisting>
>         </sect2>
>        <sect2 id="classpermission">
>            <title>classpermission</title>
> diff --git a/secilc/test/policy.cil b/secilc/test/policy.cil
> index 69103d1..884d2dc 100644
> --- a/secilc/test/policy.cil
> +++ b/secilc/test/policy.cil
> @@ -46,8 +46,13 @@
>   (levelrange lh4 ((s0) (s1)))
>
>   (block policy
> -	(classorder (file char dir))
> -	(class file (execute_no_trans entrypoint execmod open audit_access))
> +	(class file (execute_no_trans entrypoint execmod open audit_access a b c d e))
> +	; order should be: file char b c a dir d e f
> +	(classorder (file char))
> +	(classorder (unordered dir))
> +	(classorder (unordered c a b d e f))
> +	(classorder (char b c a))
> +
>   	(common file (ioctl read write create getattr setattr lock relabelfrom
>   			relabelto append unlink link rename execute swapon
>   			quotaon mounton))
> @@ -67,6 +72,12 @@
>   	(classcommon char file)
>
>   	(class dir ())
> +	(class a ())
> +	(class b ())
> +	(class c ())
> +	(class d ())
> +	(class e ())
> +	(class f ())
>   	(classcommon dir file)
>
>   	(classpermission char_w)
>


-- 
James Carter <jwcart2@tycho.nsa.gov>
National Security Agency

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2015-11-13 15:18 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-11-10 15:58 [PATCH] secilc: Add support for unordered classes ykhodorkovskiy
2015-11-10 16:08 ` Dominick Grift
2015-11-10 16:21 ` Dominick Grift
2015-11-13 15:18 ` James Carter

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.