Coverage Report

Created: 2026-10-17 06:07

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/selinux/libsepol/src/conditional.c
Line
Count
Source
1
/* Authors: Karl MacMillan <kmacmillan@tresys.com>
2
 *          Frank Mayer <mayerf@tresys.com>
3
 *          David Caplan <dac@tresys.com>
4
 *
5
 * Copyright (C) 2003 - 2005 Tresys Technology, LLC
6
 *
7
 *  This library is free software; you can redistribute it and/or
8
 *  modify it under the terms of the GNU Lesser General Public
9
 *  License as published by the Free Software Foundation; either
10
 *  version 2.1 of the License, or (at your option) any later version.
11
 *
12
 *  This library is distributed in the hope that it will be useful,
13
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 *  Lesser General Public License for more details.
16
 *
17
 *  You should have received a copy of the GNU Lesser General Public
18
 *  License along with this library; if not, write to the Free Software
19
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20
 */
21
22
#include <stdlib.h>
23
24
#include <sepol/policydb/flask_types.h>
25
#include <sepol/policydb/conditional.h>
26
27
#include "private.h"
28
#include "debug.h"
29
30
/* move all type rules to top of t/f lists to help kernel on evaluation */
31
static void cond_optimize(cond_av_list_t **l)
32
0
{
33
0
  cond_av_list_t *top, *p, *cur;
34
35
0
  top = p = cur = *l;
36
37
0
  while (cur) {
38
0
    if ((cur->node->key.specified & AVTAB_TYPE) && (top != cur)) {
39
0
      p->next = cur->next;
40
0
      cur->next = top;
41
0
      top = cur;
42
0
      cur = p->next;
43
0
    } else {
44
0
      p = cur;
45
0
      cur = cur->next;
46
0
    }
47
0
  }
48
0
  *l = top;
49
0
}
50
51
/* reorder t/f lists for kernel */
52
void cond_optimize_lists(cond_list_t *cl)
53
0
{
54
0
  cond_list_t *n;
55
56
0
  for (n = cl; n != NULL; n = n->next) {
57
0
    cond_optimize(&n->true_list);
58
0
    cond_optimize(&n->false_list);
59
0
  }
60
0
}
61
62
static int bool_present(unsigned int target, unsigned int bools[],
63
      unsigned int num_bools)
64
0
{
65
0
  unsigned int i = 0;
66
0
  int ret = 1;
67
68
0
  if (num_bools > COND_MAX_BOOLS) {
69
0
    return 0;
70
0
  }
71
0
  while (i < num_bools && target != bools[i])
72
0
    i++;
73
0
  if (i == num_bools)
74
0
    ret = 0; /* got to end w/o match */
75
0
  return ret;
76
0
}
77
78
static int same_bools(cond_node_t *a, cond_node_t *b)
79
0
{
80
0
  unsigned int i, x;
81
82
0
  x = a->nbools;
83
84
  /* same number of bools? */
85
0
  if (x != b->nbools)
86
0
    return 0;
87
88
  /* make sure all the bools in a are also in b */
89
0
  for (i = 0; i < x; i++)
90
0
    if (!bool_present(a->bool_ids[i], b->bool_ids, x))
91
0
      return 0;
92
0
  return 1;
93
0
}
94
95
/*
96
 * Determine if two conditional expressions are equal. 
97
 */
98
int cond_expr_equal(cond_node_t *a, cond_node_t *b)
99
0
{
100
0
  cond_expr_t *cur_a, *cur_b;
101
102
0
  if (a == NULL || b == NULL)
103
0
    return 0;
104
105
0
  if (a->nbools != b->nbools)
106
0
    return 0;
107
108
  /* if exprs have <= COND_MAX_BOOLS we can check the precompute values
109
   * for the expressions.
110
   */
111
0
  if (a->nbools <= COND_MAX_BOOLS && b->nbools <= COND_MAX_BOOLS) {
112
0
    if (!same_bools(a, b))
113
0
      return 0;
114
0
    return (a->expr_pre_comp == b->expr_pre_comp);
115
0
  }
116
117
  /* for long expressions we check for exactly the same expression */
118
0
  cur_a = a->expr;
119
0
  cur_b = b->expr;
120
0
  while (1) {
121
0
    if (cur_a == NULL && cur_b == NULL)
122
0
      return 1;
123
0
    else if (cur_a == NULL || cur_b == NULL)
124
0
      return 0;
125
0
    if (cur_a->expr_type != cur_b->expr_type)
126
0
      return 0;
127
0
    if (cur_a->expr_type == COND_BOOL) {
128
0
      if (cur_a->boolean != cur_b->boolean)
129
0
        return 0;
130
0
    }
131
0
    cur_a = cur_a->next;
132
0
    cur_b = cur_b->next;
133
0
  }
134
0
  return 1;
135
0
}
136
137
/* Create a new conditional node, optionally copying
138
 * the conditional expression from an existing node.
139
 * If node is NULL then a new node will be created
140
 * with no conditional expression.
141
 */
