Coverage Report

Created: 2024-07-27 06:18

/src/selinux/libsepol/src/conditional.c
Line
Count
Source (jump to first uncovered line)
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
75
{
54
75
  cond_list_t *n;
55
56
75
  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
75
}
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,
176
          cond_node_t * needle, cond_node_t * haystack,
177
          int *was_created)
178
0
{
179
0
  while (haystack) {
180
0
    if (cond_expr_equal(needle, haystack)) {
181
0
      *was_created = 0;
182
0
      return haystack;
183
0
    }
184
0
    haystack = haystack->next;
185
0
  }
186
0
  *was_created = 1;
187
188
0
  return cond_node_create(p, needle);
189
0
}
190
191
/* return either a pre-existing matching node or create a new node */
192
cond_node_t *cond_node_search(policydb_t * p, cond_node_t * list,
193
            cond_node_t * cn)
194
0
{
195
0
  int was_created;
196
0
  cond_node_t *result = cond_node_find(p, cn, list, &was_created);
197
0
  if (result != NULL && was_created) {
198
    /* add conditional node to policy list */
199
0
    result->next = p->cond_list;
200
0
    p->cond_list = result;
201
0
  }
202
0
  return result;
203
0
}
204
205
/*
206
 * cond_evaluate_expr evaluates a conditional expr
207
 * in reverse polish notation. It returns true (1), false (0),
208
 * or undefined (-1). Undefined occurs when the expression
209
 * exceeds the stack depth of COND_EXPR_MAXDEPTH.
210
 */
211
int cond_evaluate_expr(policydb_t * p, cond_expr_t * expr)
212
0
{
213
214
0
  cond_expr_t *cur;
215
0
  int s[COND_EXPR_MAXDEPTH];
216
0
  int sp = -1;
217
218
0
  s[0] = -1;
219
220
0
  for (cur = expr; cur != NULL; cur = cur->next) {
221
0
    switch (cur->expr_type) {
222
0
    case COND_BOOL:
223
0
      if (sp == (COND_EXPR_MAXDEPTH - 1))
224
0
        return -1;
225
0
      sp++;
226
0
      s[sp] = p->bool_val_to_struct[cur->boolean - 1]->state;
227
0
      break;
228
0
    case COND_NOT:
229
0
      if (sp < 0)
230
0
        return -1;
231
0
      s[sp] = !s[sp];
232
0
      break;
233
0
    case COND_OR:
234
0
      if (sp < 1)
235
0
        return -1;
236
0
      sp--;
237
0
      s[sp] |= s[sp + 1];
238
0
      break;
239
0
    case COND_AND:
240
0
      if (sp < 1)
241
0
        return -1;
242
0
      sp--;
243
0
      s[sp] &= s[sp + 1];
244
0
      break;
245
0
    case COND_XOR:
246
0
      if (sp < 1)
247
0
        return -1;
248
0
      sp--;
249
0
      s[sp] ^= s[sp + 1];
250
0
      break;
251
0
    case COND_EQ:
252
0
      if (sp < 1)
253
0
        return -1;
254
0
      sp--;
255
0
      s[sp] = (s[sp] == s[sp + 1]);
256
0
      break;
257
0
    case COND_NEQ:
258
0
      if (sp < 1)
259
0
        return -1;
260
0
      sp--;
261
0
      s[sp] = (s[sp] != s[sp + 1]);
262
0
      break;
263
0
    default:
264
0
      return -1;
265
0
    }
266
0
  }
267
0
  return s[0];
268
0
}
269
270
cond_expr_t *cond_copy_expr(cond_expr_t * expr)
271
0
{
272
0
  cond_expr_t *cur, *head, *tail, *new_expr;
273
0
  tail = head = NULL;
274
0
  cur = expr;
275
0
  while (cur) {
276
0
    new_expr = (cond_expr_t *) malloc(sizeof(cond_expr_t));
277
0
    if (!new_expr)
278
0
      goto free_head;
279
0
    memset(new_expr, 0, sizeof(cond_expr_t));
280
281
0
    new_expr->expr_type = cur->expr_type;
282
0
    new_expr->boolean = cur->boolean;
283
284
0
    if (!head)
285
0
      head = new_expr;
286
0
    if (tail)
287
0
      tail->next = new_expr;
288
0
    tail = new_expr;
289
0
    cur = cur->next;
290
0
  }
291
0
  return head;
292
293
0
      free_head:
294
0
  while (head) {
295
0
    tail = head->next;
296
0
    free(head);
297
0
    head = tail;
298
0
  }
299
0
  return NULL;
300
0
}
301
302
/*
303
 * evaluate_cond_node evaluates the conditional stored in
304
 * a cond_node_t and if the result is different than the
305
 * current state of the node it sets the rules in the true/false
306
 * list appropriately. If the result of the expression is undefined
307
 * all of the rules are disabled for safety.
308
 */
