blob: c5241e01a3dca47b2cfc67f07fa28978f14ddf1b [file] [log] [blame]
Pierre-Hugues Husson2acef1d2018-04-05 20:10:30 +02001From 9b009c3354946ec04c60b87d344ed2abbe63c4ba Mon Sep 17 00:00:00 2001
2From: James Carter <jwcart2@tycho.nsa.gov>
3Date: Thu, 29 Mar 2018 16:06:49 -0400
4Subject: [PATCH 5/5] libsepol/cil: Improve processing of context rules
5
6Improve the processing of netifcon, genfscon, ibpkeycon, ibendportcon,
7portcon, nodecon, fsuse, filecon, iomemcon, ioportcon, pcidevicecon,
8and devicetreecon rules.
9
10If the multiple-decls option is not used then report errors if duplicate
11context rules are found. If it is used then remove duplicate context rules
12and report errors when two rules are identical except for the context.
13
14This also changes the ordering of portcon and filecon rules. The protocol
15of portcon rules will be compared if the port numbers are the same and the
16path strings of filecon rules will be compared if the number of meta
17characters, the stem length, string length and file types are the same.
18
19Based on an initial patch by Pierre-Hugues Husson (phh@phh.me)
20
21Signed-off-by: James Carter <jwcart2@tycho.nsa.gov>
22---
23 libsepol/cil/src/cil_post.c | 303 ++++++++++++++++++++++++++++++++++++++++++--
24 1 file changed, 292 insertions(+), 11 deletions(-)
25
26diff --git a/libsepol/cil/src/cil_post.c b/libsepol/cil/src/cil_post.c
27index a30de0e..3799350 100644
28--- a/libsepol/cil/src/cil_post.c
29+++ b/libsepol/cil/src/cil_post.c
30@@ -53,6 +53,83 @@
31 static int __cil_expr_to_bitmap(struct cil_list *expr, ebitmap_t *out, int max, struct cil_db *db);
32 static int __cil_expr_list_to_bitmap(struct cil_list *expr_list, ebitmap_t *out, int max, struct cil_db *db);
33
34+static int cats_compare(struct cil_cats *a, struct cil_cats *b)
35+{
36+ struct cil_list_item *i, *j;
37+ int rc;
38+
39+ if (a == b) return 0;
40+ if (!a) return -1;
41+ if (!b) return 1;
42+
43+ /* Expects cat expression to have been evaluated */
44+ cil_list_for_each(i, a->datum_expr) {
45+ cil_list_for_each(j, b->datum_expr) {
46+ rc = strcmp(DATUM(i->data)->fqn, DATUM(j->data)->fqn);
47+ if (!rc) return rc;
48+ }
49+ }
50+ return 0;
51+}
52+
53+static int level_compare(struct cil_level *a, struct cil_level *b)
54+{
55+ int rc;
56+
57+ if (a == b) return 0;
58+ if (!a) return -1;
59+ if (!b) return 1;
60+
61+ if (a->sens != b->sens) {
62+ rc = strcmp(DATUM(a->sens)->fqn, DATUM(b->sens)->fqn);
63+ if (rc != 0) return rc;
64+ }
65+ if (a->cats != b->cats) {
66+ return cats_compare(a->cats, b->cats);
67+ }
68+ return 0;
69+}
70+
71+static int range_compare(struct cil_levelrange *a, struct cil_levelrange *b)
72+{
73+ int rc;
74+
75+ if (a == b) return 0;
76+ if (!a) return -1;
77+ if (!b) return 1;
78+
79+ if (a->low != b->low) {
80+ rc = level_compare(a->low, b->low);
81+ if (rc != 0) return rc;
82+ }
83+ if (a->high != b->high) {
84+ return level_compare(a->high, b->high);
85+ }
86+ return 0;
87+}
88+
89+static int context_compare(struct cil_context *a, struct cil_context *b)
90+{
91+ int rc;
92+
93+ if (a->user != b->user) {
94+ rc = strcmp(DATUM(a->user)->fqn, DATUM(b->user)->fqn);
95+ if (rc != 0) return rc;
96+ }
97+ if (a->role != b->role) {
98+ rc = strcmp(DATUM(a->role)->fqn, DATUM(b->role)->fqn);
99+ if (rc != 0) return rc;
100+ }
101+ if (a->type != b->type) {
102+ rc = strcmp(DATUM(a->type)->fqn, DATUM(b->type)->fqn);
103+ if (rc != 0) return rc;
104+ }
105+ if (a->range != b->range) {
106+ return range_compare(a->range, b->range);
107+ }
108+ return 0;
109+}
110+
111 static int cil_verify_is_list(struct cil_list *list, enum cil_flavor flavor)
112 {
113 struct cil_list_item *curr;
114@@ -144,6 +221,8 @@ int cil_post_filecon_compare(const void *a, const void *b)
115 rc = -1;
116 } else if (b_filecon->type < a_filecon->type) {
117 rc = 1;
118+ } else {
119+ rc = strcmp(a_filecon->path_str, b_filecon->path_str);
120 }
121
122 free(a_path);
123@@ -167,6 +246,10 @@ int cil_post_portcon_compare(const void *a, const void *b)
124 rc = -1;
125 } else if (bportcon->port_low < aportcon->port_low) {
126 rc = 1;
127+ } else if (aportcon->proto < bportcon->proto) {
128+ rc = -1;
129+ } else if (aportcon->proto > bportcon->proto) {
130+ rc = 1;
131 }
132 }
133
134@@ -327,6 +410,88 @@ int cil_post_fsuse_compare(const void *a, const void *b)
135 return rc;
136 }
137
138+int cil_post_filecon_context_compare(const void *a, const void *b)
139+{
140+ struct cil_filecon *a_filecon = *(struct cil_filecon**)a;
141+ struct cil_filecon *b_filecon = *(struct cil_filecon**)b;
142+ return context_compare(a_filecon->context, b_filecon->context);
143+}
144+
145+int cil_post_portcon_context_compare(const void *a, const void *b)
146+{
147+ struct cil_portcon *a_portcon = *(struct cil_portcon**)a;
148+ struct cil_portcon *b_portcon = *(struct cil_portcon**)b;
149+ return context_compare(a_portcon->context, b_portcon->context);
150+}
151+
152+int cil_post_genfscon_context_compare(const void *a, const void *b)
153+{
154+ struct cil_genfscon *a_genfscon = *(struct cil_genfscon**)a;
155+ struct cil_genfscon *b_genfscon = *(struct cil_genfscon**)b;
156+ return context_compare(a_genfscon->context, b_genfscon->context);
157+}
158+
159+int cil_post_netifcon_context_compare(const void *a, const void *b)
160+{
161+ int rc;
162+ struct cil_netifcon *a_netifcon = *(struct cil_netifcon**)a;
163+ struct cil_netifcon *b_netifcon = *(struct cil_netifcon**)b;
164+ rc = context_compare(a_netifcon->if_context, b_netifcon->if_context);
165+ if (rc != 0) {
166+ return rc;
167+ }
168+ return context_compare(a_netifcon->packet_context, b_netifcon->packet_context);
169+}
170+
171+int cil_post_nodecon_context_compare(const void *a, const void *b)
172+{
173+ struct cil_nodecon *a_nodecon = *(struct cil_nodecon **)a;
174+ struct cil_nodecon *b_nodecon = *(struct cil_nodecon **)b;
175+ return context_compare(a_nodecon->context, b_nodecon->context);
176+}
177+
178+int cil_post_pirqcon_context_compare(const void *a, const void *b)
179+{
180+ struct cil_pirqcon *a_pirqcon = *(struct cil_pirqcon**)a;
181+ struct cil_pirqcon *b_pirqcon = *(struct cil_pirqcon**)b;
182+ return context_compare(a_pirqcon->context, b_pirqcon->context);
183+}
184+
185+int cil_post_iomemcon_context_compare(const void *a, const void *b)
186+{
187+ struct cil_iomemcon *a_iomemcon = *(struct cil_iomemcon**)a;
188+ struct cil_iomemcon *b_iomemcon = *(struct cil_iomemcon**)b;
189+ return context_compare(a_iomemcon->context, b_iomemcon->context);
190+}
191+
192+int cil_post_ioportcon_context_compare(const void *a, const void *b)
193+{
194+ struct cil_ioportcon *a_ioportcon = *(struct cil_ioportcon**)a;
195+ struct cil_ioportcon *b_ioportcon = *(struct cil_ioportcon**)b;
196+ return context_compare(a_ioportcon->context, b_ioportcon->context);
197+}
198+
199+int cil_post_pcidevicecon_context_compare(const void *a, const void *b)
200+{
201+ struct cil_pcidevicecon *a_pcidevicecon = *(struct cil_pcidevicecon**)a;
202+ struct cil_pcidevicecon *b_pcidevicecon = *(struct cil_pcidevicecon**)b;
203+ return context_compare(a_pcidevicecon->context, b_pcidevicecon->context);
204+}
205+
206+int cil_post_devicetreecon_context_compare(const void *a, const void *b)
207+{
208+ struct cil_devicetreecon *a_devicetreecon = *(struct cil_devicetreecon**)a;
209+ struct cil_devicetreecon *b_devicetreecon = *(struct cil_devicetreecon**)b;
210+ return context_compare(a_devicetreecon->context, b_devicetreecon->context);
211+}
212+
213+int cil_post_fsuse_context_compare(const void *a, const void *b)
214+{
215+ struct cil_fsuse *a_fsuse = *(struct cil_fsuse**)a;
216+ struct cil_fsuse *b_fsuse = *(struct cil_fsuse**)b;
217+ return context_compare(a_fsuse->context, b_fsuse->context);
218+}
219+
220 static int __cil_post_db_count_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args)
221 {
222 struct cil_db *db = extra_args;
223@@ -1929,6 +2094,74 @@ exit:
224 return rc;
225 }
226
227+static int __cil_post_report_conflict(struct cil_tree_node *node, uint32_t *finished, void *extra_args)
228+{
229+ struct cil_list_item *li = extra_args;
230+
231+ if (node->flavor == CIL_BLOCK) {
232+ struct cil_block *blk = node->data;
233+ if (blk->is_abstract == CIL_TRUE) {
234+ *finished = CIL_TREE_SKIP_HEAD;
235+ }
236+ } else if (node->flavor == CIL_MACRO) {
237+ *finished = CIL_TREE_SKIP_HEAD;
238+ } else if (node->flavor == li->flavor) {
239+ if (node->data == li->data) {
240+ char *path = cil_tree_get_cil_path(node);
241+ cil_log(CIL_WARN, " at %s:%d\n", path, node->line);
242+ }
243+ }
244+ return SEPOL_OK;
245+}
246+
247+static int __cil_post_process_context_rules(struct cil_sort *sort, int (*compar)(const void *, const void *), int (*concompar)(const void *, const void *), struct cil_db *db, enum cil_flavor flavor, const char *flavor_str)
248+{
249+ uint32_t count = sort->count;
250+ uint32_t i, j = 0, removed = 0;
251+ int rc = SEPOL_OK;
252+
253+ if (count < 2) {
254+ return SEPOL_OK;
255+ }
256+
257+ qsort(sort->array, sort->count, sizeof(sort->array), compar);
258+
259+ for (i=1; i<count; i++) {
260+ if (compar(&sort->array[i], &sort->array[j]) != 0) {
261+ j++;
262+ } else {
263+ removed++;
264+ if (!db->multiple_decls ||
265+ concompar(&sort->array[i], &sort->array[j]) != 0) {
266+ struct cil_list_item li;
267+ int rc2;
268+ cil_log(CIL_WARN, "Found conflicting %s rules\n",
269+ flavor_str);
270+ rc = SEPOL_ERR;
271+ li.flavor = flavor;
272+ li.data = sort->array[i];
273+ rc2 = cil_tree_walk(db->ast->root,
274+ __cil_post_report_conflict,
275+ NULL, NULL, &li);
276+ if (rc2 != SEPOL_OK) goto exit;
277+ li.data = sort->array[j];
278+ rc2 = cil_tree_walk(db->ast->root,
279+ __cil_post_report_conflict,
280+ NULL, NULL, &li);
281+ if (rc2 != SEPOL_OK) goto exit;
282+ }
283+ }
284+ if (i != j) {
285+ sort->array[j] = sort->array[i];
286+ }
287+ }
288+
289+ sort->count = count - removed;
290+
291+exit:
292+ return rc;
293+}
294+
295 static int cil_post_db(struct cil_db *db)
296 {
297 int rc = SEPOL_ERR;
298@@ -1975,17 +2208,65 @@ static int cil_post_db(struct cil_db *db)
299 goto exit;
300 }
301
302- qsort(db->netifcon->array, db->netifcon->count, sizeof(db->netifcon->array), cil_post_netifcon_compare);
303- qsort(db->genfscon->array, db->genfscon->count, sizeof(db->genfscon->array), cil_post_genfscon_compare);
304- qsort(db->portcon->array, db->portcon->count, sizeof(db->portcon->array), cil_post_portcon_compare);
305- qsort(db->nodecon->array, db->nodecon->count, sizeof(db->nodecon->array), cil_post_nodecon_compare);
306- qsort(db->fsuse->array, db->fsuse->count, sizeof(db->fsuse->array), cil_post_fsuse_compare);
307- qsort(db->filecon->array, db->filecon->count, sizeof(db->filecon->array), cil_post_filecon_compare);
308- qsort(db->pirqcon->array, db->pirqcon->count, sizeof(db->pirqcon->array), cil_post_pirqcon_compare);
309- qsort(db->iomemcon->array, db->iomemcon->count, sizeof(db->iomemcon->array), cil_post_iomemcon_compare);
310- qsort(db->ioportcon->array, db->ioportcon->count, sizeof(db->ioportcon->array), cil_post_ioportcon_compare);
311- qsort(db->pcidevicecon->array, db->pcidevicecon->count, sizeof(db->pcidevicecon->array), cil_post_pcidevicecon_compare);
312- qsort(db->devicetreecon->array, db->devicetreecon->count, sizeof(db->devicetreecon->array), cil_post_devicetreecon_compare);
313+ rc = __cil_post_process_context_rules(db->netifcon, cil_post_netifcon_compare, cil_post_netifcon_context_compare, db, CIL_NETIFCON, CIL_KEY_NETIFCON);
314+ if (rc != SEPOL_OK) {
315+ cil_log(CIL_ERR, "Problems processing netifcon rules\n");
316+ goto exit;
317+ }
318+
319+ rc = __cil_post_process_context_rules(db->genfscon, cil_post_genfscon_compare, cil_post_genfscon_context_compare, db, CIL_GENFSCON, CIL_KEY_GENFSCON);
320+ if (rc != SEPOL_OK) {
321+ cil_log(CIL_ERR, "Problems processing genfscon rules\n");
322+ goto exit;
323+ }
324+
325+ rc = __cil_post_process_context_rules(db->portcon, cil_post_portcon_compare, cil_post_portcon_context_compare, db, CIL_PORTCON, CIL_KEY_PORTCON);
326+ if (rc != SEPOL_OK) {
327+ cil_log(CIL_ERR, "Problems processing portcon rules\n");
328+ goto exit;
329+ }
330+
331+ rc = __cil_post_process_context_rules(db->nodecon, cil_post_nodecon_compare, cil_post_nodecon_context_compare, db, CIL_NODECON, CIL_KEY_NODECON);
332+ if (rc != SEPOL_OK) {
333+ cil_log(CIL_ERR, "Problems processing nodecon rules\n");
334+ goto exit;
335+ }
336+
337+ rc = __cil_post_process_context_rules(db->fsuse, cil_post_fsuse_compare, cil_post_fsuse_context_compare, db, CIL_FSUSE, CIL_KEY_FSUSE);
338+ if (rc != SEPOL_OK) {
339+ cil_log(CIL_ERR, "Problems processing fsuse rules\n");
340+ goto exit;
341+ }
342+
343+ rc = __cil_post_process_context_rules(db->filecon, cil_post_filecon_compare, cil_post_filecon_context_compare, db, CIL_FILECON, CIL_KEY_FILECON);
344+ if (rc != SEPOL_OK) {
345+ cil_log(CIL_ERR, "Problems processing filecon rules\n");
346+ goto exit;
347+ }
348+
349+ rc = __cil_post_process_context_rules(db->iomemcon, cil_post_iomemcon_compare, cil_post_iomemcon_context_compare, db, CIL_IOMEMCON, CIL_KEY_IOMEMCON);
350+ if (rc != SEPOL_OK) {
351+ cil_log(CIL_ERR, "Problems processing iomemcon rules\n");
352+ goto exit;
353+ }
354+
355+ rc = __cil_post_process_context_rules(db->ioportcon, cil_post_ioportcon_compare, cil_post_ioportcon_context_compare, db, CIL_IOPORTCON, CIL_KEY_IOPORTCON);
356+ if (rc != SEPOL_OK) {
357+ cil_log(CIL_ERR, "Problems processing ioportcon rules\n");
358+ goto exit;
359+ }
360+
361+ rc = __cil_post_process_context_rules(db->pcidevicecon, cil_post_pcidevicecon_compare, cil_post_pcidevicecon_context_compare, db, CIL_PCIDEVICECON, CIL_KEY_PCIDEVICECON);
362+ if (rc != SEPOL_OK) {
363+ cil_log(CIL_ERR, "Problems processing pcidevicecon rules\n");
364+ goto exit;
365+ }
366+
367+ rc = __cil_post_process_context_rules(db->devicetreecon, cil_post_devicetreecon_compare, cil_post_devicetreecon_context_compare, db, CIL_DEVICETREECON, CIL_KEY_DEVICETREECON);
368+ if (rc != SEPOL_OK) {
369+ cil_log(CIL_ERR, "Problems processing devicetreecon rules\n");
370+ goto exit;
371+ }
372
373 exit:
374 return rc;
375--
3762.7.4
377