142
cond_node_t *cond_node_create(policydb_t *p, cond_node_t *node)
143
0
{
144
0
  cond_node_t *new_node;
145
0
  unsigned int i;
146
147
0
  new_node = (cond_node_t *)malloc(sizeof(cond_node_t));
148
0
  if (!new_node) {
149
0
    return NULL;
150
0
  }
151
0
  memset(new_node, 0, sizeof(cond_node_t));
152
153
0
  if (node) {
154
0
    new_node->expr = cond_copy_expr(node->expr);
155
0
    if (!new_node->expr) {
156
0
      free(new_node);
157
0
      return NULL;
158
0
    }
159
0
    new_node->cur_state = cond_evaluate_expr(p, new_node->expr);
160
0
    new_node->nbools = node->nbools;
161
0
    for (i = 0; i < min(node->nbools, COND_MAX_BOOLS); i++)
162
0
      new_node->bool_ids[i] = node->bool_ids[i];
163
0
    new_node->expr_pre_comp = node->expr_pre_comp;
164
0
    new_node->flags = node->flags;
165
0
  }
166
167
0
  return new_node;
168
0
}
169
170
/* Find a conditional (the needle) within a list of existing ones (the
171
 * haystack) that has a matching expression.  If found, return a
172
 * pointer to the existing node, setting 'was_created' to 0.
173
 * Otherwise create a new one and return it, setting 'was_created' to
174
 * 1. */
175
cond_node_t *cond_node_find(policydb_t *p, cond_node_t *needle,
176
          cond_node_t *haystack, int *was_created)
177
0
{
178
0
  while (haystack) {
179
0
    if (cond_expr_equal(needle, haystack)) {
180
0
      *was_created = 0;
181
0
      return haystack;
182
0
    }
183
0
    haystack = haystack->next;
184
0
  }
185
0
  *was_created = 1;
186
187
0
  return cond_node_create(p, needle);
188
0
}
189
190
/* return either a pre-existing matching node or create a new node */
191
cond_node_t *cond_node_search(policydb_t *p, cond_node_t *list, cond_node_t *cn)
192
0
{
193
0
  int was_created;
194
0
  cond_node_t *result = cond_node_find(p, cn, list, &was_created);
195
0
  if (result != NULL && was_created) {
196
    /* add conditional node to policy list */
197
0
    result->next = p->cond_list;
198
0
    p->cond_list = result;
199
0
  }
200
0
  return result;
201
0
}
202
203
/*
204
 * cond_evaluate_expr evaluates a conditional expr
205
 * in reverse polish notation. It returns true (1), false (0),
206
 * or undefined (-1). Undefined occurs when the expression
207
 * exceeds the stack depth of COND_EXPR_MAXDEPTH.
208
 */
