Coverage Report

Created: 2026-09-01 06:10

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