All of lore.kernel.org
 help / color / mirror / Atom feed
From: James Carter <jwcart2@gmail.com>
To: selinux@vger.kernel.org
Cc: nicolas.iooss@m4x.org, James Carter <jwcart2@gmail.com>
Subject: [PATCH 2/5] libsepol/cil: Detect degenerate inheritance and exit with an error
Date: Wed, 28 Apr 2021 16:17:50 -0400	[thread overview]
Message-ID: <20210428201753.282831-3-jwcart2@gmail.com> (raw)
In-Reply-To: <20210428201753.282831-1-jwcart2@gmail.com>

A CIL policy with inheritance of the form
...
(blockinherit ba)
(block ba
  (block b1
    (blockinherit bb)
  )
  (block bb
    (block b2
      (blockinherit bc)
    )
    (block bc
      (block b3
        (blockinherit bd)
      )
      (block bd
        (block b4
          (blockinherit be)
        )
        (block be
        ...
will require creating 2^depth copies of the block at the bottom of
the inheritance chain. This pattern can quickly consume all the
memory of the system compiling this policy.

The depth of the inheritance chain can be found be walking the
tree up through the parents and noting how many of the parent
blocks have been inherited. The number of times a block will be
copied is found by counting the list of nodes in the "bi_nodes"
list of the block. To minimize legitimate policies from being
falsely detected as being degenerate, both the depth and breadth
(number of copies) are checked and an error is given only if both
exceed the limits (depth >= 12 and breadth >= 4096).

This problem was found by the secilc-fuzzer.

Signed-off-by: James Carter <jwcart2@gmail.com>
---
 libsepol/cil/src/cil_internal.h    |  2 ++
 libsepol/cil/src/cil_resolve_ast.c | 54 ++++++++++++++++++++++++++++++
 2 files changed, 56 insertions(+)

diff --git a/libsepol/cil/src/cil_internal.h b/libsepol/cil/src/cil_internal.h
index 9bdcbdd0..74e0b34d 100644
--- a/libsepol/cil/src/cil_internal.h
+++ b/libsepol/cil/src/cil_internal.h
@@ -48,6 +48,8 @@
 
 #define CIL_MAX_NAME_LENGTH 2048
 
+#define CIL_DEGENERATE_INHERITANCE_DEPTH 12
+#define CIL_DEGENERATE_INHERITANCE_BREADTH (0x1 << CIL_DEGENERATE_INHERITANCE_DEPTH)
 
 enum cil_pass {
 	CIL_PASS_INIT = 0,
diff --git a/libsepol/cil/src/cil_resolve_ast.c b/libsepol/cil/src/cil_resolve_ast.c
index 5389df43..68909647 100644
--- a/libsepol/cil/src/cil_resolve_ast.c
+++ b/libsepol/cil/src/cil_resolve_ast.c
@@ -2410,6 +2410,55 @@ exit:
 	return rc;
 }
 
+/*
+ * Detect degenerate inheritance of the form:
+ * ...
+ * (blockinherit ba)
+ * (block ba
+ *    (block b1
+ *      (blockinherit bb)
+ *    )
+ *    (block bb
+ *      (block b2
+ *        (blockinherit bc)
+ *      )
+ *      (block bc
+ *      ...
+ */
+static int cil_check_for_degenerate_inheritance(struct cil_tree_node *current)
+{
+	struct cil_block *block = current->data;
+	struct cil_tree_node *node;
+	struct cil_list_item *item;
+	unsigned depth;
+	unsigned breadth = 0;
+
+	cil_list_for_each(item, block->bi_nodes) {
+		breadth++;
+	}
+
+	if (breadth >= CIL_DEGENERATE_INHERITANCE_BREADTH) {
+		node = current->parent;
+		depth = 0;
+		while (node && node->flavor != CIL_ROOT) {
+			if (node->flavor == CIL_BLOCK) {
+				block = node->data;
+				if (block->bi_nodes != NULL) {
+					depth++;
+				}
+			}
+			node = node->parent;
+		}
+
+		if (depth >= CIL_DEGENERATE_INHERITANCE_DEPTH) {
+			cil_tree_log(current, CIL_ERR, "Degenerate inheritance detected (depth=%u, breadth=%u)", depth, breadth);
+			return SEPOL_ERR;
+		}
+	}
+
+	return SEPOL_OK;
+}
+
 int cil_resolve_blockinherit_copy(struct cil_tree_node *current, void *extra_args)
 {
 	struct cil_block *block = current->data;
@@ -2426,6 +2475,11 @@ int cil_resolve_blockinherit_copy(struct cil_tree_node *current, void *extra_arg
 
 	db = args->db;
 
+	rc = cil_check_for_degenerate_inheritance(current);
+	if (rc != SEPOL_OK) {
+		goto exit;
+	}
+
 	// Make sure this is the original block and not a merged block from a blockinherit
 	if (current != block->datum.nodes->head->data) {
 		rc = SEPOL_OK;
-- 
2.26.3


  parent reply	other threads:[~2021-04-28 20:18 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-04-28 20:17 [PATCH 0/5] Fix bugs identified by the secilc-fuzzer James Carter
2021-04-28 20:17 ` [PATCH 1/5] libsepol/cil: Fix instances where an error returns SEPOL_OK James Carter
2021-04-28 20:17 ` James Carter [this message]
2021-04-28 20:17 ` [PATCH 3/5] libsepol/cil: Check datum in ordered list for expected flavor James Carter
2021-04-28 20:17 ` [PATCH 4/5] libsepol/cil: Check for self-referential loops in sets James Carter
2021-05-01 14:33   ` Nicolas Iooss
2021-05-03 13:48     ` James Carter
2021-04-28 20:17 ` [PATCH 5/5] libsepol/cil: Return an error if a call argument fails to resolve James Carter
2021-05-04 20:07 ` [PATCH 0/5] Fix bugs identified by the secilc-fuzzer James Carter

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210428201753.282831-3-jwcart2@gmail.com \
    --to=jwcart2@gmail.com \
    --cc=nicolas.iooss@m4x.org \
    --cc=selinux@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.