209
int cond_evaluate_expr(policydb_t *p, cond_expr_t *expr)
210
0
{
211
0
  cond_expr_t *cur;
212
0
  int s[COND_EXPR_MAXDEPTH];
213
0
  int sp = -1;
214
215
0
  s[0] = -1;
216
217
0
  for (cur = expr; cur != NULL; cur = cur->next) {
218
0
    switch (cur->expr_type) {
219
0
    case COND_BOOL:
220
0
      if (sp == (COND_EXPR_MAXDEPTH - 1))
221
0
        return -1;
222
0
      sp++;
223
0
      s[sp] = p->bool_val_to_struct[cur->boolean - 1]->state;
224
0
      break;
225
0
    case COND_NOT:
226
0
      if (sp < 0)
227
0
        return -1;
228
0
      s[sp] = !s[sp];
229
0
      break;
230
0
    case COND_OR:
231
0
      if (sp < 1)
232
0
        return -1;
233
0
      sp--;
234
0
      s[sp] |= s[sp + 1];
235
0
      break;
236
0
    case COND_AND:
237
0
      if (sp < 1)
238
0
        return -1;
239
0
      sp--;
240
0
      s[sp] &= s[sp + 1];
241
0
      break;
242
0
    case COND_XOR:
243
0
      if (sp < 1)
244
0
        return -1;
245
0
      sp--;
246
0
      s[sp] ^= s[sp + 1];
247
0
      break;
248
0
    case COND_EQ:
249
0
      if (sp < 1)
250
0
        return -1;
251
0
      sp--;
252
0
      s[sp] = (s[sp] == s[sp + 1]);
253
0
      break;
254
0
    case COND_NEQ:
255
0
      if (sp < 1)
256
0
        return -1;
257
0
      sp--;
258
0
      s[sp] = (s[sp] != s[sp + 1]);
259
0
      break;
260
0
    default:
261
0
      return -1;
262
0
    }
263
0
  }
264
0
  return s[0];
265
0
}
266
267
cond_expr_t *cond_copy_expr(cond_expr_t *expr)
268
0
{
269
0
  cond_expr_t *cur, *head, *tail, *new_expr;
270
0
  tail = head = NULL;
271
0
  cur = expr;
272
0
  while (cur) {
273
0
    new_expr = (cond_expr_t *)malloc(sizeof(cond_expr_t));
274
0
    if (!new_expr)
275
0
      goto free_head;
276
0
    memset(new_expr, 0, sizeof(cond_expr_t));
277
278
0
    new_expr->expr_type = cur->expr_type;
279
0
    new_expr->boolean = cur->boolean;
280
281
0
    if (!head)
282
0
      head = new_expr;
283
0
    if (tail)
284
0
      tail->next = new_expr;
285
0
    tail = new_expr;
286
0
    cur = cur->next;
287
0
  }
288
0
  return head;
289
290
0
free_head:
291
0
  while (head) {
292
0
    tail = head->next;
293
0
    free(head);
294
0
    head = tail;
295
0
  }
296
0
  return NULL;
297
0
}
298
299
/*
300
 * evaluate_cond_node evaluates the conditional stored in
301
 * a cond_node_t and if the result is different than the
302
 * current state of the node it sets the rules in the true/false
303
 * list appropriately. If the result of the expression is undefined
304
 * all of the rules are disabled for safety.
305
 */
306
static int evaluate_cond_node(policydb_t *p, cond_node_t *node)
307
0
{
308
0
  int new_state;
309
0
  cond_av_list_t *cur;
310
311
0
  new_state = cond_evaluate_expr(p, node->expr);
312
0
  if (new_state != node->cur_state) {
313
0
    node->cur_state = new_state;
314
0
    if (new_state == -1)
315
0
      WARN(NULL,
316
0
           "expression result was undefined - disabling all rules.");
317
    /* turn the rules on or off */
318
0
    for (cur = node->true_list; cur != NULL; cur = cur->next) {
319
0
      if (new_state <= 0) {
320
0
        cur->node->key.specified &= ~AVTAB_ENABLED;
321
0
      } else {
322
0
        cur->node->key.specified |= AVTAB_ENABLED;
323
0
      }
324
0
    }
325
326
0
    for (cur = node->false_list; cur != NULL; cur = cur->next) {
327
      /* -1 or 1 */
328
0
      if (new_state) {
329
0
        cur->node->key.specified &= ~AVTAB_ENABLED;
330
0
      } else {
331
0
        cur->node->key.specified |= AVTAB_ENABLED;
332
0
      }
333
0
    }
334
0
  }
335
0
  return 0;
336
0
}
337
338
/* precompute and simplify an expression if possible.  If left with !expression, change 
339
 * to expression and switch t and f. precompute expression for expressions with limited
340
 * number of bools.
341
 */
