Coverage Report

Created: 2026-05-30 06:31

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/selinux/libsepol/cil/src/cil_verify.c
Line
Count
Source
1
/*
2
 * Copyright 2011 Tresys Technology, LLC. All rights reserved.
3
 * 
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions are met:
6
 * 
7
 *    1. Redistributions of source code must retain the above copyright notice,
8
 *       this list of conditions and the following disclaimer.
9
 * 
10
 *    2. Redistributions in binary form must reproduce the above copyright notice,
11
 *       this list of conditions and the following disclaimer in the documentation
12
 *       and/or other materials provided with the distribution.
13
 * 
14
 * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS
15
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
16
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
17
 * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
18
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
19
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
21
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
22
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
23
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24
 * 
25
 * The views and conclusions contained in the software and documentation are those
26
 * of the authors and should not be interpreted as representing official policies,
27
 * either expressed or implied, of Tresys Technology, LLC.
28
 */
29
30
#include <stdlib.h>
31
#include <stdio.h>
32
#include <string.h>
33
#include <stdint.h>
34
#include <unistd.h>
35
#include <ctype.h>
36
37
#include <sepol/policydb/polcaps.h>
38
#include <sepol/errcodes.h>
39
40
#include "cil_internal.h"
41
#include "cil_flavor.h"
42
#include "cil_log.h"
43
#include "cil_mem.h"
44
#include "cil_tree.h"
45
#include "cil_list.h"
46
#include "cil_find.h"
47
#include "cil_stack.h"
48
49
#include "cil_verify.h"
50
51
static int __cil_is_reserved_name(const char *name, enum cil_flavor flavor)
52
0
{
53
0
  switch (flavor) {
54
0
  case CIL_BOOL:
55
0
  case CIL_TUNABLE:
56
0
    if ((name == CIL_KEY_EQ) || (name == CIL_KEY_NEQ))
57
0
      return CIL_TRUE;
58
0
    break;
59
0
  case CIL_PERM:
60
0
  case CIL_MAP_PERM:
61
0
  case CIL_USER:
62
0
  case CIL_USERATTRIBUTE:
63
0
  case CIL_ROLE:
64
0
  case CIL_ROLEATTRIBUTE:
65
0
    if (name == CIL_KEY_ALL)
66
0
      return CIL_TRUE;
67
0
    break;
68
0
  case CIL_TYPE:
69
0
  case CIL_TYPEATTRIBUTE:
70
0
  case CIL_TYPEALIAS:
71
0
    if ((name == CIL_KEY_ALL) || (name == CIL_KEY_SELF) || (name == CIL_KEY_NOTSELF)
72
0
      || (name == CIL_KEY_OTHER))
73
0
      return CIL_TRUE;
74
0
    break;
75
0
  case CIL_CAT:
76
0
  case CIL_CATSET:
77
0
  case CIL_CATALIAS:
78
0
  case CIL_PERMISSIONX:
79
0
    if ((name == CIL_KEY_ALL) || (name == CIL_KEY_RANGE))
80
0
      return CIL_TRUE;
81
0
    break;
82
0
  default:
83
    /* All of these are not used in expressions */
84
0
    return CIL_FALSE;
85
0
    break;
86
0
  }
87
88
  /* Everything not under the default case is also checked for these */
89
0
  if ((name == CIL_KEY_AND) || (name == CIL_KEY_OR) || (name == CIL_KEY_NOT) || (name == CIL_KEY_XOR)) {
90
0
    return CIL_TRUE;
91
0
  }
92
93
0
  return CIL_FALSE;
94
0
}
95
96
int cil_verify_name(const struct cil_db *db, const char *name, enum cil_flavor flavor)
97
0
{
98
0
  int rc = SEPOL_ERR;
99
0
  int len;
100
0
  int i = 0;
101
102
0
  if (name == NULL) {
103
0
    cil_log(CIL_ERR, "Name is NULL\n");
104
0
    goto exit;
105
0
  }
106
107
0
  len = strlen(name);
108
0
  if (len >= CIL_MAX_NAME_LENGTH) {
109
0
    cil_log(CIL_ERR, "Name length greater than max name length of %d", 
110
0
      CIL_MAX_NAME_LENGTH);
111
0
    rc = SEPOL_ERR;
112
0
    goto exit;
113
0
  }
114
115
0
  if (!isalpha(name[0])) {
116
0
      cil_log(CIL_ERR, "First character in %s is not a letter\n", name);
117
0
      goto exit;
118
0
  }
119
120
0
  if (db->qualified_names == CIL_FALSE) {
121
0
    for (i = 1; i < len; i++) {
122
0
      if (!isalnum(name[i]) && name[i] != '_' && name[i] != '-') {
123
0
        cil_log(CIL_ERR, "Invalid character \"%c\" in %s\n", name[i], name);
124
0
        goto exit;
125
0
      }
126
0
    }
127
0
  } else {
128
0
    for (i = 1; i < len; i++) {
129
0
      if (!isalnum(name[i]) && name[i] != '_' && name[i] != '-' && name[i] != '.') {
130
0
        cil_log(CIL_ERR, "Invalid character \"%c\" in %s\n", name[i], name);
131
0
        goto exit;
132
0
      }
133
0
    }
134
0
  }
135
136
0
  if (__cil_is_reserved_name(name, flavor)) {
137
0
    cil_log(CIL_ERR, "Name %s is a reserved word\n", name);
138
0
    goto exit;
139
0
  }
140
141
0
  return SEPOL_OK;
142
143
0
exit:
144
0
  cil_log(CIL_ERR, "Invalid name\n");
145
0
  return rc;
146
0
}
147
148
int __cil_verify_syntax(struct cil_tree_node *parse_current, enum cil_syntax s[], size_t len)
149
0
{
150
0
  struct cil_tree_node *c = parse_current;
151
0
  size_t i = 0;
152
153
0
  while (i < len && c != NULL) {
154
0
    if ((s[i] & CIL_SYN_STRING) && c->data != NULL && c->cl_head == NULL) {
155
0
      c = c->next;
156
0
      i++;
157
0
    } else if ((s[i] & CIL_SYN_LIST) && c->data == NULL && c->cl_head != NULL) {
158
0
      c = c->next;
159
0
      i++;
160
0
    } else if ((s[i] & CIL_SYN_EMPTY_LIST) && c->data == NULL && c->cl_head == NULL) {
161
0
      c = c->next;
162
0
      i++;
163
0
    } else if ((s[i] & CIL_SYN_N_LISTS) || (s[i] & CIL_SYN_N_STRINGS)) {
164
0
      while (c != NULL) {
165
0
        if ((s[i] & CIL_SYN_N_LISTS) && c->data == NULL && c->cl_head != NULL) {
166
0
          c = c->next;
167
0
        } else if ((s[i] & CIL_SYN_N_STRINGS) && c->data != NULL && c->cl_head == NULL) {
168
0
          c = c->next;
169
0
        } else {
170
0
          goto exit;
171
0
        }
172
0
      }
173
0
      i++;
174
0
      break; /* Only CIL_SYN_END allowed after these */
175
0
    } else {
176
0
      goto exit;
177
0
    }
178
0
  }
179
180
0
  if (i < len && (s[i] & CIL_SYN_END) && c == NULL) {
181
0
    return SEPOL_OK;
182
0
  }
183
184
0
exit:
185
0
  cil_log(CIL_ERR, "Invalid syntax\n");
186
0
  return SEPOL_ERR;
187
0
}
188
189
int cil_verify_expr_syntax(struct cil_tree_node *current, enum cil_flavor op, enum cil_flavor expr_flavor)
190
0
{
191
0
  int rc;
192
0
  enum cil_syntax syntax[] = {
193
0
    CIL_SYN_STRING,
194
0
    CIL_SYN_STRING | CIL_SYN_LIST,
195
0
    CIL_SYN_STRING | CIL_SYN_LIST,
196
0
    CIL_SYN_END
197
0
  };
198
0
  int syntax_len = sizeof(syntax)/sizeof(*syntax);
199
200
0
  switch (op) {
201
0
  case CIL_NOT:
202
0
    syntax[2] = CIL_SYN_END;
203
0
    syntax_len = 3;
204
0
    break;
205
0
  case CIL_AND:
206
0
  case CIL_OR:
207
0
  case CIL_XOR:
208
0
    break;
209
0
  case CIL_EQ:
210
0
  case CIL_NEQ:
211
0
    if (expr_flavor != CIL_BOOL && expr_flavor != CIL_TUNABLE ) {
212
0
      cil_log(CIL_ERR,"Invalid operator (%s) for set expression\n", (char*)current->data);
213
0
      goto exit;
214
0
    }
215
0
    break;
216
0
  case CIL_ALL:
217
0
    if (expr_flavor == CIL_BOOL || expr_flavor == CIL_TUNABLE) {
218
0
      cil_log(CIL_ERR,"Invalid operator (%s) for boolean or tunable expression\n", (char*)current->data);
219
0
      goto exit;
220
0
    }
221
0
    syntax[1] = CIL_SYN_END;
222
0
    syntax_len = 2;
223
0
    break;
224
0
  case CIL_RANGE:
225
0
    if (expr_flavor != CIL_CAT && expr_flavor != CIL_PERMISSIONX) {
226
0
      cil_log(CIL_ERR,"Operator (%s) only valid for catset and permissionx expression\n", (char*)current->data);
227
0
      goto exit;
228
0
    }
229
0
    syntax[1] = CIL_SYN_STRING;
230
0
    syntax[2] = CIL_SYN_STRING;
231
0
    break;
232
0
  case CIL_NONE: /* String or List */
233
0
    syntax[0] = CIL_SYN_N_STRINGS | CIL_SYN_N_LISTS;
234
0
    syntax[1] = CIL_SYN_END;
235
0
    syntax_len = 2;
236
0
    break;
237
0
  default:
238
0
    cil_log(CIL_ERR,"Unexpected value (%s) for expression operator\n", (char*)current->data);
239
0
    goto exit;
240
0
  }
241
242
0
  rc = __cil_verify_syntax(current, syntax, syntax_len);
243
0
  if (rc != SEPOL_OK) {
244
0
    goto exit;
245
0
  }
246
247
0
  return SEPOL_OK;
248
249
0
exit:
250
0
  return SEPOL_ERR;
251
0
}
252
253
int cil_verify_constraint_leaf_expr_syntax(enum cil_flavor l_flavor, enum cil_flavor r_flavor, enum cil_flavor op, enum cil_flavor expr_flavor)
254
0
{
255
0
  if (r_flavor == CIL_STRING || r_flavor == CIL_LIST) {
256
0
    if (l_flavor == CIL_CONS_L1 || l_flavor == CIL_CONS_L2 || l_flavor == CIL_CONS_H1 || l_flavor == CIL_CONS_H2 ) {
257
0
      cil_log(CIL_ERR, "l1, l2, h1, and h2 cannot be used on the left side with a string or list on the right side\n");
258
0
      goto exit;
259
0
    } else if (l_flavor == CIL_CONS_U3 || l_flavor == CIL_CONS_R3 || l_flavor == CIL_CONS_T3) {
260
0
      if (expr_flavor != CIL_VALIDATETRANS && expr_flavor != CIL_MLSVALIDATETRANS) {
261
0
        cil_log(CIL_ERR, "u3, r3, and t3 can only be used with (mls)validatetrans rules\n");
262
0
        goto exit;
263
0
      }
264
0
    }
265
0
  } else {
266
0
    if (r_flavor == CIL_CONS_U1 || r_flavor == CIL_CONS_R1 || r_flavor == CIL_CONS_T1) {
267
0
      cil_log(CIL_ERR, "u1, r1, and t1 are not allowed on the right side\n");
268
0
      goto exit;
269
0
    } else if (r_flavor == CIL_CONS_U3 || r_flavor == CIL_CONS_R3 || r_flavor == CIL_CONS_T3) {
270
0
      cil_log(CIL_ERR, "u3, r3, and t3 are not allowed on the right side\n");
271
0
      goto exit;
272
0
    } else if (r_flavor == CIL_CONS_U2) {
273
0
      if (op != CIL_EQ && op != CIL_NEQ) {
274
0
        cil_log(CIL_ERR, "u2 on the right side must be used with eq or neq as the operator\n");
275
0
        goto exit;
276
0
      } else if (l_flavor != CIL_CONS_U1) {
277
0
        cil_log(CIL_ERR, "u2 on the right side must be used with u1 on the left\n");
278
0
        goto exit;
279
0
      }
280
0
    } else if (r_flavor == CIL_CONS_R2) {
281
0
      if (l_flavor != CIL_CONS_R1) {
282
0
        cil_log(CIL_ERR, "r2 on the right side must be used with r1 on the left\n");
283
0
        goto exit;
284
0
      }
285
0
    } else if (r_flavor == CIL_CONS_T2) {
286
0
      if (op != CIL_EQ && op != CIL_NEQ) {
287
0
        cil_log(CIL_ERR, "t2 on the right side must be used with eq or neq as the operator\n");
288
0
        goto exit;
289
0
      } else if (l_flavor != CIL_CONS_T1) {
290
0
        cil_log(CIL_ERR, "t2 on the right side must be used with t1 on the left\n");
291
0
        goto exit;
292
0
      }
293
0
    } else if (r_flavor == CIL_CONS_L2) {
294
0
      if (l_flavor != CIL_CONS_L1 && l_flavor != CIL_CONS_H1) {
295
0
        cil_log(CIL_ERR, "l2 on the right side must be used with l1 or h1 on the left\n");
296
0
        goto exit;
297
0
      }
298
0
    } else if (r_flavor == CIL_CONS_H2) {
299
0
      if (l_flavor != CIL_CONS_L1 && l_flavor != CIL_CONS_L2 && l_flavor != CIL_CONS_H1 ) {
300
0
        cil_log(CIL_ERR, "h2 on the right side must be used with l1, l2, or h1 on the left\n");
301
0
        goto exit;
302
0
      }
303
0
    } else if (r_flavor == CIL_CONS_H1) {
304
0
      if (l_flavor != CIL_CONS_L1) {
305
0
        cil_log(CIL_ERR, "h1 on the right side must be used with l1 on the left\n");
306
0
        goto exit;
307
0
      }
308
0
    }
309
0
  }
310
311
0
  return SEPOL_OK;
312
313
0
exit:
314
0
  return SEPOL_ERR;
315
0
}
316
317
int cil_verify_constraint_expr_syntax(struct cil_tree_node *current, enum cil_flavor op)
318
0
{
319
0
  int rc;
320
0
  enum cil_syntax syntax[] = {
321
0
    CIL_SYN_STRING,
322
0
    CIL_SYN_END,
323
0
    CIL_SYN_END,
324
0
    CIL_SYN_END
325
0
  };
326
0
  int syntax_len = sizeof(syntax)/sizeof(*syntax);
327
328
0
  switch (op) {
329
0
  case CIL_NOT:
330
0
    syntax[1] = CIL_SYN_LIST;
331
0
    syntax_len--;
332
0
    break;
333
0
  case CIL_AND:
334
0
  case CIL_OR:
335
0
    syntax[1] = CIL_SYN_LIST;
336
0
    syntax[2] = CIL_SYN_LIST;
337
0
    break;
338
0
  case CIL_EQ:
339
0
  case CIL_NEQ:
340
0
    syntax[1] = CIL_SYN_STRING;
341
0
    syntax[2] = CIL_SYN_STRING | CIL_SYN_LIST;
342
0
    break;
343
0
  case CIL_CONS_DOM:
344
0
  case CIL_CONS_DOMBY:
345
0
  case CIL_CONS_INCOMP:
346
0
    syntax[1] = CIL_SYN_STRING;
347
0
    syntax[2] = CIL_SYN_STRING;
348
0
    break;
349
0
  default:
350
0
    cil_log(CIL_ERR, "Invalid operator (%s) for constraint expression\n", (char*)current->data);
351
0
    goto exit;
352
0
  }
353
354
0
  rc = __cil_verify_syntax(current, syntax, syntax_len);
355
0
  if (rc != SEPOL_OK) {
356
0
    cil_log(CIL_ERR, "Invalid constraint syntax\n");
357
0
    goto exit;
358
0
  }
359
360
0
  return SEPOL_OK;
361
362
0
exit:
363
0
  return SEPOL_ERR;
364
0
}
365
366
int cil_verify_conditional_blocks(struct cil_tree_node *current)
367
0
{
368
0
  int found_true = CIL_FALSE;
369
0
  int found_false = CIL_FALSE;
370
371
0
  if (current->cl_head->data == CIL_KEY_CONDTRUE) {
372
0
    found_true = CIL_TRUE;
373
0
  } else if (current->cl_head->data == CIL_KEY_CONDFALSE) {
374
0
    found_false = CIL_TRUE;
375
0
  } else {
376
0
    cil_tree_log(current, CIL_ERR, "Expected true or false block in conditional");
377
0
    return SEPOL_ERR;
378
0
  }
379
380
0
  current = current->next;
381
0
  if (current != NULL) {
382
0
    if (current->cl_head->data == CIL_KEY_CONDTRUE) {
383
0
      if (found_true) {
384
0
        cil_tree_log(current, CIL_ERR, "More than one true block in conditional");
385
0
        return SEPOL_ERR;
386
0
      }
387
0
    } else if (current->cl_head->data == CIL_KEY_CONDFALSE) {
388
0
      if (found_false) {
389
0
        cil_tree_log(current, CIL_ERR, "More than one false block in conditional");
390
0
        return SEPOL_ERR;
391
0
      }
392
0
    } else {
393
0
      cil_tree_log(current, CIL_ERR, "Expected true or false block in conditional");
394
0
      return SEPOL_ERR;
395
0
    }
396
0
  }
397
398
0
  return SEPOL_OK;
399
0
}
400
401
int cil_verify_decl_does_not_shadow_macro_parameter(struct cil_macro *macro, struct cil_tree_node *node, const char *name)
402
0
{
403
0
  struct cil_list_item *item;
404
0
  struct cil_list *param_list = macro->params;
405
0
  if (param_list != NULL) {
406
0
    cil_list_for_each(item, param_list) {
407
0
      struct cil_param *param = item->data;
408
0
      if (param->str == name) {
409
0
        if (param->flavor == node->flavor) {
410
0
          cil_log(CIL_ERR, "Declaration of %s %s shadows a macro parameter with the same flavor\n", cil_node_to_string(node), name);
411
0
          return SEPOL_ERR;
412
0
        } else {
413
0
          cil_log(CIL_WARN, "Declaration of %s %s has same name as a macro parameter with a different flavor\n", cil_node_to_string(node), name);
414
0
        }
415
0
      }
416
0
    }
417
0
  }
418
0
  return SEPOL_OK;
419
0
}
420
421
static int cil_verify_no_self_reference(enum cil_flavor flavor, struct cil_symtab_datum *datum, struct cil_stack *stack);
422
423
static int __verify_no_self_reference_in_expr(struct cil_list *expr, struct cil_stack *stack)
424
0
{
425
0
  struct cil_list_item *item;
426
0
  int rc = SEPOL_OK;
427
428
0
  if (!expr) {
429
0
    return SEPOL_OK;
430
0
  }
431
432
0
  cil_list_for_each(item, expr) {
433
0
    if (item->flavor == CIL_DATUM) {
434
0
      struct cil_symtab_datum* datum = item->data;
435
0
      rc = cil_verify_no_self_reference(FLAVOR(datum), datum, stack);
436
0
    } else if (item->flavor == CIL_LIST) {
437
0
      rc = __verify_no_self_reference_in_expr(item->data, stack);
438
0
    }
439
0
    if (rc != SEPOL_OK) {
440
0
      return SEPOL_ERR;
441
0
    }
442
0
  }
443
444
0
  return SEPOL_OK;
445
0
}
446
447
static int cil_verify_no_self_reference(enum cil_flavor flavor, struct cil_symtab_datum *datum, struct cil_stack *stack)
448
0
{
449
0
  struct cil_stack_item *item;
450
0
  int i = 0;
451
0
  int rc = SEPOL_OK;
452
453
0
  cil_stack_for_each(stack, i, item) {
454
0
    struct cil_symtab_datum *prev = item->data;
455
0
    if (datum == prev) {
456
0
      cil_tree_log(NODE(datum), CIL_ERR, "Self-reference found for %s", datum->name);
457
0
      return SEPOL_ERR;
458
0
    }
459
0
  }
460
461
0
  switch (flavor) {
462
0
  case CIL_USERATTRIBUTE: {
463
0
    struct cil_userattribute *attr = (struct cil_userattribute *)datum;
464
0
    cil_stack_push(stack, CIL_DATUM, datum);
465
0
    rc = __verify_no_self_reference_in_expr(attr->expr_list, stack);
466
0
    cil_stack_pop(stack);
467
0
    break;
468
0
  }
469
0
  case CIL_ROLEATTRIBUTE: {
470
0
    struct cil_roleattribute *attr = (struct cil_roleattribute *)datum;
471
0
    cil_stack_push(stack, CIL_DATUM, datum);
472
0
    rc = __verify_no_self_reference_in_expr(attr->expr_list, stack);
473
0
    cil_stack_pop(stack);
474
0
    break;
475
0
  }
476
0
  case CIL_TYPEATTRIBUTE: {
477
0
    struct cil_typeattribute *attr = (struct cil_typeattribute *)datum;
478
0
    cil_stack_push(stack, CIL_DATUM, datum);
479
0
    rc = __verify_no_self_reference_in_expr(attr->expr_list, stack);
480
0
    cil_stack_pop(stack);
481
0
    break;
482
0
  }
483
0
  case CIL_CATSET: {
484
0
    struct cil_catset *set = (struct cil_catset *)datum;
485
0
    cil_stack_push(stack, CIL_DATUM, datum);
486
0
    rc = __verify_no_self_reference_in_expr(set->cats->datum_expr, stack);
487
0
    cil_stack_pop(stack);
488
0
    break;
489
0
  }
490
0
  default:
491
0
    break;
492
0
  }
493
494
0
  return rc;
495
0
}
496
497
int __cil_verify_ranges(struct cil_list *list)
498
0
{
499
0
  int rc = SEPOL_ERR;
500
0
  struct cil_list_item *curr;
501
0
  struct cil_list_item *range = NULL;
502
503
0
  if (list == NULL || list->head == NULL) {
504
0
    goto exit;
505
0
  }
506
507
0
  cil_list_for_each(curr, list) {
508
    /* range */
509
0
    if (curr->flavor == CIL_LIST) {
510
0
      range = ((struct cil_list*)curr->data)->head;
511
0
      if (range == NULL || range->next == NULL || range->next->next != NULL) {
512
0
        goto exit;
513
0
      }
514
0
    }
515
0
  }
516
517
0
  return SEPOL_OK;
518
519
0
exit:
520
0
  cil_log(CIL_ERR,"Invalid Range syntax\n");
521
0
  return rc;
522
0
}
523
524
int cil_verify_completed_ordered_list(struct cil_list *complete, struct cil_list *ordered_lists)
525
0
{
526
0
  struct cil_list_item *cprev, *ccurr, *cnext;
527
0
  int found_prev, found_next;
528
0
  int rc = SEPOL_OK;
529
530
0
  found_prev = CIL_FALSE;
531
0
  found_next = CIL_FALSE;
532
0
  cprev = NULL;
533
0
  ccurr = complete->head;
534
0
  cnext = ccurr ? ccurr->next : NULL;
535
0
  while (ccurr) {
536
0
    struct cil_tree_node *node;
537
0
    struct cil_ordered *ordered;
538
0
    struct cil_list_item *curr_list, *oprev, *ocurr, *onext;
539
0
    int change = CIL_FALSE;
540
0
    cil_list_for_each(curr_list, ordered_lists) {
541
0
      node = curr_list->data;
542
0
      ordered = node->data;
543
0
      oprev = NULL;
544
0
      cil_list_for_each(ocurr, ordered->datums) {
545
0
        onext = ocurr ? ocurr->next : NULL;
546
0
        if (ccurr->data == ocurr->data) {
547
0
          if (found_prev == CIL_FALSE && ((!cprev && !oprev) ||
548
0
            (cprev && oprev && cprev->data == oprev->data))) {
549
0
            found_prev = CIL_TRUE;
550
0
            change = CIL_TRUE;
551
0
          }
552
0
          if (found_next == CIL_FALSE && ((!cnext && !onext) ||
553
0
            (cnext && onext && cnext->data == onext->data))) {
554
0
            found_next = CIL_TRUE;
555
0
            change = CIL_TRUE;
556
0
          }
557
0
          if (found_prev && found_next) {
558
0
            cprev = ccurr;
559
0
            ccurr = cnext;
560
0
            cnext = ccurr ? ccurr->next : NULL;
561
0
            found_prev = CIL_FALSE;
562
0
            found_next = CIL_FALSE;
563
0
            if (!ccurr) {
564
              /* Went through the whole list */
565
0
              return rc;
566
0
            }
567
0
          }
568
0
        }
569
0
        oprev = ocurr;
570
0
      }
571
0
    }
572
0
    if (!change) {
573
0
      rc = SEPOL_ERR;
574
0
      cil_log(CIL_ERR, "Unable to verify the order of %s\n", DATUM(ccurr->data)->fqn);
575
0
      cil_log(CIL_ERR, "Found in the following ordering rules:\n");
576
0
      cil_list_for_each(curr_list, ordered_lists) {
577
0
        node = curr_list->data;
578
0
        ordered = node->data;
579
0
        cil_list_for_each(ocurr, ordered->datums) {
580
0
          if (ccurr->data == ocurr->data) {
581
0
            cil_tree_log(node, CIL_ERR, "    ");
582
0
          }
583
0
        }
584
0
      }
585
0
      cprev = ccurr;
586
0
      ccurr = cnext;
587
0
      cnext = ccurr ? ccurr->next : NULL;
588
0
      found_prev = CIL_FALSE;
589
0
      found_next = CIL_FALSE;
590
0
    }
591
0
  }
592
593
0
  return rc;
594
0
}
595
596
struct cil_args_verify_order {
597
  uint32_t *flavor;
598
};
599
600
int __cil_verify_ordered_node_helper(struct cil_tree_node *node, __attribute__((unused)) uint32_t *finished, void *extra_args)
601
0
{
602
0
  struct cil_args_verify_order *args = extra_args;
603
0
  uint32_t *flavor = args->flavor;
604
605
0
  if (node->flavor == *flavor) {
606
0
    if (node->flavor == CIL_SID) {
607
0
      struct cil_sid *sid = node->data;
608
0
      if (sid->ordered == CIL_FALSE) {
609
0
        cil_tree_log(node, CIL_ERR, "SID %s not in sidorder statement", sid->datum.name);
610
0
        return SEPOL_ERR;
611
0
      }
612
0
    } else if (node->flavor == CIL_CLASS) {
613
0
      struct cil_class *class = node->data;
614
0
      if (class->ordered == CIL_FALSE) {
615
0
        cil_tree_log(node, CIL_ERR, "Class %s not in classorder statement", class->datum.name);
616
0
        return SEPOL_ERR;
617
0
      }
618
0
    } else if (node->flavor == CIL_CAT) {
619
0
      struct cil_cat *cat = node->data;
620
0
      if (cat->ordered == CIL_FALSE) {
621
0
        cil_tree_log(node, CIL_ERR, "Category %s not in categoryorder statement", cat->datum.name);
622
0
        return SEPOL_ERR;
623
0
      }
624
0
    } else if (node->flavor == CIL_SENS) {
625
0
      struct cil_sens *sens = node->data;
626
0
      if (sens->ordered == CIL_FALSE) {
627
0
        cil_tree_log(node, CIL_ERR, "Sensitivity %s not in sensitivityorder statement", sens->datum.name);
628
0
        return SEPOL_ERR;
629
0
      }
630
0
    }
631
0
  }
632
633
0
  return SEPOL_OK;
634
0
}
635
636
int __cil_verify_ordered(struct cil_tree_node *current, enum cil_flavor flavor)
637
0
{
638
0
  struct cil_args_verify_order extra_args;
639
0
  int rc = SEPOL_ERR;
640
641
0
  extra_args.flavor = &flavor;
642
643
0
  rc = cil_tree_walk(current, __cil_verify_ordered_node_helper, NULL, NULL, &extra_args);
644
645
0
  return rc;
646
0
}
647
648
int __cil_verify_initsids(struct cil_list *sids)
649
0
{
650
0
  int rc = SEPOL_OK;
651
0
  struct cil_list_item *i;
652
653
0
  if (sids->head == NULL) {
654
0
    cil_log(CIL_ERR, "At least one initial sid must be defined in the policy\n");
655
0
    return SEPOL_ERR;
656
0
  }
657
658
0
  cil_list_for_each(i, sids) {
659
0
    struct cil_sid *sid = i->data;
660
0
    if (sid->context == NULL) {
661
0
      struct cil_tree_node *node = sid->datum.nodes->head->data;
662
0
      cil_tree_log(node, CIL_INFO, "No context assigned to SID %s, omitting from policy",sid->datum.name);
663
0
    }
664
0
  }
665
666
0
  return rc;
667
0
}
668
669
static int __cil_is_cat_in_cats(struct cil_cat *cat, struct cil_cats *cats)
670
0
{
671
0
  struct cil_list_item *i;
672
673
0
  cil_list_for_each(i, cats->datum_expr) {
674
0
    struct cil_cat *c = i->data;
675
0
    if (c == cat) {
676
0
      return CIL_TRUE;
677
0
    }
678
0
  }
679
680
0
  return CIL_FALSE;
681
0
}
682
683
684
static int __cil_verify_cat_in_cats(struct cil_cat *cat, struct cil_cats *cats)
685
0
{
686
0
  if (__cil_is_cat_in_cats(cat, cats) != CIL_TRUE) {
687
0
    cil_log(CIL_ERR, "Failed to find category %s in category list\n", cat->datum.name);
688
0
    return SEPOL_ERR;
689
0
  }
690
691
0
  return SEPOL_OK;
692
0
}
693
694
static int __cil_verify_cats_associated_with_sens(struct cil_sens *sens, struct cil_cats *cats)
695
0
{
696
0
  int rc = SEPOL_OK;
697
0
  struct cil_list_item *i, *j;
698
699
0
  if (!cats) {
700
0
    return SEPOL_OK;
701
0
  }
702
703
0
  if (!sens->cats_list) {
704
0
    cil_log(CIL_ERR, "No categories can be used with sensitivity %s\n", sens->datum.name);
705
0
    return SEPOL_ERR;
706
0
  }
707
708
0
  cil_list_for_each(i, cats->datum_expr) {
709
0
    struct cil_cat *cat = i->data;
710
0
    int ok = CIL_FALSE;
711
0
    cil_list_for_each(j, sens->cats_list) {
712
0
      if (__cil_is_cat_in_cats(cat, j->data) == CIL_TRUE) {
713
0
        ok = CIL_TRUE;
714
0
        break;
715
0
      }
716
0
    }
717
718
0
    if (ok != CIL_TRUE) {
719
0
      cil_log(CIL_ERR, "Category %s cannot be used with sensitivity %s\n", 
720
0
          cat->datum.name, sens->datum.name);
721
0
      rc = SEPOL_ERR;
722
0
    }
723
0
  }
724
725
0
  return rc;
726
0
}
727
728
static int __cil_verify_levelrange_sensitivity(struct cil_db *db, struct cil_sens *low, struct cil_sens *high)
729
0
{
730
0
  struct cil_list_item *curr;
731
0
  int found = CIL_FALSE;
732
0
  int rc = SEPOL_ERR;
733
734
0
  cil_list_for_each(curr, db->sensitivityorder) {
735
0
    if (curr->data == low) {
736
0
      found = CIL_TRUE;
737
0
    }
738
739
0
    if ((found == CIL_TRUE) && (curr->data == high)) {
740
0
      break;
741
0
    }
742
0
  }
743
744
0
  if (found != CIL_TRUE || curr == NULL) {
745
0
    goto exit;
746
0
  }
747
748
0
  return SEPOL_OK;
749
750
0
exit:
751
0
  cil_log(CIL_ERR, "Sensitivity %s does not dominate %s\n", 
752
0
    high->datum.name, low->datum.name);
753
0
  return rc;
754
755
0
}
756
757
static int __cil_verify_levelrange_cats(struct cil_cats *low, struct cil_cats *high)
758
0
{
759
0
  int rc = SEPOL_ERR;
760
0
  struct cil_list_item *item;
761
762
0
  if (low == NULL || (low == NULL && high == NULL)) {
763
0
    return SEPOL_OK;
764
0
  }
765
766
0
  if (high == NULL) {
767
0
    rc = SEPOL_ERR;
768
0
    goto exit;
769
0
  }
770
771
0
  cil_list_for_each(item, low->datum_expr) {
772
0
    rc = __cil_verify_cat_in_cats(item->data, high);
773
0
    if (rc != SEPOL_OK) {
774
0
      goto exit;
775
0
    }
776
0
  }
777
778
0
  return SEPOL_OK;
779
780
0
exit:
781
0
  cil_log(CIL_ERR, "Low level category set must be a subset of the high level category set\n");
782
0
  return rc;
783
0
}
784
785
static int __cil_verify_levelrange(struct cil_db *db, struct cil_levelrange *lr)
786
0
{
787
0
  int rc = SEPOL_ERR;
788
789
0
  rc = __cil_verify_levelrange_sensitivity(db, lr->low->sens, lr->high->sens);
790
0
  if (rc != SEPOL_OK) {
791
0
    goto exit;
792
0
  }
793
794
0
  rc = __cil_verify_levelrange_cats(lr->low->cats, lr->high->cats);
795
0
  if (rc != SEPOL_OK) {
796
0
    goto exit;
797
0
  }
798
799
0
  rc = __cil_verify_cats_associated_with_sens(lr->low->sens, lr->low->cats);
800
0
  if (rc != SEPOL_OK) {
801
0
    cil_log(CIL_ERR, "Low level sensitivity and categories are not associated\n");
802
0
    goto exit;
803
0
  }
804
805
0
  rc = __cil_verify_cats_associated_with_sens(lr->high->sens, lr->high->cats);
806
0
  if (rc != SEPOL_OK) {
807
0
    cil_log(CIL_ERR, "High level sensitivity and categories are not associated\n");
808
0
    goto exit;
809
0
  }
810
  
811
0
  return SEPOL_OK;
812
813
0
exit:
814
0
  return rc;
815
0
}
816
817
static int __cil_verify_named_levelrange(struct cil_db *db, struct cil_tree_node *node)
818
0
{
819
0
  int rc = SEPOL_ERR;
820
0
  struct cil_levelrange *lr = node->data;
821
822
0
  rc = __cil_verify_levelrange(db, lr);
823
0
  if (rc != SEPOL_OK) {
824
0
    goto exit;
825
0
  }
826
827
0
  return SEPOL_OK;
828
0
exit:
829
0
  cil_tree_log(node, CIL_ERR, "Invalid named range");
830
0
  return rc;
831
0
}
832
833
static int __cil_verify_user_pre_eval(struct cil_tree_node *node)
834
0
{
835
0
  int rc = SEPOL_ERR;
836
0
  struct cil_user *user = node->data;
837
838
0
  if (user->dftlevel == NULL) {
839
0
    cil_log(CIL_ERR, "User %s does not have a default level\n", user->datum.name);
840
0
    goto exit;
841
0
  } else if (user->range == NULL) {
842
0
    cil_log(CIL_ERR, "User %s does not have a level range\n", user->datum.name);
843
0
    goto exit;
844
0
  } else if (user->bounds != NULL) {
845
0
    int steps = 0;
846
0
    int limit = 2;
847
0
    struct cil_user *u1 = user;
848
0
    struct cil_user *u2 = user->bounds;
849
850
0
    while (u2 != NULL) {
851
0
      if (u1 == u2) {
852
0
        cil_log(CIL_ERR, "Circular bounds found for user %s\n", u1->datum.name);
853
0
        goto exit;
854
0
      }
855
856
0
      if (steps == limit) {
857
0
        steps = 0;
858
0
        limit *= 2;
859
0
        u1 = u2;
860
0
      }
861
862
0
      u2 = u2->bounds;
863
0
      steps++;
864
0
    }
865
0
  }
866
867
0
  return SEPOL_OK;
868
0
exit:
869
0
  cil_tree_log(node, CIL_ERR, "Invalid user");
870
0
  return rc;
871
0
}
872
873
static int __cil_verify_user_post_eval(struct cil_db *db, struct cil_tree_node *node)
874
0
{
875
0
  int rc = SEPOL_ERR;
876
0
  struct cil_user *user = node->data;
877
878
  /* Verify user range only if anonymous */
879
0
  if (user->range->datum.name == NULL) {
880
0
    rc = __cil_verify_levelrange(db, user->range);
881
0
    if (rc != SEPOL_OK) {
882
0
      goto exit;
883
0
    }
884
0
  }
885
886
0
  return SEPOL_OK;
887
0
exit:
888
0
  cil_tree_log(node, CIL_ERR, "Invalid user");
889
0
  return rc;
890
0
}
891
892
static int __cil_verify_role(struct cil_tree_node *node)
893
0
{
894
0
  int rc = SEPOL_ERR;
895
0
  struct cil_role *role = node->data;
896
0
  int steps = 0;
897
0
  int limit = 2;
898
0
  struct cil_role *r1 = role;
899
0
  struct cil_role *r2 = role->bounds;
900
901
0
  while (r2 != NULL) {
902
0
    if (r1 == r2) {
903
0
      cil_log(CIL_ERR, "Circular bounds found for role %s\n", r1->datum.name);
904
0
      goto exit;
905
0
    }
906
907
0
    if (steps == limit) {
908
0
      steps = 0;
909
0
      limit *= 2;
910
0
      r1 = r2;
911
0
    }
912
913
0
    r2 = r2->bounds;
914
0
    steps++;
915
0
  }
916
917
0
  return SEPOL_OK;
918
0
exit:
919
0
  cil_tree_log(node, CIL_ERR, "Invalid role");
920
0
  return rc;
921
0
}
922
923
static int __cil_verify_type(struct cil_tree_node *node)
924
0
{
925
0
  int rc = SEPOL_ERR;
926
0
  struct cil_type *type = node->data;
927
0
  int steps = 0;
928
0
  int limit = 2;
929
0
  struct cil_type *t1 = type;
930
0
  struct cil_type *t2 = type->bounds;
931
932
0
  while (t2 != NULL) {
933
0
    if (t1 == t2) {
934
0
      cil_log(CIL_ERR, "Circular bounds found for type %s\n", t1->datum.name);
935
0
      goto exit;
936
0
    }
937
938
0
    if (steps == limit) {
939
0
      steps = 0;
940
0
      limit *= 2;
941
0
      t1 = t2;
942
0
    }
943
944
0
    t2 = t2->bounds;
945
0
    steps++;
946
0
  }
947
948
0
  return SEPOL_OK;
949
0
exit:
950
0
  cil_tree_log(node, CIL_ERR, "Invalid type");
951
0
  return rc;
952
0
}
953
954
static int __cil_verify_context(struct cil_db *db, struct cil_context *ctx)
955
0
{
956
0
  int rc = SEPOL_ERR;
957
0
  struct cil_user *user = ctx->user;
958
0
  struct cil_role *role = ctx->role;
959
0
  struct cil_type *type = ctx->type;
960
0
  struct cil_level *user_low = user->range->low;
961
0
  struct cil_level *user_high = user->range->high;
962
0
  struct cil_level *ctx_low = ctx->range->low;
963
0
  struct cil_level *ctx_high = ctx->range->high;
964
0
  struct cil_list *sensitivityorder = db->sensitivityorder;
965
0
  struct cil_list_item *curr;
966
0
  int found = CIL_FALSE;
967
968
0
  if (user->roles != NULL) {
969
0
    if (!ebitmap_get_bit(user->roles, role->value)) {
970
0
      cil_log(CIL_ERR, "Role %s is invalid for user %s\n", ctx->role_str, ctx->user_str);
971
0
      rc = SEPOL_ERR;
972
0
      goto exit;
973
0
    }
974
0
  } else {
975
0
    cil_log(CIL_ERR, "No roles given to the user %s\n", ctx->user_str);
976
0
    rc = SEPOL_ERR;
977
0
    goto exit;
978
0
  }
979
980
0
  if (role->types != NULL) {
981
0
    if (!ebitmap_get_bit(role->types, type->value)) {
982
0
      cil_log(CIL_ERR, "Type %s is invalid for role %s\n", ctx->type_str, ctx->role_str);
983
0
      rc = SEPOL_ERR;
984
0
      goto exit;
985
0
    }
986
0
  } else {
987
0
    cil_log(CIL_ERR, "No types associated with role %s\n", ctx->role_str);
988
0
    rc = SEPOL_ERR;
989
0
    goto exit;
990
0
  }
991
992
  /* Verify range only when anonymous */
993
0
  if (ctx->range->datum.name == NULL) {
994
0
    rc = __cil_verify_levelrange(db, ctx->range);
995
0
    if (rc != SEPOL_OK) {
996
0
      goto exit;
997
0
    }
998
0
  }
999
1000
0
  for (curr = sensitivityorder->head; curr != NULL; curr = curr->next) {
1001
0
    struct cil_sens *sens = curr->data;
1002
1003
0
    if (found == CIL_FALSE) {
1004
0
      if (sens == user_low->sens) {
1005
0
        found = CIL_TRUE;
1006
0
      } else if (sens == ctx_low->sens) {
1007
0
        cil_log(CIL_ERR, "Range %s is invalid for user %s\n", 
1008
0
          ctx->range_str, ctx->user_str);
1009
0
        rc = SEPOL_ERR;
1010
0
        goto exit;
1011
0
      }
1012
0
    }
1013
1014
0
    if (found == CIL_TRUE) {
1015
0
      if (sens == ctx_high->sens) {
1016
0
        break;
1017
0
      } else if (sens == user_high->sens) {
1018
0
        cil_log(CIL_ERR, "Range %s is invalid for user %s\n", 
1019
0
          ctx->range_str, ctx->user_str);
1020
0
        rc = SEPOL_ERR;
1021
0
        goto exit;
1022
0
      }
1023
0
    }
1024
0
  }
1025
1026
0
  return SEPOL_OK;
1027
0
exit:
1028
0
  cil_log(CIL_ERR, "Invalid context\n");
1029
0
  return rc;
1030
0
}
1031
1032
static int __cil_verify_named_context(struct cil_db *db, struct cil_tree_node *node)
1033
0
{
1034
0
  int rc = SEPOL_ERR;
1035
0
  struct cil_context *ctx = node->data;
1036
1037
0
  rc = __cil_verify_context(db, ctx);
1038
0
  if (rc != SEPOL_OK) {
1039
0
    goto exit;
1040
0
  }
1041
1042
0
  return SEPOL_OK;
1043
0
exit:
1044
0
  cil_tree_log(node, CIL_ERR, "Invalid named context");
1045
0
  return rc;
1046
0
}
1047
1048
/*
1049
static int __cil_verify_rule(struct cil_tree_node *node, struct cil_complex_symtab *symtab)
1050
{
1051
1052
  int rc = SEPOL_ERR;
1053
  struct cil_type_rule *typerule = NULL;
1054
  struct cil_roletransition *roletrans = NULL;
1055
  struct cil_complex_symtab_key ckey;
1056
1057
  switch (node->flavor) {
1058
  case CIL_ROLETRANSITION: {
1059
    roletrans = node->data;
1060
    ckey.key1 = (intptr_t)roletrans->src;
1061
    ckey.key2 = (intptr_t)roletrans->tgt;
1062
    ckey.key3 = (intptr_t)roletrans->obj;
1063
    ckey.key4 = CIL_ROLETRANSITION;
1064
    break;
1065
  }
1066
  case CIL_TYPE_RULE: {
1067
    typerule = node->data;
1068
    ckey.key1 = (intptr_t)typerule->src;
1069
    ckey.key2 = (intptr_t)typerule->tgt;
1070
    ckey.key3 = (intptr_t)typerule->obj;
1071
    ckey.key4 = (intptr_t)typerule->rule_kind;
1072
    break;
1073
  }
1074
  default:
1075
    break;
1076
  }
1077
1078
1079
  rc = cil_complex_symtab_insert(symtab, &ckey, NULL);
1080
  if (rc == SEPOL_EEXIST) {
1081
    struct cil_complex_symtab_datum *datum = NULL;
1082
    cil_complex_symtab_search(symtab, &ckey, &datum);
1083
    if (datum == NULL) {
1084
      cil_tree_log(node, CIL_ERR, "Duplicate rule defined");
1085
      rc = SEPOL_ERR;
1086
      goto exit;
1087
    }
1088
  }
1089
1090
  return SEPOL_OK;
1091
exit:
1092
  cil_tree_log(node, CIL_ERR, "Invalid rule");
1093
  return rc;
1094
}
1095
*/
1096
1097
static int __cil_verify_booleanif_helper(struct cil_tree_node *node, __attribute__((unused)) uint32_t *finished, __attribute__((unused)) void *extra_args)
1098
0
{
1099
0
  int rc = SEPOL_ERR;
1100
0
  struct cil_tree_node *rule_node = node;
1101
0
  struct cil_booleanif *bif = node->parent->parent->data;
1102
1103
0
  switch (rule_node->flavor) {
1104
0
  case CIL_AVRULE:
1105
0
  case CIL_AVRULEX: {
1106
0
    struct cil_avrule *avrule = NULL;
1107
0
    avrule = rule_node->data;
1108
0
    if (avrule->rule_kind == CIL_AVRULE_NEVERALLOW) {
1109
0
      if (bif->preserved_tunable) {
1110
0
        cil_tree_log(node, CIL_ERR, "Neverallow found in tunableif block (treated as a booleanif due to preserve-tunables)");
1111
0
      } else {
1112
0
        cil_tree_log(node, CIL_ERR, "Neverallow found in booleanif block");
1113
0
      }
1114
0
      rc = SEPOL_ERR;
1115
0
      goto exit;
1116
0
    }
1117
0
    break;
1118
0
  }
1119
0
  case CIL_DENY_RULE:
1120
0
    if (bif->preserved_tunable) {
1121
0
      cil_tree_log(node, CIL_ERR, "Not allowed to have a deny rule in a tunableif block (treated as a booleanif due to preserve-tunables)");
1122
0
    } else {
1123
0
      cil_tree_log(node, CIL_ERR, "Not allowed to have deny rule in a booleanif block");
1124
0
    }
1125
0
    rc = SEPOL_ERR;
1126
0
    goto exit;
1127
0
    break;
1128
0
  case CIL_TYPE_RULE: /*
1129
  struct cil_type_rule *typerule = NULL;
1130
  struct cil_tree_node *temp_node = NULL;
1131
  struct cil_complex_symtab *symtab = extra_args;
1132
  struct cil_complex_symtab_key ckey;
1133
  struct cil_complex_symtab_datum datum;
1134
    typerule = rule_node->data;
1135
1136
    ckey.key1 = (intptr_t)typerule->src;
1137
    ckey.key2 = (intptr_t)typerule->tgt;
1138
    ckey.key3 = (intptr_t)typerule->obj;
1139
    ckey.key4 = (intptr_t)typerule->rule_kind;
1140
1141
    datum.data = node;
1142
1143
    rc = cil_complex_symtab_insert(symtab, &ckey, &datum);
1144
    if (rc != SEPOL_OK) {
1145
      goto exit;
1146
    }
1147
1148
    for (temp_node = rule_node->next;
1149
      temp_node != NULL;
1150
      temp_node = temp_node->next) {
1151
1152
      if (temp_node->flavor == CIL_TYPE_RULE) {
1153
        typerule = temp_node->data;
1154
        if ((intptr_t)typerule->src == ckey.key1 &&
1155
          (intptr_t)typerule->tgt == ckey.key2 &&
1156
          (intptr_t)typerule->obj == ckey.key3 &&
1157
          (intptr_t)typerule->rule_kind == ckey.key4) {
1158
          cil_log(CIL_ERR, "Duplicate type rule found (line: %d)\n", node->line);
1159
          rc = SEPOL_ERR;
1160
          goto exit;
1161
        }
1162
      }
1163
    }
1164
    break;*/
1165
1166
    //TODO Fix duplicate type_rule detection
1167
0
    break;
1168
0
  case CIL_CALL:
1169
    //Fall through to check content of call
1170
0
    break;
1171
0
  case CIL_TUNABLEIF:
1172
    //Fall through
1173
0
    break;
1174
0
  case CIL_NAMETYPETRANSITION:
1175
    /* While type transitions with file component are not allowed in
1176
       booleanif statements if they don't have "*" as the file. We
1177
       can't check that here. Or at least we won't right now. */
1178
0
    break;
1179
0
  case CIL_SRC_INFO:
1180
    //Fall through
1181
0
    break;
1182
0
  default: {
1183
0
    const char * flavor = cil_node_to_string(node);
1184
0
    if (bif->preserved_tunable) {
1185
0
      cil_tree_log(node, CIL_ERR, "Invalid %s statement in tunableif (treated as a booleanif due to preserve-tunables)", flavor);
1186
0
    } else {
1187
0
      cil_tree_log(node, CIL_ERR, "Invalid %s statement in booleanif", flavor);
1188
0
    }
1189
0
    goto exit;
1190
0
  }
1191
0
  }
1192
1193
0
  rc = SEPOL_OK;
1194
0
exit:
1195
0
  return rc;
1196
0
}
1197
1198
static int __cil_verify_booleanif(struct cil_tree_node *node, struct cil_complex_symtab *symtab)
1199
0
{
1200
0
  int rc = SEPOL_ERR;
1201
0
  struct cil_booleanif *bif = (struct cil_booleanif*)node->data;
1202
0
  struct cil_tree_node *cond_block = node->cl_head;
1203
1204
0
  while (cond_block != NULL) {
1205
0
    rc = cil_tree_walk(cond_block, __cil_verify_booleanif_helper, NULL, NULL, symtab);
1206
0
    if (rc != SEPOL_OK) {
1207
0
      goto exit;
1208
0
    }
1209
0
    cond_block = cond_block->next;
1210
0
  }
1211
1212
0
  return SEPOL_OK;
1213
0
exit:
1214
0
  if (bif->preserved_tunable) {
1215
0
    cil_tree_log(node, CIL_ERR, "Invalid tunableif (treated as a booleanif due to preserve-tunables)");
1216
0
  } else {
1217
0
    cil_tree_log(node, CIL_ERR, "Invalid booleanif");
1218
0
  }
1219
0
  return rc;
1220
0
}
1221
1222
static int __cil_verify_netifcon(struct cil_db *db, struct cil_tree_node *node)
1223
0
{
1224
0
  int rc = SEPOL_ERR;
1225
0
  struct cil_netifcon *netif = node->data;
1226
0
  struct cil_context *if_ctx = netif->if_context;
1227
0
  struct cil_context *pkt_ctx = netif->packet_context;
1228
1229
  /* Verify only when anonymous */
1230
0
  if (if_ctx->datum.name == NULL) {
1231
0
    rc = __cil_verify_context(db, if_ctx);
1232
0
    if (rc != SEPOL_OK) {
1233
0
      goto exit;
1234
0
    }
1235
0
  }
1236
1237
  /* Verify only when anonymous */
1238
0
  if (pkt_ctx->datum.name == NULL) {
1239
0
    rc = __cil_verify_context(db, pkt_ctx);
1240
0
    if (rc != SEPOL_OK) {
1241
0
      goto exit;
1242
0
    }
1243
0
  }
1244
1245
0
  if (strcmp(netif->interface_str, "?") == 0 ||
1246
0
      strcmp(netif->interface_str, "*") == 0) {
1247
0
    goto exit;
1248
0
  }
1249
1250
0
  return SEPOL_OK;
1251
1252
0
exit:
1253
0
  cil_tree_log(node, CIL_ERR, "Invalid netifcon");
1254
0
  return rc;
1255
0
}
1256
1257
static int __cil_verify_ibendportcon(struct cil_db *db, struct cil_tree_node *node)
1258
0
{
1259
0
  int rc = SEPOL_ERR;
1260
0
  struct cil_ibendportcon *ib_end_port = node->data;
1261
0
  struct cil_context *ctx = ib_end_port->context;
1262
1263
  /* Verify only when anonymous */
1264
0
  if (!ctx->datum.name) {
1265
0
    rc = __cil_verify_context(db, ctx);
1266
0
    if (rc != SEPOL_OK)
1267
0
      goto exit;
1268
0
  }
1269
1270
0
  return SEPOL_OK;
1271
1272
0
exit:
1273
0
  cil_tree_log(node, CIL_ERR, "Invalid ibendportcon");
1274
0
  return rc;
1275
0
}
1276
1277
static int __cil_verify_genfscon(struct cil_db *db, struct cil_tree_node *node)
1278
0
{
1279
0
  int rc = SEPOL_ERR;
1280
0
  struct cil_genfscon *genfs = node->data;
1281
0
  struct cil_context *ctx = genfs->context;
1282
1283
  /* Verify only when anonymous */
1284
0
  if (ctx->datum.name == NULL) {
1285
0
    rc = __cil_verify_context(db, ctx);
1286
0
    if (rc != SEPOL_OK) {
1287
0
      goto exit;
1288
0
    }
1289
0
  }
1290
1291
0
  return SEPOL_OK;
1292
1293
0
exit:
1294
0
  cil_tree_log(node, CIL_ERR, "Invalid genfscon");
1295
0
  return rc;
1296
0
}
1297
1298
static int __cil_verify_filecon(struct cil_db *db, struct cil_tree_node *node)
1299
0
{
1300
0
  int rc = SEPOL_ERR;
1301
0
  struct cil_filecon *file = node->data;
1302
0
  struct cil_context *ctx = file->context;
1303
1304
0
  if (ctx == NULL) {
1305
0
    rc = SEPOL_OK;
1306
0
    goto exit;
1307
0
  }
1308
1309
  /* Verify only when anonymous */
1310
0
  if (ctx->datum.name == NULL) {
1311
0
    rc = __cil_verify_context(db, ctx);
1312
0
    if (rc != SEPOL_OK) {
1313
0
      cil_tree_log(node, CIL_ERR, "Invalid filecon");
1314
0
      goto exit;
1315
0
    }
1316
0
  }
1317
1318
0
  return SEPOL_OK;
1319
1320
0
exit:
1321
0
  return rc;
1322
0
}
1323
1324
static int __cil_verify_nodecon(struct cil_db *db, struct cil_tree_node *node)
1325
0
{
1326
0
  int rc = SEPOL_ERR;
1327
0
  struct cil_nodecon *nodecon = node->data;
1328
0
  struct cil_context *ctx = nodecon->context;
1329
1330
  /* Verify only when anonymous */
1331
0
  if (ctx->datum.name == NULL) {
1332
0
    rc = __cil_verify_context(db, ctx);
1333
0
    if (rc != SEPOL_OK) {
1334
0
      goto exit;
1335
0
    }
1336
0
  }
1337
1338
0
  return SEPOL_OK;
1339
1340
0
exit:
1341
0
  cil_tree_log(node, CIL_ERR, "Invalid nodecon");
1342
0
  return rc;
1343
0
}
1344
1345
static int __cil_verify_ibpkeycon(struct cil_db *db, struct cil_tree_node *node)
1346
0
{
1347
0
  int rc = SEPOL_ERR;
1348
0
  struct cil_ibpkeycon *pkey = node->data;
1349
0
  struct cil_context *ctx = pkey->context;
1350
1351
  /* Verify only when anonymous */
1352
0
  if (!ctx->datum.name) {
1353
0
    rc = __cil_verify_context(db, ctx);
1354
0
    if (rc != SEPOL_OK)
1355
0
      goto exit;
1356
0
  }
1357
1358
0
  return SEPOL_OK;
1359
1360
0
exit:
1361
0
  cil_tree_log(node, CIL_ERR, "Invalid ibpkeycon");
1362
0
  return rc;
1363
0
}
1364
1365
static int __cil_verify_portcon(struct cil_db *db, struct cil_tree_node *node)
1366
0
{
1367
0
  int rc = SEPOL_ERR;
1368
0
  struct cil_portcon *port = node->data;
1369
0
  struct cil_context *ctx = port->context;
1370
1371
  /* Verify only when anonymous */
1372
0
  if (ctx->datum.name == NULL) {
1373
0
    rc = __cil_verify_context(db, ctx);
1374
0
    if (rc != SEPOL_OK) {
1375
0
      goto exit;
1376
0
    }
1377
0
  }
1378
1379
0
  return SEPOL_OK;
1380
1381
0
exit:
1382
0
  cil_tree_log(node, CIL_ERR, "Invalid portcon");
1383
0
  return rc;
1384
0
}
1385
1386
static int __cil_verify_pirqcon(struct cil_db *db, struct cil_tree_node *node)
1387
0
{
1388
0
  int rc = SEPOL_ERR;
1389
0
  struct cil_pirqcon *pirq = node->data;
1390
0
  struct cil_context *ctx = pirq->context;
1391
1392
  /* Verify only when anonymous */
1393
0
  if (ctx->datum.name == NULL) {
1394
0
    rc = __cil_verify_context(db, ctx);
1395
0
    if (rc != SEPOL_OK) {
1396
0
      goto exit;
1397
0
    }
1398
0
  }
1399
1400
0
  return SEPOL_OK;
1401
1402
0
exit:
1403
0
  cil_tree_log(node, CIL_ERR, "Invalid pirqcon");
1404
0
  return rc;
1405
0
}
1406
1407
static int __cil_verify_iomemcon(struct cil_db *db, struct cil_tree_node *node)
1408
0
{
1409
0
  int rc = SEPOL_ERR;
1410
0
  struct cil_iomemcon *iomem = node->data;
1411
0
  struct cil_context *ctx = iomem->context;
1412
1413
  /* Verify only when anonymous */
1414
0
  if (ctx->datum.name == NULL) {
1415
0
    rc = __cil_verify_context(db, ctx);
1416
0
    if (rc != SEPOL_OK) {
1417
0
      goto exit;
1418
0
    }
1419
0
  }
1420
1421
0
  return SEPOL_OK;
1422
1423
0
exit:
1424
0
  cil_tree_log(node, CIL_ERR, "Invalid iomemcon");
1425
0
  return rc;
1426
0
}
1427
1428
static int __cil_verify_ioportcon(struct cil_db *db, struct cil_tree_node *node)
1429
0
{
1430
0
  int rc = SEPOL_ERR;
1431
0
  struct cil_ioportcon *ioport = node->data;
1432
0
  struct cil_context *ctx = ioport->context;
1433
1434
  /* Verify only when anonymous */
1435
0
  if (ctx->datum.name == NULL) {
1436
0
    rc = __cil_verify_context(db, ctx);
1437
0
    if (rc != SEPOL_OK) {
1438
0
      goto exit;
1439
0
    }
1440
0
  }
1441
1442
0
  return SEPOL_OK;
1443
1444
0
exit:
1445
0
  cil_tree_log(node, CIL_ERR, "Invalid ioportcon");
1446
0
  return rc;
1447
0
}
1448
1449
static int __cil_verify_pcidevicecon(struct cil_db *db, struct cil_tree_node *node)
1450
0
{
1451
0
  int rc = SEPOL_ERR;
1452
0
  struct cil_pcidevicecon *pcidev = node->data;
1453
0
  struct cil_context *ctx = pcidev->context;
1454
1455
  /* Verify only when anonymous */
1456
0
  if (ctx->datum.name == NULL) {
1457
0
    rc = __cil_verify_context(db, ctx);
1458
0
    if (rc != SEPOL_OK) {
1459
0
      goto exit;
1460
0
    }
1461
0
  }
1462
1463
0
  return SEPOL_OK;
1464
1465
0
exit:
1466
0
  cil_tree_log(node, CIL_ERR, "Invalid pcidevicecon");
1467
0
  return rc;
1468
0
}
1469
1470
static int __cil_verify_devicetreecon(struct cil_db *db, struct cil_tree_node *node)
1471
0
{
1472
0
  int rc = SEPOL_ERR;
1473
0
  struct cil_devicetreecon *dt = node->data;
1474
0
  struct cil_context *ctx = dt->context;
1475
1476
  /* Verify only when anonymous */
1477
0
  if (ctx->datum.name == NULL) {
1478
0
    rc = __cil_verify_context(db, ctx);
1479
0
    if (rc != SEPOL_OK) {
1480
0
      goto exit;
1481
0
    }
1482
0
  }
1483
1484
0
  return SEPOL_OK;
1485
1486
0
exit:
1487
0
  cil_tree_log(node, CIL_ERR, "Invalid devicetreecon");
1488
0
  return rc;
1489
0
}
1490
1491
static int __cil_verify_fsuse(struct cil_db *db, struct cil_tree_node *node)
1492
0
{
1493
0
  int rc = SEPOL_ERR;
1494
0
  struct cil_fsuse *fsuse = node->data;
1495
0
  struct cil_context *ctx = fsuse->context;
1496
1497
  /* Verify only when anonymous */
1498
0
  if (ctx->datum.name == NULL) {
1499
0
    rc = __cil_verify_context(db, ctx);
1500
0
    if (rc != SEPOL_OK) {
1501
0
      goto exit;
1502
0
    }
1503
0
  }
1504
1505
0
  return SEPOL_OK;
1506
1507
0
exit:
1508
0
  cil_tree_log(node, CIL_ERR, "Invalid fsuse");
1509
0
  return rc;
1510
0
}
1511
1512
static int __cil_verify_permissionx(struct cil_permissionx *permx, struct cil_tree_node *node)
1513
0
{
1514
0
  int rc;
1515
0
  struct cil_list *classes = NULL;
1516
0
  struct cil_list_item *item;
1517
0
  struct cil_class *class;
1518
0
  struct cil_symtab_datum *perm_datum;
1519
0
  char *kind_str;
1520
1521
0
  switch (permx->kind) {
1522
0
    case CIL_PERMX_KIND_IOCTL:
1523
0
      kind_str = CIL_KEY_IOCTL;
1524
0
      break;
1525
0
    case CIL_PERMX_KIND_NLMSG:
1526
0
      kind_str = CIL_KEY_NLMSG;
1527
0
      break;
1528
0
    default:
1529
0
      cil_tree_log(node, CIL_ERR, "Invalid permissionx kind (%d)", permx->kind);
1530
0
      rc = SEPOL_ERR;
1531
0
      goto exit;
1532
0
  }
1533
1534
0
  classes = cil_expand_class(permx->obj);
1535
1536
0
  cil_list_for_each(item, classes) {
1537
0
    class = item->data;
1538
0
    rc = cil_symtab_get_datum(&class->perms, kind_str, &perm_datum);
1539
0
    if (rc == SEPOL_ENOENT) {
1540
0
      if (class->common != NULL) {
1541
0
        rc = cil_symtab_get_datum(&class->common->perms, kind_str, &perm_datum);
1542
0
      }
1543
1544
0
      if (rc == SEPOL_ENOENT) {
1545
0
        cil_tree_log(node, CIL_ERR, "Invalid permissionx: %s is not a permission of class %s", kind_str, class->datum.name);
1546
0
        rc = SEPOL_ERR;
1547
0
        goto exit;
1548
0
      }
1549
0
    }
1550
0
  }
1551
1552
0
  rc = SEPOL_OK;
1553
1554
0
exit:
1555
0
  if (classes != NULL) {
1556
0
    cil_list_destroy(&classes, CIL_FALSE);
1557
0
  }
1558
1559
0
  return rc;
1560
0
}
1561
1562
static int __cil_verify_avrulex(struct cil_tree_node *node)
1563
0
{
1564
0
  struct cil_avrule *avrulex = node->data;
1565
0
  return __cil_verify_permissionx(avrulex->perms.x.permx, node);
1566
0
}
1567
1568
static int __cil_verify_class(struct cil_tree_node *node)
1569
0
{
1570
0
  int rc = SEPOL_ERR;
1571
0
  struct cil_class *class = node->data;
1572
1573
0
  if (class->common != NULL) {
1574
0
    struct cil_class *common = class->common;
1575
0
    struct cil_tree_node *common_node = common->datum.nodes->head->data;
1576
0
    struct cil_tree_node *curr_com_perm = NULL;
1577
1578
0
    for (curr_com_perm = common_node->cl_head;
1579
0
      curr_com_perm != NULL;
1580
0
      curr_com_perm = curr_com_perm->next) {
1581
0
      struct cil_perm *com_perm = curr_com_perm->data;
1582
0
      struct cil_tree_node *curr_class_perm = NULL;
1583
1584
0
      for (curr_class_perm = node->cl_head;
1585
0
        curr_class_perm != NULL;
1586
0
        curr_class_perm = curr_class_perm->next) {
1587
0
        struct cil_perm *class_perm = curr_class_perm->data;
1588
1589
0
        if (com_perm->datum.name == class_perm->datum.name) {
1590
0
          cil_log(CIL_ERR, "Duplicate permissions between %s common and class declarations\n", class_perm->datum.name);
1591
0
          goto exit;
1592
0
        }
1593
0
      }
1594
0
    }
1595
0
  }
1596
1597
0
  return SEPOL_OK;
1598
1599
0
exit:
1600
0
  cil_tree_log(node, CIL_ERR, "Invalid class");
1601
0
  return rc;
1602
0
}
1603
1604
static int __cil_verify_policycap(struct cil_tree_node *node)
1605
0
{
1606
0
  int rc;
1607
0
  struct cil_policycap *polcap = node->data;
1608
1609
0
  rc = sepol_polcap_getnum((const char*)polcap->datum.name);
1610
0
  if (rc == SEPOL_ERR) {
1611
0
    goto exit;
1612
0
  }
1613
1614
0
  return SEPOL_OK;
1615
1616
0
exit:
1617
0
  cil_tree_log(node, CIL_ERR, "Invalid policycap (%s)", (const char*)polcap->datum.name);
1618
0
  return rc;
1619
0
}
1620
1621
int __cil_verify_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args)
1622
0
{
1623
0
  int rc = SEPOL_ERR;
1624
0
  int *avrule_cnt = 0;
1625
0
  int *handleunknown;
1626
0
  int *mls;
1627
0
  int *nseuserdflt = 0;
1628
0
  int *pass = 0;
1629
0
  struct cil_args_verify *args = extra_args;
1630
0
  struct cil_complex_symtab *csymtab = NULL;
1631
0
  struct cil_db *db = NULL;
1632
1633
0
  if (node == NULL || extra_args == NULL) {
1634
0
    goto exit;
1635
0
  }
1636
1637
0
  db = args->db;
1638
0
  avrule_cnt = args->avrule_cnt;
1639
0
  handleunknown = args->handleunknown;
1640
0
  mls = args->mls;
1641
0
  nseuserdflt = args->nseuserdflt;
1642
0
  csymtab = args->csymtab;
1643
0
  pass = args->pass;
1644
1645
0
  if (node->flavor == CIL_MACRO) {
1646
0
    *finished = CIL_TREE_SKIP_HEAD;
1647
0
    rc = SEPOL_OK;
1648
0
    goto exit;
1649
0
  } else if (node->flavor == CIL_BLOCK) {
1650
0
    struct cil_block *blk = node->data;
1651
0
    if (blk->is_abstract == CIL_TRUE) {
1652
0
      *finished = CIL_TREE_SKIP_HEAD;
1653
0
    }
1654
0
    rc = SEPOL_OK;
1655
0
    goto exit;
1656
0
  }
1657
1658
0
  switch (*pass) {
1659
0
  case 0: {
1660
0
    switch (node->flavor) {
1661
0
    case CIL_USER:
1662
0
      rc = __cil_verify_user_post_eval(db, node);
1663
0
      break;
1664
0
    case CIL_SELINUXUSERDEFAULT:
1665
0
      (*nseuserdflt)++;
1666
0
      rc = SEPOL_OK;
1667
0
      break;
1668
0
    case CIL_ROLE:
1669
0
      rc = __cil_verify_role(node);
1670
0
      break;
1671
0
    case CIL_TYPE:
1672
0
      rc = __cil_verify_type(node);
1673
0
      break;
1674
0
    case CIL_AVRULE:
1675
0
      (*avrule_cnt)++;
1676
0
      rc = SEPOL_OK;
1677
0
      break;
1678
0
    case CIL_HANDLEUNKNOWN:
1679
0
      if (*handleunknown != -1) {
1680
0
        cil_log(CIL_ERR, "Policy can not have more than one handleunknown\n");
1681
0
        rc = SEPOL_ERR;
1682
0
      } else {
1683
0
        *handleunknown = ((struct cil_handleunknown*)node->data)->handle_unknown;
1684
0
        rc = SEPOL_OK;
1685
0
      }
1686
0
      break;
1687
0
    case CIL_MLS:
1688
0
      if (*mls != -1) {
1689
0
        cil_log(CIL_ERR, "Policy can not have more than one mls\n");
1690
0
        rc = SEPOL_ERR;
1691
0
      } else {
1692
0
        *mls = ((struct cil_mls*)node->data)->value;
1693
0
        rc = SEPOL_OK;
1694
0
      }
1695
0
      break;
1696
0
    case CIL_ROLETRANSITION:
1697
0
      rc = SEPOL_OK; //TODO __cil_verify_rule doesn't work quite right
1698
      //rc = __cil_verify_rule(node, csymtab);
1699
0
      break;
1700
0
    case CIL_TYPE_RULE:
1701
0
      rc = SEPOL_OK; //TODO __cil_verify_rule doesn't work quite right
1702
      //rc = __cil_verify_rule(node, csymtab);
1703
0
      break;
1704
0
    case CIL_BOOLEANIF:
1705
0
      rc = __cil_verify_booleanif(node, csymtab);
1706
0
      *finished = CIL_TREE_SKIP_HEAD;
1707
0
      break;
1708
0
    case CIL_LEVELRANGE:
1709
0
      rc = __cil_verify_named_levelrange(db, node);
1710
0
      break;
1711
0
    case CIL_CLASS:
1712
0
      rc = __cil_verify_class(node);
1713
0
      break;
1714
0
    case CIL_POLICYCAP:
1715
0
      rc = __cil_verify_policycap(node);
1716
0
      break;
1717
0
    default:
1718
0
      rc = SEPOL_OK;
1719
0
      break;
1720
0
    }
1721
0
    break;
1722
0
  }
1723
0
  case 1: {
1724
0
    switch (node->flavor) {
1725
0
    case CIL_CONTEXT:
1726
0
      rc = __cil_verify_named_context(db, node);
1727
0
      break;
1728
0
    case CIL_NETIFCON:
1729
0
      rc = __cil_verify_netifcon(db, node);
1730
0
      break;
1731
0
    case CIL_GENFSCON:
1732
0
      rc = __cil_verify_genfscon(db, node);
1733
0
      break;
1734
0
    case CIL_FILECON:
1735
0
      rc = __cil_verify_filecon(db, node);
1736
0
      break;
1737
0
    case CIL_NODECON:
1738
0
      rc = __cil_verify_nodecon(db, node);
1739
0
      break;
1740
0
    case CIL_IBPKEYCON:
1741
0
      rc = __cil_verify_ibpkeycon(db, node);
1742
0
      break;
1743
0
    case CIL_IBENDPORTCON:
1744
0
      rc = __cil_verify_ibendportcon(db, node);
1745
0
      break;
1746
0
    case CIL_PORTCON:
1747
0
      rc = __cil_verify_portcon(db, node);
1748
0
      break;
1749
0
    case CIL_PIRQCON:
1750
0
      rc = __cil_verify_pirqcon(db, node);
1751
0
      break;
1752
0
    case CIL_IOMEMCON:
1753
0
      rc = __cil_verify_iomemcon(db, node);
1754
0
      break;
1755
0
    case CIL_IOPORTCON:
1756
0
      rc = __cil_verify_ioportcon(db, node);
1757
0
      break;
1758
0
    case CIL_PCIDEVICECON:
1759
0
      rc = __cil_verify_pcidevicecon(db, node);
1760
0
      break;
1761
0
    case CIL_DEVICETREECON:
1762
0
      rc = __cil_verify_devicetreecon(db, node);
1763
0
      break;
1764
0
    case CIL_FSUSE:
1765
0
      rc = __cil_verify_fsuse(db, node);
1766
0
      break;
1767
0
    case CIL_AVRULEX:
1768
0
      rc = __cil_verify_avrulex(node);
1769
0
      break;
1770
0
    case CIL_PERMISSIONX:
1771
0
      rc = __cil_verify_permissionx(node->data, node);
1772
0
      break;
1773
0
    case CIL_RANGETRANSITION:
1774
0
      rc = SEPOL_OK;
1775
0
      break;
1776
0
    default:
1777
0
      rc = SEPOL_OK;
1778
0
      break;
1779
0
    }
1780
0
    break;
1781
0
  }
1782
0
  default:
1783
0
    rc = SEPOL_ERR;
1784
0
  }
1785
1786
0
exit:
1787
0
  return rc;
1788
0
}
1789
1790
static int __add_perm_to_list(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, void *args)
1791
0
{
1792
0
  struct cil_list *perm_list = (struct cil_list *)args;
1793
1794
0
  cil_list_append(perm_list, CIL_DATUM, d);
1795
1796
0
  return SEPOL_OK;
1797
0
}
1798
1799
static int __cil_verify_classperms(struct cil_list *classperms, struct cil_symtab_datum *orig, struct cil_symtab_datum *cur, unsigned steps, unsigned limit);
1800
1801
static int __cil_verify_map_perm(struct cil_class *class, struct cil_perm *perm, struct cil_symtab_datum *orig, unsigned steps, unsigned limit)
1802
0
{
1803
0
  int rc;
1804
1805
0
  if (!perm->classperms) {
1806
0
    cil_tree_log(NODE(class), CIL_ERR, "No class permissions for map class %s, permission %s", DATUM(class)->name, DATUM(perm)->name);
1807
0
    goto exit;
1808
0
  }
1809
1810
0
  rc = __cil_verify_classperms(perm->classperms, orig, &perm->datum, steps, limit);
1811
0
  if (rc != SEPOL_OK) {
1812
0
    cil_tree_log(NODE(class), CIL_ERR, "There was an error verifying class permissions for map class %s, permission %s", DATUM(class)->name, DATUM(perm)->name);
1813
0
    goto exit;
1814
0
  }
1815
1816
0
  return SEPOL_OK;
1817
1818
0
exit:
1819
0
  return SEPOL_ERR;
1820
0
}
1821
1822
1823
static int __cil_verify_perms(struct cil_class *class, struct cil_list *perms, struct cil_symtab_datum *orig, unsigned steps, unsigned limit)
1824
0
{
1825
0
  int rc = SEPOL_ERR;
1826
0
  int count = 0;
1827
0
  struct cil_list_item *i = NULL;
1828
1829
0
  if (!perms) {
1830
0
    cil_tree_log(NODE(class), CIL_ERR, "No permissions for class %s in class permissions", DATUM(class)->name);
1831
0
    goto exit;
1832
0
  }
1833
1834
0
  cil_list_for_each(i, perms) {
1835
0
    count++;
1836
0
    if (i->flavor == CIL_LIST) {
1837
0
      rc = __cil_verify_perms(class, i->data, orig, steps, limit);
1838
0
      if (rc != SEPOL_OK) {
1839
0
        goto exit;
1840
0
      }
1841
0
    } else if (i->flavor == CIL_DATUM) {
1842
0
      struct cil_perm *perm = i->data;
1843
0
      if (FLAVOR(perm) == CIL_MAP_PERM) {
1844
0
        rc = __cil_verify_map_perm(class, perm, orig, steps, limit);
1845
0
        if (rc != SEPOL_OK) {
1846
0
          goto exit;
1847
0
        }
1848
0
      }
1849
0
    } else if (i->flavor == CIL_OP) {
1850
0
      enum cil_flavor op = (enum cil_flavor)(uintptr_t)i->data;
1851
0
      if (op == CIL_ALL) {
1852
0
        struct cil_list *perm_list;
1853
0
        struct cil_list_item *j = NULL;
1854
0
        int count2 = 0;
1855
0
        cil_list_init(&perm_list, CIL_MAP_PERM);
1856
0
        cil_symtab_map(&class->perms, __add_perm_to_list, perm_list);
1857
0
        if (class->common != NULL) {
1858
0
          cil_symtab_map(&class->common->perms, __add_perm_to_list, perm_list);
1859
0
        }
1860
0
        cil_list_for_each(j, perm_list) {
1861
0
          count2++;
1862
0
          struct cil_perm *perm = j->data;
1863
0
          if (FLAVOR(perm) == CIL_MAP_PERM) {
1864
0
            rc = __cil_verify_map_perm(class, perm, orig, steps, limit);
1865
0
            if (rc != SEPOL_OK) {
1866
0
              cil_list_destroy(&perm_list, CIL_FALSE);
1867
0
              goto exit;
1868
0
            }
1869
0
          }
1870
0
        }
1871
0
        cil_list_destroy(&perm_list, CIL_FALSE);
1872
0
        if (count2 == 0) {
1873
0
          cil_tree_log(NODE(class), CIL_ERR, "Operator \"all\" used for %s which has no permissions associated with it", DATUM(class)->name);
1874
0
          goto exit;
1875
0
        }
1876
0
      }
1877
0
    } else {
1878
0
      cil_tree_log(NODE(class), CIL_ERR, "Permission list for %s has an unexpected flavor: %d", DATUM(class)->name, i->flavor);
1879
0
      goto exit;
1880
0
    }
1881
0
  }
1882
1883
0
  if (count == 0) {
1884
0
    cil_tree_log(NODE(class), CIL_ERR, "Empty permissions list for class %s in class permissions", DATUM(class)->name);
1885
0
    goto exit;
1886
0
  }
1887
1888
0
  return SEPOL_OK;
1889
1890
0
exit:
1891
0
  return SEPOL_ERR;
1892
0
}
1893
1894
static int __cil_verify_classperms(struct cil_list *classperms, struct cil_symtab_datum *orig, struct cil_symtab_datum *cur, unsigned steps, unsigned limit)
1895
0
{
1896
0
  int rc;
1897
0
  struct cil_list_item *i;
1898
1899
0
  if (classperms == NULL) {
1900
0
    goto exit;
1901
0
  }
1902
1903
0
  if (steps > 0 && orig == cur) {
1904
0
    cil_tree_log(NODE(cur), CIL_ERR, "Found circular class permissions involving %s", cur->name);
1905
0
    goto exit;
1906
0
  } else {
1907
0
    steps++;
1908
0
    if (steps > limit) {
1909
0
      steps = 1;
1910
0
      limit *= 2;
1911
0
      orig = cur;
1912
0
    }
1913
0
  }
1914
1915
0
  cil_list_for_each(i, classperms) {
1916
0
    if (i->flavor == CIL_CLASSPERMS) {
1917
0
      struct cil_classperms *cp = i->data;
1918
0
      rc = __cil_verify_perms(cp->class, cp->perms, orig, steps, limit);
1919
0
      if (rc != SEPOL_OK) {
1920
0
        goto exit;
1921
0
      }
1922
0
    } else { /* SET */
1923
0
      struct cil_classperms_set *cp_set = i->data;
1924
0
      struct cil_classpermission *cp = cp_set->set;
1925
0
      if (!cp->classperms) {
1926
0
        cil_tree_log(NODE(cur), CIL_ERR, "Classpermission %s does not have a classpermissionset", DATUM(cp)->name);
1927
0
      }
1928
0
      rc = __cil_verify_classperms(cp->classperms, orig, &cp->datum, steps, limit);
1929
0
      if (rc != SEPOL_OK) {
1930
0
        goto exit;
1931
0
      }
1932
0
    }
1933
0
  }
1934
1935
0
  return SEPOL_OK;
1936
1937
0
exit:
1938
0
  return SEPOL_ERR;
1939
0
}
1940
1941
static int __cil_verify_classpermission(struct cil_tree_node *node)
1942
0
{
1943
0
  int rc;
1944
0
  struct cil_classpermission *cp = node->data;
1945
1946
0
  rc = __cil_verify_classperms(cp->classperms, &cp->datum, &cp->datum, 0, 2);
1947
0
  if (rc != SEPOL_OK) {
1948
0
    cil_tree_log(node, CIL_ERR, "Error verifying class permissions for classpermission %s", DATUM(cp)->name);
1949
0
  }
1950
1951
0
  return rc;
1952
0
}
1953
1954
struct cil_verify_map_args {
1955
  struct cil_class *class;
1956
  struct cil_tree_node *node;
1957
  int rc;
1958
};
1959
1960
static int __verify_map_perm_classperms(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, void *args)
1961
0
{
1962
0
  struct cil_verify_map_args *map_args = args;
1963
0
  struct cil_perm *cmp = (struct cil_perm *)d;
1964
0
  int rc;
1965
1966
0
  rc = __cil_verify_classperms(cmp->classperms, &cmp->datum, &cmp->datum, 0, 2);
1967
0
  if (rc != SEPOL_OK) {
1968
0
    cil_tree_log(NODE(cmp), CIL_ERR, "Error verifying class permissions for map class %s, permission %s", DATUM(map_args->class)->name, DATUM(cmp)->name);
1969
0
    map_args->rc = rc;
1970
0
  }
1971
1972
0
  return SEPOL_OK;
1973
0
}
1974
1975
static int __cil_verify_map_class(struct cil_tree_node *node)
1976
0
{
1977
0
  struct cil_class *mc = node->data;
1978
0
  struct cil_verify_map_args map_args;
1979
1980
0
  map_args.class = mc;
1981
0
  map_args.node = node;
1982
0
  map_args.rc = SEPOL_OK;
1983
1984
0
  cil_symtab_map(&mc->perms, __verify_map_perm_classperms, &map_args);
1985
1986
0
  if (map_args.rc != SEPOL_OK) {
1987
0
    return SEPOL_ERR;
1988
0
  }
1989
1990
0
  return SEPOL_OK;
1991
0
}
1992
1993
int __cil_pre_verify_helper(struct cil_tree_node *node, uint32_t *finished, __attribute__((unused)) void *extra_args)
1994
0
{
1995
0
  int rc = SEPOL_OK;
1996
1997
0
  switch (node->flavor) {
1998
0
  case CIL_MACRO: {
1999
0
    *finished = CIL_TREE_SKIP_HEAD;
2000
0
    break;
2001
0
  }
2002
0
  case CIL_BLOCK: {
2003
0
    struct cil_block *blk = node->data;
2004
0
    if (blk->is_abstract == CIL_TRUE) {
2005
0
      *finished = CIL_TREE_SKIP_HEAD;
2006
0
    }
2007
0
    break;
2008
0
  }
2009
0
  case CIL_USER:
2010
0
    rc = __cil_verify_user_pre_eval(node);
2011
0
    break;
2012
0
  case CIL_MAP_CLASS:
2013
0
    rc = __cil_verify_map_class(node);
2014
0
    break;
2015
0
  case CIL_CLASSPERMISSION:
2016
0
    rc = __cil_verify_classpermission(node);
2017
0
    break;
2018
0
  case CIL_USERATTRIBUTE:
2019
0
  case CIL_ROLEATTRIBUTE:
2020
0
  case CIL_TYPEATTRIBUTE:
2021
0
  case CIL_CATSET: {
2022
0
    struct cil_stack *stack;
2023
0
    cil_stack_init(&stack);
2024
0
    rc = cil_verify_no_self_reference(node->flavor, node->data, stack);
2025
0
    cil_stack_destroy(&stack);
2026
0
    break;
2027
0
  }
2028
0
  default:
2029
0
    rc = SEPOL_OK;
2030
0
    break;
2031
0
  }
2032
2033
0
  return rc;
2034
0
}