309
static int evaluate_cond_node(policydb_t * p, cond_node_t * node)
310
0
{
311
0
  int new_state;
312
0
  cond_av_list_t *cur;
313
314
0
  new_state = cond_evaluate_expr(p, node->expr);
315
0
  if (new_state != node->cur_state) {
316
0
    node->cur_state = new_state;
317
0
    if (new_state == -1)
318
0
      WARN(NULL, "expression result was undefined - disabling all rules.");
319
    /* turn the rules on or off */
320
0
    for (cur = node->true_list; cur != NULL; cur = cur->next) {
321
0
      if (new_state <= 0) {
322
0
        cur->node->key.specified &= ~AVTAB_ENABLED;
323
0
      } else {
324
0
        cur->node->key.specified |= AVTAB_ENABLED;
325
0
      }
326
0
    }
327
328
0
    for (cur = node->false_list; cur != NULL; cur = cur->next) {
329
      /* -1 or 1 */
330
0
      if (new_state) {
331
0
        cur->node->key.specified &= ~AVTAB_ENABLED;
332
0
      } else {
333
0
        cur->node->key.specified |= AVTAB_ENABLED;
334
0
      }
335
0
    }
336
0
  }
337
0
  return 0;
338
0
}
339
340
/* precompute and simplify an expression if possible.  If left with !expression, change 
341
 * to expression and switch t and f. precompute expression for expressions with limited
342
 * number of bools.
343
 */