342
int cond_normalize_expr(policydb_t *p, cond_node_t *cn)
343
0
{
344
0
  cond_expr_t *ne, *e;
345
0
  cond_av_list_t *tmp;
346
0
  unsigned int i, j, orig_value[COND_MAX_BOOLS];
347
0
  int k;
348
0
  uint32_t test = 0x0;
349
0
  avrule_t *tmp2;
350
351
0
  cn->nbools = 0;
352
353
0
  memset(cn->bool_ids, 0, sizeof(cn->bool_ids));
354
0
  cn->expr_pre_comp = 0x0;
355
356
  /* take care of !expr case */
357
0
  ne = NULL;
358
0
  e = cn->expr;
359
360
  /* because it's RPN look at last element */
361
0
  while (e->next != NULL) {
362
0
    ne = e;
363
0
    e = e->next;
364
0
  }
365
0
  if (e->expr_type == COND_NOT) {
366
0
    if (ne) {
367
0
      ne->next = NULL;
368
0
    } else { /* ne should never be NULL */
369
0
      ERR(NULL,
370
0
          "Found expr with no bools and only a ! - this should never happen.");
371
0
      return -1;
372
0
    }
373
    /* swap the true and false lists */
374
0
    tmp = cn->true_list;
375
0
    cn->true_list = cn->false_list;
376
0
    cn->false_list = tmp;
377
0
    tmp2 = cn->avtrue_list;
378
0
    cn->avtrue_list = cn->avfalse_list;
379
0
    cn->avfalse_list = tmp2;
380
381
    /* free the "not" node in the list */
382
0
    free(e);
383
0
  }
384
385
  /* find all the bools in the expression */
386
0
  for (e = cn->expr; e != NULL; e = e->next) {
387
0
    switch (e->expr_type) {
388
0
    case COND_BOOL:
389
      /* see if we've already seen this bool */
390
0
      if (!bool_present(e->boolean, cn->bool_ids,
391
0
            cn->nbools)) {
392
        /* count em all but only record up to COND_MAX_BOOLS */
393
0
        if (cn->nbools < COND_MAX_BOOLS)
394
0
          cn->bool_ids[cn->nbools++] = e->boolean;
395
0
        else
396
0
          cn->nbools++;
397
0
      }
398
0
      break;
399
0
    default:
400
0
      break;
401
0
    }
402
0
  }
403
404
  /* only precompute for exprs with <= COND_AX_BOOLS */
405
0
  if (cn->nbools <= COND_MAX_BOOLS) {
406
    /* save the default values for the bools so we can play with them */
407
0
    for (i = 0; i < cn->nbools; i++) {
408
0
      orig_value[i] =
409
0
        p->bool_val_to_struct[cn->bool_ids[i] - 1]
410
0
          ->state;
411
0
    }
412
413
    /* loop through all possible combinations of values for bools in expression */
414
0
    for (test = 0x0; test < (UINT32_C(1) << cn->nbools); test++) {
415
      /* temporarily set the value for all the bools in the
416
       * expression using the corr.  bit in test */
417
0
      for (j = 0; j < cn->nbools; j++) {
418
0
        p->bool_val_to_struct[cn->bool_ids[j] - 1]
419
0
          ->state =
420
0
          (test & (UINT32_C(1) << j)) ? 1 : 0;
421
0
      }
422
0
      k = cond_evaluate_expr(p, cn->expr);
423
0
      if (k == -1) {
424
0
        ERR(NULL,
425
0
            "While testing expression, expression result "
426
0
            "was undefined - this should never happen.");
427
0
        return -1;
428
0
      }
429
      /* set the bit if expression evaluates true */
430
0
      if (k)
431
0
        cn->expr_pre_comp |= UINT32_C(1) << test;
432
0
    }
433
434
    /* restore bool default values */
435
0
    for (i = 0; i < cn->nbools; i++)
436
0
      p->bool_val_to_struct[cn->bool_ids[i] - 1]->state =
437
0
        orig_value[i];
438
0
  }
439
0
  return 0;
440
0
}
441
442
int evaluate_conds(policydb_t *p)
443
0
{
444
0
  int ret;
445
0
  cond_node_t *cur;
446
447
0
  for (cur = p->cond_list; cur != NULL; cur = cur->next) {
448
0
    ret = evaluate_cond_node(p, cur);
449
0
    if (ret)
450
0
      return ret;
451
0
  }
452
0
  return 0;
453
0
}
454
455
int cond_policydb_init(policydb_t *p)
456
9.64k
{
457
9.64k
  p->bool_val_to_struct = NULL;
458
9.64k
  p->cond_list = NULL;
459
9.64k
  if (avtab_init(&p->te_cond_avtab))
460
0
    return -1;
461
462
9.64k
  return 0;
463
9.64k
}
464
465
void cond_av_list_destroy(cond_av_list_t *list)
466
3.77k
{
467
3.77k
  cond_av_list_t *cur, *next;
468
3.77k
  for (cur = list; cur != NULL; cur = next) {
469
0
    next = cur->next;
470
    /* the avtab_ptr_t node is destroy by the avtab */
471
0
    free(cur);
472
0
  }
473
3.77k
}
474
475
void cond_expr_destroy(cond_expr_t *expr)
476
1.88k
{
477
1.88k
  cond_expr_t *cur_expr, *next_expr;
478
479
1.88k
  if (!expr)
480
1.62k
    return;
481
482
734
  for (cur_expr = expr; cur_expr != NULL; cur_expr = next_expr) {
483
475
    next_expr = cur_expr->next;
484
475
    free(cur_expr);
485
475
  }
486
259
}
487
488
void cond_node_destroy(cond_node_t *node)
489
1.88k
{
490
1.88k
  if (!node)
491
0
    return;
492
493
1.88k
  cond_expr_destroy(node->expr);
494
1.88k
  avrule_list_destroy(node->avtrue_list);
495
1.88k
  avrule_list_destroy(node->avfalse_list);
496
1.88k
  cond_av_list_destroy(node->true_list);
497
1.88k
  cond_av_list_destroy(node->false_list);
498
1.88k
}
499
500
void cond_list_destroy(cond_list_t *list)
501
29.4k
{
502
29.4k
  cond_node_t *next, *cur;
503
504
29.4k
  if (list == NULL)
505
29.4k
    return;
506
507
1.68k
  for (cur = list; cur != NULL; cur = next) {
508
1.60k
    next = cur->next;
509
1.60k
    cond_node_destroy(cur);
510
1.60k
    free(cur);
511
1.60k
  }
512
74
}
513
514
void cond_policydb_destroy(policydb_t *p)
515
9.64k
{
516
9.64k
  if (p->bool_val_to_struct != NULL)
517
5.33k
    free(p->bool_val_to_struct);
518
9.64k
  avtab_destroy(&p->te_cond_avtab);
519
9.64k
  cond_list_destroy(p->cond_list);
520
9.64k
}
521
522
int cond_init_bool_indexes(policydb_t *p)
523
5.33k
{
524
5.33k
  if (p->bool_val_to_struct)
525
0
    free(p->bool_val_to_struct);
526
5.33k
  p->bool_val_to_struct = (cond_bool_datum_t **)calloc(
527
5.33k
    p->p_bools.nprim, sizeof(cond_bool_datum_t *));
528
5.33k
  if (!p->bool_val_to_struct)
529
0
    return -1;
530
5.33k
  return 0;
531
5.33k
}
532
533
int cond_destroy_bool(hashtab_key_t key, hashtab_datum_t datum,
534
          void *p __attribute__((unused)))
