summaryrefslogtreecommitdiff
path: root/pcr/libsepol/0007-libsepol-cil-Verify-neither-child-nor-parent-in-a-bo.patch
blob: bed074d59a06fb00425c9108fa3ca1cda47ff02d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
From ab1b88b4e9938048bafabeab7c87c456a5f96196 Mon Sep 17 00:00:00 2001
From: James Carter <jwcart2@tycho.nsa.gov>
Date: Tue, 18 Oct 2016 14:50:48 -0400
Subject: [PATCH] libsepol/cil: Verify neither child nor parent in a bounds is
 an attribute

Nicolas Iooss found while fuzzing secilc with AFL that using an attribute
as a child in a typebounds statement will cause a segfault.

This happens because the child datum is assumed to be part of a cil_type
struct when it is really part of a cil_typeattribute struct. The check to
verify that it is a type and not an attribute comes after it is used.

This bug effects user and role bounds as well because they do not check
whether a datum refers to an attribute or not.

Add checks to verify that neither the child nor the parent datum refer
to an attribute before using them in user, role, and type bounds.

Signed-off-by: James Carter <jwcart2@tycho.nsa.gov>
---
 libsepol/cil/src/cil_resolve_ast.c | 44 ++++++++++++++++----------------------
 1 file changed, 18 insertions(+), 26 deletions(-)

diff --git a/libsepol/cil/src/cil_resolve_ast.c b/libsepol/cil/src/cil_resolve_ast.c
index 149e4f4e7d42..ec547d38125d 100644
--- a/libsepol/cil/src/cil_resolve_ast.c
+++ b/libsepol/cil/src/cil_resolve_ast.c
@@ -2468,7 +2468,7 @@ exit:
 }
 
 
-int cil_resolve_bounds(struct cil_tree_node *current, void *extra_args, enum cil_flavor flavor)
+int cil_resolve_bounds(struct cil_tree_node *current, void *extra_args, enum cil_flavor flavor, enum cil_flavor attr_flavor)
 {
 	int rc = SEPOL_ERR;
 	struct cil_bounds *bounds = current->data;
@@ -2485,19 +2485,29 @@ int cil_resolve_bounds(struct cil_tree_node *current, void *extra_args, enum cil
 	if (rc != SEPOL_OK) {
 		goto exit;
 	}
+	if (NODE(parent_datum)->flavor == attr_flavor) {
+		cil_log(CIL_ERR, "Bounds parent %s is an attribute\n", bounds->parent_str);
+		rc = SEPOL_ERR;
+		goto exit;
+	}
+
 
 	rc = cil_resolve_name(current, bounds->child_str, index, extra_args, &child_datum);
 	if (rc != SEPOL_OK) {
 		goto exit;
 	}
+	if (NODE(child_datum)->flavor == attr_flavor) {
+		cil_log(CIL_ERR, "Bounds child %s is an attribute\n", bounds->child_str);
+		rc = SEPOL_ERR;
+		goto exit;
+	}
 
 	switch (flavor) {
 	case CIL_USER: {
 		struct cil_user *user = (struct cil_user *)child_datum;
 
 		if (user->bounds != NULL) {
-			struct cil_tree_node *node = user->bounds->datum.nodes->head->data;
-			cil_tree_log(node, CIL_ERR, "User %s already bound by parent", bounds->child_str);
+			cil_tree_log(NODE(user->bounds), CIL_ERR, "User %s already bound by parent", bounds->child_str);
 			rc = SEPOL_ERR;
 			goto exit;
 		}
@@ -2509,8 +2519,7 @@ int cil_resolve_bounds(struct cil_tree_node *current, void *extra_args, enum cil
 		struct cil_role *role = (struct cil_role *)child_datum;
 
 		if (role->bounds != NULL) {
-			struct cil_tree_node *node = role->bounds->datum.nodes->head->data;
-			cil_tree_log(node, CIL_ERR, "Role %s already bound by parent", bounds->child_str);
+			cil_tree_log(NODE(role->bounds), CIL_ERR, "Role %s already bound by parent", bounds->child_str);
 			rc = SEPOL_ERR;
 			goto exit;
 		}
@@ -2520,26 +2529,9 @@ int cil_resolve_bounds(struct cil_tree_node *current, void *extra_args, enum cil
 	}
 	case CIL_TYPE: {
 		struct cil_type *type = (struct cil_type *)child_datum;
-		struct cil_tree_node *node = NULL;
 
 		if (type->bounds != NULL) {
-			node = ((struct cil_symtab_datum *)type->bounds)->nodes->head->data;
-			cil_tree_log(node, CIL_ERR, "Type %s already bound by parent", bounds->child_str);
-			cil_tree_log(current, CIL_ERR, "Now being bound to parent %s", bounds->parent_str);
-			rc = SEPOL_ERR;
-			goto exit;
-		}
-
-		node = parent_datum->nodes->head->data;
-		if (node->flavor == CIL_TYPEATTRIBUTE) {
-			cil_log(CIL_ERR, "Bounds parent %s is an attribute\n", bounds->parent_str);
-			rc = SEPOL_ERR;
-			goto exit;
-		}
-
-		node = child_datum->nodes->head->data;
-		if (node->flavor == CIL_TYPEATTRIBUTE) {
-			cil_log(CIL_ERR, "Bounds child %s is an attribute\n", bounds->child_str);
+			cil_tree_log(NODE(type->bounds), CIL_ERR, "Type %s already bound by parent", bounds->child_str);
 			rc = SEPOL_ERR;
 			goto exit;
 		}
@@ -3445,7 +3437,7 @@ int __cil_resolve_ast_node(struct cil_tree_node *node, void *extra_args)
 			rc = cil_resolve_typeattributeset(node, args);
 			break;
 		case CIL_TYPEBOUNDS:
-			rc = cil_resolve_bounds(node, args, CIL_TYPE);
+			rc = cil_resolve_bounds(node, args, CIL_TYPE, CIL_TYPEATTRIBUTE);
 			break;
 		case CIL_TYPEPERMISSIVE:
 			rc = cil_resolve_typepermissive(node, args);
@@ -3482,7 +3474,7 @@ int __cil_resolve_ast_node(struct cil_tree_node *node, void *extra_args)
 			rc = cil_resolve_userrange(node, args);
 			break;
 		case CIL_USERBOUNDS:
-			rc = cil_resolve_bounds(node, args, CIL_USER);
+			rc = cil_resolve_bounds(node, args, CIL_USER, CIL_USERATTRIBUTE);
 			break;
 		case CIL_USERPREFIX:
 			rc = cil_resolve_userprefix(node, args);
@@ -3504,7 +3496,7 @@ int __cil_resolve_ast_node(struct cil_tree_node *node, void *extra_args)
 			rc = cil_resolve_roleallow(node, args);
 			break;
 		case CIL_ROLEBOUNDS:
-			rc = cil_resolve_bounds(node, args, CIL_ROLE);
+			rc = cil_resolve_bounds(node, args, CIL_ROLE, CIL_ROLEATTRIBUTE);
 			break;
 		case CIL_LEVEL:
 			rc = cil_resolve_level(node, (struct cil_level*)node->data, args);
-- 
2.10.2