344
int cond_normalize_expr(policydb_t * p, cond_node_t * cn)
345
0
{
346
0
  cond_expr_t *ne, *e;
347
0
  cond_av_list_t *tmp;
348
0
  unsigned int i, j, orig_value[COND_MAX_BOOLS];
349
0
  int k;
350
0
  uint32_t test = 0x0;
351
0
  avrule_t *tmp2;
352
353
0
  cn->nbools = 0;
354
355
0
  memset(cn->bool_ids, 0, sizeof(cn->bool_ids));
356
0
  cn->expr_pre_comp = 0x0;
357
358
  /* take care of !expr case */
359
0
  ne = NULL;
360
0
  e = cn->expr;
361
362
  /* because it's RPN look at last element */
363
0
  while (e->next != NULL) {
364
0
    ne = e;
365
0
    e = e->next;
366
0
  }
367
0
  if (e->expr_type == COND_NOT) {
368
0
    if (ne) {
369
0
      ne->next = NULL;
370
0
    } else { /* ne should never be NULL */
371
0
      ERR(NULL, "Found expr with no bools and only a ! - this should never happen.");
372
0
      return -1;
373
0
    }
374
    /* swap the true and false lists */
375
0
    tmp = cn->true_list;
376
0
    cn->true_list = cn->false_list;
377
0
    cn->false_list = tmp;
378
0
    tmp2 = cn->avtrue_list;
379
0
    cn->avtrue_list = cn->avfalse_list;
380
0
    cn->avfalse_list = tmp2;
381
382
    /* free the "not" node in the list */
383
0
    free(e);
384
0
  }
385
386
  /* find all the bools in the expression */
387
0
  for (e = cn->expr; e != NULL; e = e->next) {
388
0
    switch (e->expr_type) {
389
0
    case COND_BOOL:
390
      /* see if we've already seen this bool */
391
0
      if (!bool_present(e->boolean, cn->bool_ids, 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]->state;
410
0
    }
411
412
    /* loop through all possible combinations of values for bools in expression */
413
0
    for (test = 0x0; test < (UINT32_C(1) << cn->nbools); test++) {
414
      /* temporarily set the value for all the bools in the
415
       * expression using the corr.  bit in test */
416
0
      for (j = 0; j < cn->nbools; j++) {
417
0
        p->bool_val_to_struct[cn->bool_ids[j] -
418
0
                  1]->state =
419
0
            (test & (UINT32_C(1) << j)) ? 1 : 0;
420
0
      }
421
0
      k = cond_evaluate_expr(p, cn->expr);
422
0
      if (k == -1) {
423
0
        ERR(NULL, "While testing expression, expression result "
424
0
             "was undefined - this should never happen.");
425
0
        return -1;
426
0
      }
427
      /* set the bit if expression evaluates true */
428
0
      if (k)
429
0
        cn->expr_pre_comp |= UINT32_C(1) << test;
430
0
    }
431
432
    /* restore bool default values */
433
0
    for (i = 0; i < cn->nbools; i++)
434
0
      p->bool_val_to_struct[cn->bool_ids[i] - 1]->state =
435
0
          orig_value[i];
436
0
  }
437
0
  return 0;
438
0
}
439
440
int evaluate_conds(policydb_t * p)
441
75
{
442
75
  int ret;
443
75
  cond_node_t *cur;
444
445
75
  for (cur = p->cond_list; cur != NULL; cur = cur->next) {
446
0
    ret = evaluate_cond_node(p, cur);
447
0
    if (ret)
448
0
      return ret;
449
0
  }
450
75
  return 0;
451
75
}
452
453
int cond_policydb_init(policydb_t * p)
454
12.1k
{
455
12.1k
  p->bool_val_to_struct = NULL;
456
12.1k
  p->cond_list = NULL;
457
12.1k
  if (avtab_init(&p->te_cond_avtab))
458
0
    return -1;
459
460
12.1k
  return 0;
461
12.1k
}
462
463
void cond_av_list_destroy(cond_av_list_t * list)
464
7.57k
{
465
7.57k
  cond_av_list_t *cur, *next;
466
14.5k
  for (cur = list; cur != NULL; cur = next) {
467
6.99k
    next = cur->next;
468
    /* the avtab_ptr_t node is destroy by the avtab */
469
6.99k
    free(cur);
470
6.99k
  }
471
7.57k
}
472
473
void cond_expr_destroy(cond_expr_t * expr)
474
3.48k
{
475
3.48k
  cond_expr_t *cur_expr, *next_expr;
476
477
3.48k
  if (!expr)
478
3.36k
    return;
479
480
16.9k
  for (cur_expr = expr; cur_expr != NULL; cur_expr = next_expr) {
481
16.7k
    next_expr = cur_expr->next;
482
16.7k
    free(cur_expr);
483
16.7k
  }
484
126
}
485
486
void cond_node_destroy(cond_node_t * node)
487
3.48k
{
488
3.48k
  if (!node)
489
0
    return;
490
491
3.48k
  cond_expr_destroy(node->expr);
492
3.48k
  avrule_list_destroy(node->avtrue_list);
493
3.48k
  avrule_list_destroy(node->avfalse_list);
494
3.48k
  cond_av_list_destroy(node->true_list);
495
3.48k
  cond_av_list_destroy(node->false_list);
496
3.48k
}
497
498
void cond_list_destroy(cond_list_t * list)
499
45.2k
{
500
45.2k
  cond_node_t *next, *cur;
501
502
45.2k
  if (list == NULL)
503
45.0k
    return;
504
505
2.69k
  for (cur = list; cur != NULL; cur = next) {
506
2.46k
    next = cur->next;
507
2.46k
    cond_node_destroy(cur);
508
2.46k
    free(cur);
509
2.46k
  }
510
233
}
511
512
void cond_policydb_destroy(policydb_t * p)
513
24.1k
{
514
24.1k
  if (p->bool_val_to_struct != NULL)
515
5.70k
    free(p->bool_val_to_struct);
516
24.1k
  avtab_destroy(&p->te_cond_avtab);
517
24.1k
  cond_list_destroy(p->cond_list);
518
24.1k
}
519
520
int cond_init_bool_indexes(policydb_t * p)
521
5.98k
{
522
5.98k
  if (p->bool_val_to_struct)
523
274
    free(p->bool_val_to_struct);
524
5.98k
  p->bool_val_to_struct = (cond_bool_datum_t **)
525
5.98k
      calloc(p->p_bools.nprim, sizeof(cond_bool_datum_t *));
526
5.98k
  if (!p->bool_val_to_struct)
527
0
    return -1;
528
5.98k
  return 0;
529
5.98k
}
530
531
int cond_destroy_bool(hashtab_key_t key, hashtab_datum_t datum, void *p
532
          __attribute__ ((unused)))
533
629
{
534
629
  if (key)
535
548
    free(key);
536
629
  free(datum);
537
629
  return 0;
538
629
}
539
540
int cond_index_bool(hashtab_key_t key, hashtab_datum_t datum, void *datap)
541
162
{
542
162
  policydb_t *p;
543
162
  cond_bool_datum_t *booldatum;
544
545
162
  booldatum = datum;
546
162
  p = datap;
547
548
162
  if (!booldatum->s.value || booldatum->s.value > p->p_bools.nprim)
549
44
    return -EINVAL;
550
551
118
  if (p->p_bool_val_to_name[booldatum->s.value - 1] != NULL)
552
2
    return -EINVAL;
553
554
116
  p->p_bool_val_to_name[booldatum->s.value - 1] = key;
555
116
  p->bool_val_to_struct[booldatum->s.value - 1] = booldatum;
556
557
116
  return 0;
558
118
}
559
560
static int bool_isvalid(cond_bool_datum_t * b)
561
604
{
562
604
  if (!(b->state == 0 || b->state == 1))
563
45
    return 0;
564
559
  return 1;
565
604
}
566
567
int cond_read_bool(policydb_t * p,
568
       hashtab_t h,
569
       struct policy_file *fp)
570
628
{
571
628
  char *key = 0;
572
628
  cond_bool_datum_t *booldatum;
573
628
  uint32_t buf[3], len;
574
628
  int rc;
575
576
628
  booldatum = malloc(sizeof(cond_bool_datum_t));
577
628
  if (!booldatum)
578
0
    return -1;
579
628
  memset(booldatum, 0, sizeof(cond_bool_datum_t));
580
581
628
  rc = next_entry(buf, fp, sizeof(uint32_t) * 3);
582
628
  if (rc < 0)
583
24
    goto err;
584
585
604
  booldatum->s.value = le32_to_cpu(buf[0]);
586
604
  booldatum->state = le32_to_cpu(buf[1]);
587
588
604
  if (!bool_isvalid(booldatum))
589
45
    goto err;
590
591
559
  len = le32_to_cpu(buf[2]);
592
559
  if (str_read(&key, fp, len))
593
12
    goto err;
594
595
547
  if (p->policy_type != POLICY_KERN &&
596
547
      p->policyvers >= MOD_POLICYDB_VERSION_TUNABLE_SEP) {
597
78
    rc = next_entry(buf, fp, sizeof(uint32_t));
598
78
    if (rc < 0)
599
2
      goto err;
600
76
    booldatum->flags = le32_to_cpu(buf[0]);
601
76
  }
602
603
545
  if (hashtab_insert(h, key, booldatum))
604
1
    goto err;
605
606
544
  return 0;
607
84
      err:
608
84
  cond_destroy_bool(key, booldatum, 0);
609
84
  return -1;
610
545
}
611
612
struct cond_insertf_data {
613
  struct policydb *p;
614
  cond_av_list_t *other;
615
  cond_av_list_t *head;
616
  cond_av_list_t *tail;
617
};
618
619
static int cond_insertf(avtab_t * a
620
      __attribute__ ((unused)), avtab_key_t * k,
621
      avtab_datum_t * d, void *ptr)
622
7.03k
{
623
7.03k
  struct cond_insertf_data *data = ptr;
624
7.03k
  struct policydb *p = data->p;
625
7.03k
  cond_av_list_t *other = data->other, *list, *cur;
626
7.03k
  avtab_ptr_t node_ptr;
627
7.03k
  uint8_t found;
628
629
  /*
630
   * For type rules we have to make certain there aren't any
631
   * conflicting rules by searching the te_avtab and the
632
   * cond_te_avtab.
633
   */
634
7.03k
  if (k->specified & AVTAB_TYPE) {
635
2.90k
    if (avtab_search(&p->te_avtab, k)) {
636
2
      WARN(NULL, "security: type rule already exists outside of a conditional.");
637
2
      return -1;
638
2
    }
639
    /*
640
     * If we are reading the false list other will be a pointer to
641
     * the true list. We can have duplicate entries if there is only
642
     * 1 other entry and it is in our true list.
643
     *
644
     * If we are reading the true list (other == NULL) there shouldn't
645
     * be any other entries.
646
     */
647
2.90k
    if (other) {
648
1.23k
      node_ptr = avtab_search_node(&p->te_cond_avtab, k);
649
1.23k
      if (node_ptr) {
650
389
        if (avtab_search_node_next
651
389
            (node_ptr, k->specified)) {
652
3
          ERR(NULL, "security: too many conflicting type rules.");
653
3
          return -1;
654
3
        }
655
386
        found = 0;
656
3.39k
        for (cur = other; cur != NULL; cur = cur->next) {
657
3.35k
          if (cur->node == node_ptr) {
658
352
            found = 1;
659
352
            break;
660
352
          }
661
3.35k
        }
662
386
        if (!found) {
663
34
          ERR(NULL, "security: conflicting type rules.");
664
34
          return -1;
665
34
        }
666
386
      }
667
1.66k
    } else {
668
1.66k
      if (avtab_search(&p->te_cond_avtab, k)) {
669
2
        ERR(NULL, "security: conflicting type rules when adding type rule for true.");
670
2
        return -1;
671
2
      }
672
1.66k
    }
673
2.90k
  }
674
675
6.99k
  node_ptr = avtab_insert_nonunique(&p->te_cond_avtab, k, d);
676
6.99k
  if (!node_ptr) {
677
0
    ERR(NULL, "security: could not insert rule.");
678
0
    return -1;
679
0
  }
680
6.99k
  node_ptr->parse_context = (void *)1;
681
682
6.99k
  list = malloc(sizeof(cond_av_list_t));
683
6.99k
  if (!list)
684
0
    return -1;
685
6.99k
  memset(list, 0, sizeof(cond_av_list_t));
686
687
6.99k
  list->node = node_ptr;
688
6.99k
  if (!data->head)
689
1.27k
    data->head = list;
690
5.72k
  else
691
5.72k
    data->tail->next = list;
692
6.99k
  data->tail = list;
693
6.99k
  return 0;
694
6.99k
}
695
696
static int cond_read_av_list(policydb_t * p, void *fp,
697
           cond_av_list_t ** ret_list, cond_av_list_t * other)
698
4.10k
{
699
4.10k
  unsigned int i;
700
4.10k
  int rc;
701
4.10k
  uint32_t buf[1], len;
702
4.10k
  struct cond_insertf_data data;
703
704
4.10k
  *ret_list = NULL;
705
706
4.10k
  rc = next_entry(buf, fp, sizeof(uint32_t));
707
4.10k
  if (rc < 0)
708
71
    return -1;
709
710
4.03k
  len = le32_to_cpu(buf[0]);
711
4.03k
  if (len == 0) {
712
2.67k
    return 0;
713
2.67k
  }
714
715
1.35k
  data.p = p;
716
1.35k
  data.other = other;
717
1.35k
  data.head = NULL;
718
1.35k
  data.tail = NULL;
719
5.52k
  for (i = 0; i < len; i++) {
720
4.76k
    rc = avtab_read_item(fp, p->policyvers, &p->te_cond_avtab,
721
4.76k
             cond_insertf, &data);
722
4.76k
    if (rc) {
723
594
      cond_av_list_destroy(data.head);
724
594
      return rc;
725
594
    }
726
727
4.76k
  }
728
729
762
  *ret_list = data.head;
730
762
  return 0;
731
1.35k
}
732
733
static int expr_isvalid(policydb_t * p, cond_expr_t * expr)
734
16.8k
{
735
16.8k
  if (expr->expr_type <= 0 || expr->expr_type > COND_LAST) {
736
52
    WARN(NULL, "security: conditional expressions uses unknown operator.");
737
52
    return 0;
738
52
  }
739
740
16.8k
  if (expr->boolean > p->p_bools.nprim) {
741
44
    WARN(NULL, "security: conditional expressions uses unknown bool.");
742
44
    return 0;
743
44
  }
744
16.7k
  return 1;
745
16.8k
}
746
747
static int cond_read_node(policydb_t * p, cond_node_t * node, void *fp)
748
3.48k
{
749
3.48k
  uint32_t buf[2], i, len;
750
3.48k
  int rc;
751
3.48k
  cond_expr_t *expr = NULL, *last = NULL;
752
753
3.48k
  rc = next_entry(buf, fp, sizeof(uint32_t));
754
3.48k
  if (rc < 0)
755
128
    goto err;
756
757
3.36k
  node->cur_state = le32_to_cpu(buf[0]);
758
759
3.36k
  rc = next_entry(buf, fp, sizeof(uint32_t));
760
3.36k
  if (rc < 0)
761
6
    goto err;
762
763
  /* expr */
764
3.35k
  len = le32_to_cpu(buf[0]);
765
766
20.1k
  for (i = 0; i < len; i++) {
767
16.9k
    rc = next_entry(buf, fp, sizeof(uint32_t) * 2);
768
16.9k
    if (rc < 0)
769
61
      goto err;
770
771
16.8k
    expr = malloc(sizeof(cond_expr_t));
772
16.8k
    if (!expr) {
773
0
      goto err;
774
0
    }
775
16.8k
    memset(expr, 0, sizeof(cond_expr_t));
776
777
16.8k
    expr->expr_type = le32_to_cpu(buf[0]);
778
16.8k
    expr->boolean = le32_to_cpu(buf[1]);
779
780
16.8k
    if (!expr_isvalid(p, expr)) {
781
96
      free(expr);
782
96
      goto err;
783
96
    }
784
785
16.7k
    if (i == 0) {
786
126
      node->expr = expr;
787
16.6k
    } else {
788
16.6k
      last->next = expr;
789
16.6k
    }
790
16.7k
    last = expr;
791
16.7k
  }
792
793
3.19k
  if (p->policy_type == POLICY_KERN) {
794
2.21k
    if (cond_read_av_list(p, fp, &node->true_list, NULL) != 0)
795
323
      goto err;
796
1.88k
    if (cond_read_av_list(p, fp, &node->false_list, node->true_list)
797
1.88k
        != 0)
798
342
      goto err;
799
1.88k
  } else {
800
985
    if (avrule_read_list(p, &node->avtrue_list, fp))
801
56
      goto err;
802
929
    if (avrule_read_list(p, &node->avfalse_list, fp))
803
8
      goto err;
804
929
  }
805
806
2.46k
  if (p->policy_type != POLICY_KERN &&
807
2.46k
      p->policyvers >= MOD_POLICYDB_VERSION_TUNABLE_SEP) {
808
224
    rc = next_entry(buf, fp, sizeof(uint32_t));
809
224
    if (rc < 0)
810
5
      goto err;
811
219
    node->flags = le32_to_cpu(buf[0]);
812
219
  }
813
814
2.46k
  return 0;
815
1.02k
      err:
816
1.02k
  cond_node_destroy(node);
817
1.02k
  free(node);
818
1.02k
  return -1;
819
2.46k
}
820
821
int cond_read_list(policydb_t * p, cond_list_t ** list, void *fp)
822
13.8k
{
823
13.8k
  cond_node_t *node, *last = NULL;
824
13.8k
  uint32_t buf[1], i, len;
825
13.8k
  int rc;
826
827
13.8k
  rc = next_entry(buf, fp, sizeof(uint32_t));
828
13.8k
  if (rc < 0)
829
40
    return -1;
830
831
13.7k
  len = le32_to_cpu(buf[0]);
832
833
13.7k
  rc = avtab_alloc(&p->te_cond_avtab, p->te_avtab.nel);
834
13.7k
  if (rc)
835
0
    goto err;
836
837
16.2k
  for (i = 0; i < len; i++) {
838
3.48k
    node = malloc(sizeof(cond_node_t));
839
3.48k
    if (!node)
840
0
      goto err;
841
3.48k
    memset(node, 0, sizeof(cond_node_t));
842
843
3.48k
    if (cond_read_node(p, node, fp) != 0)
844
1.02k
      goto err;
845
846
2.46k
    if (i == 0) {
847
235
      *list = node;
848
2.22k
    } else {
849
2.22k
      last->next = node;
850
2.22k
    }
851
2.46k
    last = node;
852
2.46k
  }
853
12.7k
  return 0;
854
1.02k
      err:
855
1.02k
  return -1;
856
13.7k
}
857
858
/* Determine whether additional permissions are granted by the conditional
859
 * av table, and if so, add them to the result 
860
 */
861
void cond_compute_av(avtab_t * ctab, avtab_key_t * key,
862
         struct sepol_av_decision *avd)
863
0
{
864
0
  avtab_ptr_t node;
865
866
0
  if (!ctab || !key || !avd)
867
0
    return;
868
869
0
  for (node = avtab_search_node(ctab, key); node != NULL;
870
0
       node = avtab_search_node_next(node, key->specified)) {
871
0
    if ((uint16_t) (AVTAB_ALLOWED | AVTAB_ENABLED) ==
872
0
        (node->key.specified & (AVTAB_ALLOWED | AVTAB_ENABLED)))
873
0
      avd->allowed |= node->datum.data;
874
0
    if ((uint16_t) (AVTAB_AUDITDENY | AVTAB_ENABLED) ==
875
0
        (node->key.specified & (AVTAB_AUDITDENY | AVTAB_ENABLED)))
876
      /* Since a '0' in an auditdeny mask represents a 
877
       * permission we do NOT want to audit (dontaudit), we use
878
       * the '&' operand to ensure that all '0's in the mask
879
       * are retained (much unlike the allow and auditallow cases).
880
       */
881
0
      avd->auditdeny &= node->datum.data;
882
0
    if ((uint16_t) (AVTAB_AUDITALLOW | AVTAB_ENABLED) ==
883
0
        (node->key.specified & (AVTAB_AUDITALLOW | AVTAB_ENABLED)))
884
0
      avd->auditallow |= node->datum.data;
885
0
  }
886
0
  return;
887
0
}
888
889
avtab_datum_t *cond_av_list_search(avtab_key_t * key,
890
           cond_av_list_t * cond_list)
891
0
{
892
893
0
  cond_av_list_t *cur_av;
894
895
0
  for (cur_av = cond_list; cur_av != NULL; cur_av = cur_av->next) {
896
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
903
0
  }
904
0
  return NULL;
905
906
0
}