535
540
{
536
540
  if (key)
537
419
    free(key);
538
540
  free(datum);
539
540
  return 0;
540
540
}
541
542
int cond_index_bool(hashtab_key_t key, hashtab_datum_t datum, void *datap)
543
121
{
544
121
  policydb_t *p;
545
121
  cond_bool_datum_t *booldatum;
546
547
121
  booldatum = datum;
548
121
  p = datap;
549
550
121
  if (!booldatum->s.value || booldatum->s.value > p->p_bools.nprim)
551
72
    return -EINVAL;
552
553
49
  if (p->p_bool_val_to_name[booldatum->s.value - 1] != NULL)
554
0
    return -EINVAL;
555
556
49
  p->p_bool_val_to_name[booldatum->s.value - 1] = key;
557
49
  p->bool_val_to_struct[booldatum->s.value - 1] = booldatum;
558
559
49
  return 0;
560
49
}
561
562
static int bool_isvalid(cond_bool_datum_t *b)
563
479
{
564
479
  if (!(b->state == 0 || b->state == 1))
565
50
    return 0;
566
429
  return 1;
567
479
}
568
569
int cond_read_bool(policydb_t *p, hashtab_t h, struct policy_file *fp)
570
540
{
571
540
  char *key = NULL;
572
540
  cond_bool_datum_t *booldatum;
573
540
  uint32_t buf[3], len;
574
540
  int rc;
575
576
540
  booldatum = malloc(sizeof(cond_bool_datum_t));
577
540
  if (!booldatum)
578
0
    return -1;
579
540
  memset(booldatum, 0, sizeof(cond_bool_datum_t));
580
581
540
  rc = next_entry(buf, fp, sizeof(uint32_t) * 3);
582
540
  if (rc < 0)
583
61
    goto err;
584
585
479
  booldatum->s.value = le32_to_cpu(buf[0]);
586
479
  booldatum->state = le32_to_cpu(buf[1]);
587
588
479
  if (!bool_isvalid(booldatum))
589
50
    goto err;
590
591
429
  len = le32_to_cpu(buf[2]);
592
429
  if (str_read(&key, fp, len))
593
10
    goto err;
594
595
419
  if (p->policy_type != POLICY_KERN) {
596
419
    rc = next_entry(buf, fp, sizeof(uint32_t));
597
419
    if (rc < 0)
598
1
      goto err;
599
418
    booldatum->flags = le32_to_cpu(buf[0]);
600
418
  }
601
602
418
  if (hashtab_insert(h, key, booldatum))
603
1
    goto err;
604
605
417
  return 0;
606
123
err:
607
123
  cond_destroy_bool(key, booldatum, NULL);
608
123
  return -1;
609
418
}
610
611
struct cond_insertf_data {
612
  struct policydb *p;
613
  cond_av_list_t *other;
614
  cond_av_list_t *head;
615
  cond_av_list_t *tail;
616
};
617
618
static int cond_insertf(avtab_t *a __attribute__((unused)), avtab_key_t *k,
619
      avtab_datum_t *d, void *ptr)
620
0
{
621
0
  struct cond_insertf_data *data = ptr;
622
0
  struct policydb *p = data->p;
623
0
  cond_av_list_t *other = data->other, *list, *cur;
624
0
  avtab_ptr_t node_ptr;
625
0
  uint8_t found;
626
627
  /*
628
   * For type rules we have to make certain there aren't any
629
   * conflicting rules by searching the te_avtab and the
630
   * cond_te_avtab.
631
   */
632
0
  if (k->specified & AVTAB_TYPE) {
633
0
    if (avtab_search(&p->te_avtab, k)) {
634
0
      WARN(NULL,
635
0
           "security: type rule already exists outside of a conditional.");
636
0
      return -1;
637
0
    }
638
    /*
639
     * If we are reading the false list other will be a pointer to
640
     * the true list. We can have duplicate entries if there is only
641
     * 1 other entry and it is in our true list.
642
     *
643
     * If we are reading the true list (other == NULL) there shouldn't
644
     * be any other entries.
645
     */
646
0
    if (other) {
647
0
      node_ptr = avtab_search_node(&p->te_cond_avtab, k);
648
0
      if (node_ptr) {
649
0
        if (avtab_search_node_next(node_ptr,
650
0
                 k->specified)) {
651
0
          ERR(NULL,
652
0
              "security: too many conflicting type rules.");
653
0
          return -1;
654
0
        }
655
0
        found = 0;
656
0
        for (cur = other; cur != NULL;
657
0
             cur = cur->next) {
658
0
          if (cur->node == node_ptr) {
659
0
            found = 1;
660
0
            break;
661
0
          }
662
0
        }
663
0
        if (!found) {
664
0
          ERR(NULL,
665
0
              "security: conflicting type rules.");
666
0
          return -1;
667
0
        }
668
0
      }
669
0
    } else {
670
0
      if (avtab_search(&p->te_cond_avtab, k)) {
671
0
        ERR(NULL,
672
0
            "security: conflicting type rules when adding type rule for true.");
673
0
        return -1;
674
0
      }
675
0
    }
676
0
  }
677
678
0
  node_ptr = avtab_insert_nonunique(&p->te_cond_avtab, k, d);
679
0
  if (!node_ptr) {
680
0
    ERR(NULL, "security: could not insert rule.");
681
0
    return -1;
682
0
  }
683
0
  node_ptr->parse_context = (void *)1;
684
685
0
  list = malloc(sizeof(cond_av_list_t));
686
0
  if (!list)
687
0
    return -1;
688
0
  memset(list, 0, sizeof(cond_av_list_t));
689
690
0
  list->node = node_ptr;
691
0
  if (!data->head)
692
0
    data->head = list;
693
0
  else
694
0
    data->tail->next = list;
695
0
  data->tail = list;
696
0
  return 0;
697
0
}
698
699
static int cond_read_av_list(policydb_t *p, void *fp, cond_av_list_t **ret_list,
700
           cond_av_list_t *other)
701
0
{
702
0
  unsigned int i;
703
0
  int rc;
704
0
  uint32_t buf[1], len;
705
0
  struct cond_insertf_data data;
706
707
0
  *ret_list = NULL;
708
709
0
  rc = next_entry(buf, fp, sizeof(uint32_t));
710
0
  if (rc < 0)
711
0
    return -1;
712
713
0
  len = le32_to_cpu(buf[0]);
714
0
  if (len == 0) {
715
0
    return 0;
716
0
  }
717
718
0
  data.p = p;
719
0
  data.other = other;
720
0
  data.head = NULL;
721
0
  data.tail = NULL;
722
0
  for (i = 0; i < len; i++) {
723
0
    rc = avtab_read_item(fp, &p->te_cond_avtab, cond_insertf,
724
0
             &data);
725
0
    if (rc) {
726
0
      cond_av_list_destroy(data.head);
727
0
      return rc;
728
0
    }
729
0
  }
730
731
0
  *ret_list = data.head;
732
0
  return 0;
733
0
}
734
735
static int expr_isvalid(policydb_t *p, cond_expr_t *expr)
736
527
{
737
527
  if (expr->expr_type <= 0 || expr->expr_type > COND_LAST) {
738
48
    WARN(NULL,
739
48
         "security: conditional expressions uses unknown operator.");
740
48
    return 0;
741
48
  }
742
743
479
  if (expr->boolean > p->p_bools.nprim) {
744
4
    WARN(NULL,
745
4
         "security: conditional expressions uses unknown bool.");
746
4
    return 0;
747
4
  }
748
475
  return 1;
749
479
}
750
751
static int cond_read_node(policydb_t *p, cond_node_t *node, void *fp)
752
1.88k
{
753
1.88k
  uint32_t buf[2], i, len;
754
1.88k
  int rc;
755
1.88k
  cond_expr_t *expr = NULL, *last = NULL;
756
757
1.88k
  rc = next_entry(buf, fp, sizeof(uint32_t));
758
1.88k
  if (rc < 0)
759
66
    goto err;
760
761
1.81k
  node->cur_state = le32_to_cpu(buf[0]);
762
763
1.81k
  rc = next_entry(buf, fp, sizeof(uint32_t));
764
1.81k
  if (rc < 0)
765
5
    goto err;
766
767
  /* expr */
768
1.81k
  len = le32_to_cpu(buf[0]);
769
770
2.28k
  for (i = 0; i < len; i++) {
771
589
    rc = next_entry(buf, fp, sizeof(uint32_t) * 2);
772
589
    if (rc < 0)
773
62
      goto err;
774
775
527
    expr = malloc(sizeof(cond_expr_t));
776
527
    if (!expr) {
777
0
      goto err;
778
0
    }
779
527
    memset(expr, 0, sizeof(cond_expr_t));
780
781
527
    expr->expr_type = le32_to_cpu(buf[0]);
782
527
    expr->boolean = le32_to_cpu(buf[1]);
783
784
527
    if (!expr_isvalid(p, expr)) {
785
52
      free(expr);
786
52
      goto err;
787
52
    }
788
789
475
    if (i == 0) {
790
259
      node->expr = expr;
791
259
    } else {
792
216
      last->next = expr;
793
216
    }
794
475
    last = expr;
795
475
  }
796
797
1.70k
  if (p->policy_type == POLICY_KERN) {
798
0
    if (cond_read_av_list(p, fp, &node->true_list, NULL) != 0)
799
0
      goto err;
800
0
    if (cond_read_av_list(p, fp, &node->false_list,
801
0
              node->true_list) != 0)
802
0
      goto err;
803
1.70k
  } else {
804
1.70k
    if (avrule_read_list(p, &node->avtrue_list, fp))
805
70
      goto err;
806
1.63k
    if (avrule_read_list(p, &node->avfalse_list, fp))
807
11
      goto err;
808
1.63k
  }
809
810
1.61k
  if (p->policy_type != POLICY_KERN) {
811
1.61k
    rc = next_entry(buf, fp, sizeof(uint32_t));
812
1.61k
    if (rc < 0)
813
13
      goto err;
814
1.60k
    node->flags = le32_to_cpu(buf[0]);
815
1.60k
  }
816
817
1.60k
  return 0;
818
279
err:
819
279
  cond_node_destroy(node);
820
279
  free(node);
821
279
  return -1;
822
1.61k
}
823
824
int cond_read_list(policydb_t *p, cond_list_t **list, void *fp)
825
10.0k
{
826
10.0k
  cond_node_t *node, *last = NULL;
827
10.0k
  uint32_t buf[1], i, len;
828
10.0k
  int rc;
829
830
10.0k
  rc = next_entry(buf, fp, sizeof(uint32_t));
831
10.0k
  if (rc < 0)
832
6
    return -1;
833
834
10.0k
  len = le32_to_cpu(buf[0]);
835
836
10.0k
  rc = avtab_alloc(&p->te_cond_avtab, p->te_avtab.nel);
837
10.0k
  if (rc)
838
0
    goto err;
839
840
11.6k
  for (i = 0; i < len; i++) {
841
1.88k
    node = malloc(sizeof(cond_node_t));
842
1.88k
    if (!node)
843
0
      goto err;
844
1.88k
    memset(node, 0, sizeof(cond_node_t));
845
846
1.88k
    if (cond_read_node(p, node, fp) != 0)
847
279
      goto err;
848
849
1.60k
    if (i == 0) {
850
74
      *list = node;
851
1.53k
    } else {
852
1.53k
      last->next = node;
853
1.53k
    }
854
1.60k
    last = node;
855
1.60k
  }
856
9.77k
  return 0;
857
279
err:
858
279
  return -1;
859
10.0k
}
860
861
/* Determine whether additional permissions are granted by the conditional
862
 * av table, and if so, add them to the result 
863
 */
864
void cond_compute_av(avtab_t *ctab, avtab_key_t *key,
865
         struct sepol_av_decision *avd)
866
0
{
867
0
  avtab_ptr_t node;
868
869
0
  if (!ctab || !key || !avd)
870
0
    return;
871
872
0
  for (node = avtab_search_node(ctab, key); node != NULL;
873
0
       node = avtab_search_node_next(node, key->specified)) {
874
0
    if ((uint16_t)(AVTAB_ALLOWED | AVTAB_ENABLED) ==
875
0
        (node->key.specified & (AVTAB_ALLOWED | AVTAB_ENABLED)))
876
0
      avd->allowed |= node->datum.data;
877
0
    if ((uint16_t)(AVTAB_AUDITDENY | AVTAB_ENABLED) ==
878
0
        (node->key.specified & (AVTAB_AUDITDENY | AVTAB_ENABLED)))
879
      /* Since a '0' in an auditdeny mask represents a 
880
       * permission we do NOT want to audit (dontaudit), we use
881
       * the '&' operand to ensure that all '0's in the mask
882
       * are retained (much unlike the allow and auditallow cases).
883
       */
884
0
      avd->auditdeny &= node->datum.data;
885
0
    if ((uint16_t)(AVTAB_AUDITALLOW | AVTAB_ENABLED) ==
886
0
        (node->key.specified & (AVTAB_AUDITALLOW | AVTAB_ENABLED)))
887
0
      avd->auditallow |= node->datum.data;
888
0
  }
889
0
  return;
890
0
}
891
892
avtab_datum_t *cond_av_list_search(avtab_key_t *key, cond_av_list_t *cond_list)
893
0
{
894
0
  cond_av_list_t *cur_av;
895
896
0
  for (cur_av = cond_list; cur_av != NULL; cur_av = cur_av->next) {
897
0
    if (cur_av->node->key.source_type == key->source_type &&
898
0
        cur_av->node->key.target_type == key->target_type &&
899
0
        cur_av->node->key.target_class == key->target_class)
900
901
0
      return &cur_av->node->datum;
902
0
  }
903
0
  return NULL;
904
0
}