Coverage Report

Created: 2026-08-31 06:40

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/selinux/checkpolicy/module_compiler.c
Line
Count
Source
1
/* Author : Joshua Brindle <jbrindle@tresys.com>
2
 *      Karl MacMillan <kmacmillan@tresys.com>
3
 *          Jason Tang     <jtang@tresys.com>
4
 *  Added support for binary policy modules
5
 *
6
 * Copyright (C) 2004 - 2005 Tresys Technology, LLC
7
 *  This program is free software; you can redistribute it and/or modify
8
 *    it under the terms of the GNU General Public License as published by
9
 *  the Free Software Foundation, version 2.
10
 */
11
12
#include <assert.h>
13
#include <stdarg.h>
14
#include <stdlib.h>
15
#include <string.h>
16
17
#include <sepol/policydb/policydb.h>
18
#include <sepol/policydb/avrule_block.h>
19
#include <sepol/policydb/conditional.h>
20
21
#include "queue.h"
22
#include "module_compiler.h"
23
24
typedef struct scope_stack {
25
  int type; /* 1 = avrule block, 2 = conditional */
26
  avrule_decl_t *decl; /* if in an avrule block, which
27
         * declaration is current */
28
  avrule_t *last_avrule;
29
  int in_else; /* if in an avrule block, within ELSE branch */
30
  int require_given; /* 1 if this block had at least one require */
31
  struct scope_stack *parent;
32
} scope_stack_t;
33
34
extern policydb_t *policydbp;
35
extern queue_t id_queue;
36
extern int yyerror(const char *msg);
37
__attribute__((format(printf, 1, 2))) extern void yyerror2(const char *fmt,
38
                 ...);
39
40
static int push_stack(int stack_type, ...);
41
static void pop_stack(void);
42
43
/* keep track of the last item added to the stack */
44
static scope_stack_t *stack_top = NULL;
45
static avrule_block_t *last_block;
46
static uint32_t next_decl_id = 1;
47
48
static const char *const flavor_str[SYM_NUM] = {
49
  [SYM_COMMONS] = "common", [SYM_CLASSES] = "class", [SYM_ROLES] = "role",
50
  [SYM_TYPES] = "type",   [SYM_USERS] = "user",    [SYM_BOOLS] = "bool",
51
  [SYM_LEVELS] = "level",   [SYM_CATS] = "cat"
52
};
53
54
static void print_error_msg(int ret, uint32_t symbol_type)
55
18
{
56
18
  switch (ret) {
57
0
  case -3:
58
0
    yyerror("Out of memory!");
59
0
    break;
60
8
  case -2:
61
8
    yyerror2("Duplicate declaration of %s",
62
8
       flavor_str[symbol_type]);
63
8
    break;
64
10
  case -1:
65
10
    yyerror2("Could not declare %s here", flavor_str[symbol_type]);
66
10
    break;
67
0
  default:
68
0
    yyerror2("Unknown error %d", ret);
69
18
  }
70
18
}
71
72
int define_policy(int pass, int module_header_given)
73
13.3k
{
74
13.3k
  char *id;
75
76
13.3k
  if (module_header_given) {
77
2
    if (policydbp->policy_type != POLICY_MOD) {
78
2
      yyerror("Module specification found while not building a policy module.");
79
2
      return -1;
80
2
    }
81
82
0
    if (pass == 2) {
83
0
      while ((id = queue_remove(id_queue)) != NULL)
84
0
        free(id);
85
0
    } else {
86
0
      id = (char *)queue_remove(id_queue);
87
0
      if (!id) {
88
0
        yyerror("no module name");
89
0
        return -1;
90
0
      }
91
0
      free(policydbp->name);
92
0
      policydbp->name = id;
93
0
      if ((policydbp->version = queue_remove(id_queue)) ==
94
0
          NULL) {
95
0
        yyerror("Expected a module version but none was found.");
96
0
        return -1;
97
0
      }
98
0
    }
99
13.3k
  } else {
100
13.3k
    if (policydbp->policy_type == POLICY_MOD) {
101
0
      yyerror("Building a policy module, but no module specification found.");
102
0
      return -1;
103
0
    }
104
13.3k
  }
105
  /* the first declaration within the global avrule
106
     block will always have an id of 1 */
107
13.3k
  next_decl_id = 2;
108
109
  /* reset the scoping stack */
110
18.3k
  while (stack_top != NULL) {
111
5.06k
    pop_stack();
112
5.06k
  }
113
13.3k
  if (push_stack(1, policydbp->global, policydbp->global->branch_list) ==
114
13.3k
      -1) {
115
0
    return -1;
116
0
  }
117
13.3k
  last_block = policydbp->global;
118
13.3k
  return 0;
119
13.3k
}
120
121
/* Given the current parse stack, returns 1 if a declaration or require would
122
 * be allowed here or 0 if not.  For example, declarations and requirements are
123
 * not allowed in conditionals, so if there are any conditionals in the
124
 * current scope stack then this would return a 0.
125
 */
126
static int is_creation_allowed(void)
127
432k
{
128
432k
  if (stack_top->type != 1 || stack_top->in_else) {
129
12
    return 0;
130
12
  }
131
432k
  return 1;
132
432k
}
133
134
/* Attempt to declare or require a symbol within the current scope.
135
 * Returns:
136
 *  0: Success - Symbol had not been previously created.
137
 *  1: Success - Symbol had already been created and caller must free datum.
138
 * -1: Failure - Symbol cannot be created here
139
 * -2: Failure - Duplicate declaration or type/attribute mismatch
140
 * -3: Failure - Out of memory or some other error
141
 */
142
static int create_symbol(uint32_t symbol_type, hashtab_key_t key,
143
       hashtab_datum_t datum, uint32_t *dest_value,
144
       uint32_t scope)
145
432k
{
146
432k
  avrule_decl_t *decl = stack_top->decl;
147
432k
  int ret;
148
149
432k
  if (!is_creation_allowed()) {
150
12
    return -1;
151
12
  }
152
153
432k
  ret = symtab_insert(policydbp, symbol_type, key, datum, scope,
154
432k
          decl->decl_id, dest_value);
155
156
432k
  if (ret == 1 && dest_value) {
157
315k
    hashtab_datum_t s = hashtab_search(
158
315k
      policydbp->symtab[symbol_type].table, key);
159
315k
    assert(s != NULL);
160
161
315k
    if (symbol_type == SYM_LEVELS) {
162
7.57k
      *dest_value = ((level_datum_t *)s)->level->sens;
163
308k
    } else {
164
308k
      *dest_value = ((symtab_datum_t *)s)->value;
165
308k
    }
166
315k
  } else if (ret == -2) {
167
22
    return -2;
168
116k
  } else if (ret < 0) {
169
0
    return -3;
170
0
  }
171
172
432k
  return ret;
173
432k
}
174
175
/* Attempt to declare a symbol within the current declaration.  If
176
 * currently within a non-conditional and in a non-else branch then
177
 * insert the symbol, return 0 on success if symbol was undeclared.
178
 * For roles and users, it is legal to have multiple declarations; as
179
 * such return 1 to indicate that caller must free() the datum because
180
 * it was not added.  If symbols may not be declared here return -1.
181
 * For duplicate declarations return -2.  For all else, including out
182
 * of memory, return -3.  Note that dest_value and datum_value might
183
 * not be restricted pointers. */
184
int declare_symbol(uint32_t symbol_type, hashtab_key_t key,
185
       hashtab_datum_t datum, uint32_t *dest_value,
186
       const uint32_t *datum_value)
187
147k
{
188
147k
  avrule_decl_t *decl = stack_top->decl;
189
147k
  int ret =
190
147k
    create_symbol(symbol_type, key, datum, dest_value, SCOPE_DECL);
191
192
147k
  if (ret < 0) {
193
27
    return ret;
194
27
  }
195
196
147k
  if (ebitmap_set_bit(decl->declared.scope + symbol_type,
197
147k
          *datum_value - 1, 1)) {
198
0
    return -3;
199
0
  }
200
201
147k
  return ret;
202
147k
}
203
204
static int role_implicit_bounds(hashtab_t roles_tab, char *role_id,
205
        role_datum_t *role)
206
51.0k
{
207
51.0k
  role_datum_t *bounds;
208
51.0k
  char *bounds_id, *delim;
209
210
51.0k
  delim = strrchr(role_id, '.');
211
51.0k
  if (!delim)
212
49.4k
    return 0; /* no implicit boundary */
213
214
1.52k
  bounds_id = strdup(role_id);
215
1.52k
  if (!bounds_id) {
216
0
    yyerror("out of memory");
217
0
    return -1;
218
0
  }
219
1.52k
  bounds_id[(size_t)(delim - role_id)] = '\0';
220
221
1.52k
  bounds = hashtab_search(roles_tab, bounds_id);
222
1.52k
  if (!bounds) {
223
2
    yyerror2(
224
2
      "Implicit role bounds declared (%s), but the parent (%s) was not found in the same scope",
225
2
      role_id, bounds_id);
226
2
    free(bounds_id);
227
2
    return -1;
228
2
  }
229
230
1.52k
  role->bounds = bounds->s.value;
231
232
1.52k
  free(bounds_id);
233
234
1.52k
  return 0;
235
1.52k
}
236
237
static int create_role(uint32_t scope, unsigned char isattr,
238
           role_datum_t **role, char **key)
239
198k
{
240
198k
  char *id = queue_remove(id_queue);
241
198k
  role_datum_t *datum = NULL;
242
198k
  int ret;
243
198k
  uint32_t value;
244
245
198k
  *role = NULL;
246
198k
  *key = NULL;
247
198k
  isattr = isattr ? ROLE_ATTRIB : ROLE_ROLE;
248
249
198k
  if (id == NULL) {
250
1
    yyerror("no role name");
251
1
    return -1;
252
1
  }
253
254
198k
  datum = malloc(sizeof(*datum));
255
198k
  if (datum == NULL) {
256
0
    yyerror("Out of memory!");
257
0
    free(id);
258
0
    return -1;
259
0
  }
260
261
198k
  role_datum_init(datum);
262
198k
  datum->flavor = isattr;
263
264
198k
  if (scope == SCOPE_DECL) {
265
117k
    ret = declare_symbol(SYM_ROLES, id, datum, &value, &value);
266
117k
  } else {
267
81.1k
    ret = require_symbol(SYM_ROLES, id, datum, &value, &value);
268
81.1k
  }
269
270
198k
  if (ret == 0) {
271
47.4k
    datum->s.value = value;
272
47.4k
    *role = datum;
273
47.4k
    *key = strdup(id);
274
47.4k
    if (*key == NULL) {
275
0
      yyerror("Out of memory!");
276
0
      return -1;
277
0
    }
278
151k
  } else if (ret == 1) {
279
151k
    *role = hashtab_search(policydbp->symtab[SYM_ROLES].table, id);
280
151k
    if (*role && (isattr != (*role)->flavor)) {
281
1
      yyerror2(
282
1
        "Identifier %s used as both an attribute and a role",
283
1
        id);
284
1
      *role = NULL;
285
1
      free(id);
286
1
      role_datum_destroy(datum);
287
1
      free(datum);
288
1
      return -1;
289
1
    }
290
151k
    datum->s.value = value;
291
151k
    *role = datum;
292
151k
    *key = id;
293
151k
  } else {
294
4
    print_error_msg(ret, SYM_ROLES);
295
4
    free(id);
296
4
    role_datum_destroy(datum);
297
4
    free(datum);
298
4
  }
299
300
198k
  return ret;
301
198k
}
302
303
role_datum_t *declare_role(unsigned char isattr)
304
117k
{
305
117k
  char *key = NULL;
306
117k
  role_datum_t *role = NULL;
307
117k
  role_datum_t *dest_role = NULL;
308
117k
  hashtab_t roles_tab;
309
117k
  int ret, ret2;
310
311
117k
  ret = create_role(SCOPE_DECL, isattr, &role, &key);
312
117k
  if (ret < 0) {
313
3
    return NULL;
314
3
  }
315
316
  /* create a new role_datum_t for this decl, if necessary */
317
117k
  assert(stack_top->type == 1);
318
319
117k
  if (stack_top->parent == NULL) {
320
    /* in parent, so use global symbol table */
321
60.0k
    roles_tab = policydbp->p_roles.table;
322
60.0k
  } else {
323
57.3k
    roles_tab = stack_top->decl->p_roles.table;
324
57.3k
  }
325
326
117k
  dest_role = hashtab_search(roles_tab, key);
327
117k
  if (dest_role == NULL) {
328
51.0k
    if (ret == 0) {
329
9.11k
      dest_role = malloc(sizeof(*dest_role));
330
9.11k
      if (dest_role == NULL) {
331
0
        yyerror("Out of memory!");
332
0
        free(key);
333
0
        return NULL;
334
0
      }
335
9.11k
      role_datum_init(dest_role);
336
9.11k
      dest_role->s.value = role->s.value;
337
9.11k
      dest_role->flavor = role->flavor;
338
41.8k
    } else {
339
41.8k
      dest_role = role;
340
41.8k
    }
341
51.0k
    ret2 = role_implicit_bounds(roles_tab, key, dest_role);
342
51.0k
    if (ret2 != 0) {
343
2
      free(key);
344
2
      role_datum_destroy(dest_role);
345
2
      free(dest_role);
346
2
      return NULL;
347
2
    }
348
51.0k
    ret2 = hashtab_insert(roles_tab, key, dest_role);
349
51.0k
    if (ret2 != 0) {
350
0
      yyerror("Out of memory!");
351
0
      free(key);
352
0
      role_datum_destroy(dest_role);
353
0
      free(dest_role);
354
0
      return NULL;
355
0
    }
356
66.4k
  } else {
357
66.4k
    free(key);
358
66.4k
    if (ret == 1) {
359
36.5k
      role_datum_destroy(role);
360
36.5k
      free(role);
361
36.5k
    }
362
66.4k
  }
363
364
117k
  if (ret == 0) {
365
38.9k
    ret2 = ebitmap_set_bit(&dest_role->dominates,
366
38.9k
               dest_role->s.value - 1, 1);
367
38.9k
    if (ret2 != 0) {
368
0
      yyerror("out of memory");
369
0
      return NULL;
370
0
    }
371
38.9k
  }
372
373
117k
  return dest_role;
374
117k
}
375
376
static int create_type(uint32_t scope, unsigned char isattr,
377
           type_datum_t **type)
378
69.7k
{
379
69.7k
  char *id;
380
69.7k
  type_datum_t *datum;
381
69.7k
  int ret;
382
69.7k
  uint32_t value = 0;
383
384
69.7k
  *type = NULL;
385
69.7k
  isattr = isattr ? TYPE_ATTRIB : TYPE_TYPE;
386
387
69.7k
  id = (char *)queue_remove(id_queue);
388
69.7k
  if (!id) {
389
1
    yyerror("no type/attribute name?");
390
1
    return -1;
391
1
  }
392
69.7k
  if (strcmp(id, "self") == 0) {
393
3
    yyerror("\"self\" is a reserved type name.");
394
3
    free(id);
395
3
    return -1;
396
3
  }
397
398
69.6k
  datum = malloc(sizeof(*datum));
399
69.6k
  if (!datum) {
400
0
    yyerror("Out of memory!");
401
0
    free(id);
402
0
    return -1;
403
0
  }
404
69.6k
  type_datum_init(datum);
405
69.6k
  datum->primary = 1;
406
69.6k
  datum->flavor = isattr;
407
408
69.6k
  if (scope == SCOPE_DECL) {
409
3.01k
    ret = declare_symbol(SYM_TYPES, id, datum, &value, &value);
410
66.6k
  } else {
411
66.6k
    ret = require_symbol(SYM_TYPES, id, datum, &value, &value);
412
66.6k
  }
413
414
69.6k
  if (ret == 0) {
415
21.7k
    datum->s.value = value;
416
21.7k
    *type = datum;
417
47.9k
  } else if (ret == 1) {
418
47.9k
    type_datum_destroy(datum);
419
47.9k
    free(datum);
420
47.9k
    *type = hashtab_search(policydbp->symtab[SYM_TYPES].table, id);
421
47.9k
    if (*type && (isattr != (*type)->flavor)) {
422
4
      yyerror2(
423
4
        "Identifier %s used as both an attribute and a type",
424
4
        id);
425
4
      *type = NULL;
426
4
      free(id);
427
4
      return -1;
428
4
    }
429
47.9k
    free(id);
430
47.9k
  } else {
431
8
    print_error_msg(ret, SYM_TYPES);
432
8
    free(id);
433
8
    type_datum_destroy(datum);
434
8
    free(datum);
435
8
  }
436
437
69.6k
  return ret;
438
69.6k
}
439
440
type_datum_t *declare_type(unsigned char primary, unsigned char isattr)
441
3.01k
{
442
3.01k
  type_datum_t *type = NULL;
443
3.01k
  int ret = create_type(SCOPE_DECL, isattr, &type);
444
445
3.01k
  if (ret == 0) {
446
2.97k
    type->primary = primary;
447
2.97k
  }
448
449
3.01k
  return type;
450
3.01k
}
451
452
static int user_implicit_bounds(hashtab_t users_tab, char *user_id,
453
        user_datum_t *user)
454
3.47k
{
455
3.47k
  user_datum_t *bounds;
456
3.47k
  char *bounds_id, *delim;
457
458
3.47k
  delim = strrchr(user_id, '.');
459
3.47k
  if (!delim)
460
3.17k
    return 0; /* no implicit boundary */
461
462
306
  bounds_id = strdup(user_id);
463
306
  if (!bounds_id) {
464
0
    yyerror("out of memory");
465
0
    return -1;
466
0
  }
467
306
  bounds_id[(size_t)(delim - user_id)] = '\0';
468
469
306
  bounds = hashtab_search(users_tab, bounds_id);
470
306
  if (!bounds) {
471
4
    yyerror2(
472
4
      "Implicit user bounds declared (%s), but the parent (%s) was not found in the same scope",
473
4
      user_id, bounds_id);
474
4
    free(bounds_id);
475
4
    return -1;
476
4
  }
477
478
302
  user->bounds = bounds->s.value;
479
480
302
  free(bounds_id);
481
482
302
  return 0;
483
306
}
484
485
static int create_user(uint32_t scope, user_datum_t **user, char **key)
486
17.4k
{
487
17.4k
  char *id = queue_remove(id_queue);
488
17.4k
  user_datum_t *datum = NULL;
489
17.4k
  int ret;
490
17.4k
  uint32_t value;
491
492
17.4k
  *user = NULL;
493
17.4k
  *key = NULL;
494
495
17.4k
  if (id == NULL) {
496
1
    yyerror("no user name");
497
1
    return -1;
498
1
  }
499
500
17.3k
  datum = malloc(sizeof(*datum));
501
17.3k
  if (datum == NULL) {
502
0
    yyerror("Out of memory!");
503
0
    free(id);
504
0
    return -1;
505
0
  }
506
507
17.3k
  user_datum_init(datum);
508
509
17.3k
  if (scope == SCOPE_DECL) {
510
9.45k
    ret = declare_symbol(SYM_USERS, id, datum, &value, &value);
511
9.45k
  } else {
512
7.94k
    ret = require_symbol(SYM_USERS, id, datum, &value, &value);
513
7.94k
  }
514
515
17.3k
  if (ret == 0) {
516
8.96k
    datum->s.value = value;
517
8.96k
    *user = datum;
518
8.96k
    *key = strdup(id);
519
8.96k
    if (*key == NULL) {
520
0
      yyerror("Out of memory!");
521
0
      return -1;
522
0
    }
523
8.96k
  } else if (ret == 1) {
524
8.43k
    datum->s.value = value;
525
8.43k
    *user = datum;
526
8.43k
    *key = id;
527
8.43k
  } else {
528
2
    print_error_msg(ret, SYM_USERS);
529
2
    free(id);
530
2
    user_datum_destroy(datum);
531
2
    free(datum);
532
2
  }
533
534
17.3k
  return ret;
535
17.3k
}
536
537
user_datum_t *declare_user(void)
538
9.45k
{
539
9.45k
  char *key = NULL;
540
9.45k
  user_datum_t *user = NULL;
541
9.45k
  user_datum_t *dest_user = NULL;
542
9.45k
  hashtab_t users_tab;
543
9.45k
  int ret, ret2;
544
545
9.45k
  ret = create_user(SCOPE_DECL, &user, &key);
546
9.45k
  if (ret < 0) {
547
1
    return NULL;
548
1
  }
549
550
  /* create a new user_datum_t for this decl, if necessary */
551
9.45k
  assert(stack_top->type == 1);
552
553
9.45k
  if (stack_top->parent == NULL) {
554
    /* in parent, so use global symbol table */
555
4.97k
    users_tab = policydbp->p_users.table;
556
4.97k
  } else {
557
4.48k
    users_tab = stack_top->decl->p_users.table;
558
4.48k
  }
559
560
9.45k
  dest_user = hashtab_search(users_tab, key);
561
9.45k
  if (dest_user == NULL) {
562
3.47k
    if (ret == 0) {
563
1.15k
      dest_user = malloc(sizeof(*dest_user));
564
1.15k
      if (dest_user == NULL) {
565
0
        yyerror("Out of memory!");
566
0
        free(key);
567
0
        return NULL;
568
0
      }
569
1.15k
      user_datum_init(dest_user);
570
1.15k
      dest_user->s.value = user->s.value;
571
2.32k
    } else {
572
2.32k
      dest_user = user;
573
2.32k
    }
574
3.47k
    ret2 = user_implicit_bounds(users_tab, key, dest_user);
575
3.47k
    if (ret2 != 0) {
576
4
      free(key);
577
4
      user_datum_destroy(dest_user);
578
4
      free(dest_user);
579
4
      return NULL;
580
4
    }
581
3.47k
    ret2 = hashtab_insert(users_tab, key, dest_user);
582
3.47k
    if (ret2 != 0) {
583
0
      yyerror("Out of memory!");
584
0
      free(key);
585
0
      user_datum_destroy(dest_user);
586
0
      free(dest_user);
587
0
      return NULL;
588
0
    }
589
5.98k
  } else {
590
5.98k
    free(key);
591
5.98k
    if (ret == 1) {
592
1.93k
      user_datum_destroy(user);
593
1.93k
      free(user);
594
1.93k
    }
595
5.98k
  }
596
597
9.45k
  return dest_user;
598
9.45k
}
599
600
/* Return a type_datum_t for the local avrule_decl with the given ID.
601
 * If it does not exist, create one with the same value as 'value'.
602
 * This function assumes that the ID is within scope.  c.f.,
603
 * is_id_in_scope().
604
 *
605
 * NOTE: this function usurps ownership of id afterwards.  The caller
606
 * shall not reference it nor free() it afterwards.
607
 */
608
type_datum_t *get_local_type(char *id, uint32_t value, unsigned char isattr)
609
3.42k
{
610
3.42k
  type_datum_t *dest_typdatum;
611
3.42k
  hashtab_t types_tab;
612
3.42k
  assert(stack_top->type == 1);
613
3.42k
  if (stack_top->parent == NULL) {
614
    /* in global, so use global symbol table */
615
547
    types_tab = policydbp->p_types.table;
616
2.87k
  } else {
617
2.87k
    types_tab = stack_top->decl->p_types.table;
618
2.87k
  }
619
3.42k
  dest_typdatum = hashtab_search(types_tab, id);
620
3.42k
  if (!dest_typdatum) {
621
2.42k
    dest_typdatum = (type_datum_t *)malloc(sizeof(type_datum_t));
622
2.42k
    if (dest_typdatum == NULL) {
623
0
      free(id);
624
0
      return NULL;
625
0
    }
626
2.42k
    type_datum_init(dest_typdatum);
627
2.42k
    dest_typdatum->s.value = value;
628
2.42k
    dest_typdatum->flavor = isattr ? TYPE_ATTRIB : TYPE_TYPE;
629
2.42k
    dest_typdatum->primary = 1;
630
2.42k
    if (hashtab_insert(types_tab, id, dest_typdatum)) {
631
0
      free(id);
632
0
      type_datum_destroy(dest_typdatum);
633
0
      free(dest_typdatum);
634
0
      return NULL;
635
0
    }
636
637
2.42k
  } else {
638
1.00k
    free(id);
639
1.00k
    if (dest_typdatum->flavor !=
640
1.00k
        (isattr ? TYPE_ATTRIB : TYPE_TYPE)) {
641
0
      return NULL;
642
0
    }
643
1.00k
  }
644
3.42k
  return dest_typdatum;
645
3.42k
}
646
647
/* Return a role_datum_t for the local avrule_decl with the given ID.
648
 * If it does not exist, create one with the same value as 'value'.
649
 * This function assumes that the ID is within scope.  c.f.,
650
 * is_id_in_scope().
651
 *
652
 * NOTE: this function usurps ownership of id afterwards.  The caller
653
 * shall not reference it nor free() it afterwards.
654
 */
655
role_datum_t *get_local_role(char *id, uint32_t value, unsigned char isattr)
656
21.3k
{
657
21.3k
  role_datum_t *dest_roledatum;
658
21.3k
  hashtab_t roles_tab;
659
660
21.3k
  assert(stack_top->type == 1);
661
662
21.3k
  if (stack_top->parent == NULL) {
663
    /* in global, so use global symbol table */
664
14.4k
    roles_tab = policydbp->p_roles.table;
665
14.4k
  } else {
666
6.85k
    roles_tab = stack_top->decl->p_roles.table;
667
6.85k
  }
668
669
21.3k
  dest_roledatum = hashtab_search(roles_tab, id);
670
21.3k
  if (!dest_roledatum) {
671
3.36k
    dest_roledatum = (role_datum_t *)malloc(sizeof(role_datum_t));
672
3.36k
    if (dest_roledatum == NULL) {
673
0
      free(id);
674
0
      return NULL;
675
0
    }
676
677
3.36k
    role_datum_init(dest_roledatum);
678
3.36k
    dest_roledatum->s.value = value;
679
3.36k
    dest_roledatum->flavor = isattr ? ROLE_ATTRIB : ROLE_ROLE;
680
681
3.36k
    if (hashtab_insert(roles_tab, id, dest_roledatum)) {
682
0
      free(id);
683
0
      role_datum_destroy(dest_roledatum);
684
0
      free(dest_roledatum);
685
0
      return NULL;
686
0
    }
687
17.9k
  } else {
688
17.9k
    free(id);
689
17.9k
    if (dest_roledatum->flavor !=
690
17.9k
        (isattr ? ROLE_ATTRIB : ROLE_ROLE))
691
0
      return NULL;
692
17.9k
  }
693
694
21.3k
  return dest_roledatum;
695
21.3k
}
696
697
/* Attempt to require a symbol within the current scope.  If currently
698
 * within an optional (and not its else branch), add the symbol to the
699
 * required list.  Return 0 on success, 1 if caller needs to free()
700
 * datum.  If symbols may not be declared here return -1.  For duplicate
701
 * declarations return -2.  For all else, including out of memory,
702
 * return -3..  Note that dest_value and datum_value might not be
703
 * restricted pointers.
704
 */
705
int require_symbol(uint32_t symbol_type, hashtab_key_t key,
706
       hashtab_datum_t datum, uint32_t *dest_value,
707
       uint32_t *datum_value)
708
284k
{
709
284k
  avrule_decl_t *decl = stack_top->decl;
710
284k
  int ret = create_symbol(symbol_type, key, datum, dest_value, SCOPE_REQ);
711
712
284k
  if (ret < 0) {
713
7
    return ret;
714
7
  }
715
716
284k
  if (ebitmap_set_bit(decl->required.scope + symbol_type,
717
284k
          *datum_value - 1, 1)) {
718
0
    return -3;
719
0
  }
720
721
284k
  stack_top->require_given = 1;
722
284k
  return ret;
723
284k
}
724
725
int add_perm_to_class(uint32_t perm_value, uint32_t class_value)
726
16.4k
{
727
16.4k
  avrule_decl_t *decl = stack_top->decl;
728
16.4k
  scope_index_t *scope;
729
730
16.4k
  assert(perm_value >= 1);
731
16.4k
  assert(class_value >= 1);
732
16.4k
  scope = &decl->required;
733
16.4k
  if (class_value > scope->class_perms_len) {
734
8.92k
    uint32_t i;
735
8.92k
    ebitmap_t *new_map = realloc(scope->class_perms_map,
736
8.92k
               class_value * sizeof(*new_map));
737
8.92k
    if (new_map == NULL) {
738
0
      return -1;
739
0
    }
740
8.92k
    scope->class_perms_map = new_map;
741
18.8k
    for (i = scope->class_perms_len; i < class_value; i++) {
742
9.92k
      ebitmap_init(scope->class_perms_map + i);
743
9.92k
    }
744
8.92k
    scope->class_perms_len = class_value;
745
8.92k
  }
746
16.4k
  if (ebitmap_set_bit(scope->class_perms_map + class_value - 1,
747
16.4k
          perm_value - 1, 1)) {
748
0
    return -1;
749
0
  }
750
16.4k
  return 0;
751
16.4k
}
752
753
static int perm_destroy(hashtab_key_t key, hashtab_datum_t datum,
754
      void *p __attribute__((unused)))
755
0
{
756
0
  if (key)
757
0
    free(key);
758
0
  free(datum);
759
0
  return 0;
760
0
}
761
762
static void class_datum_destroy(class_datum_t *cladatum)
763
2.07k
{
764
2.07k
  if (cladatum != NULL) {
765
2.07k
    hashtab_map(cladatum->permissions.table, perm_destroy, NULL);
766
2.07k
    hashtab_destroy(cladatum->permissions.table);
767
2.07k
    free(cladatum);
768
2.07k
  }
769
2.07k
}
770
771
int require_class(int pass)
772
2.66k
{
773
2.66k
  char *class_id = queue_remove(id_queue);
774
2.66k
  char *perm_id = NULL;
775
2.66k
  class_datum_t *datum = NULL;
776
2.66k
  perm_datum_t *perm = NULL;
777
2.66k
  int ret;
778
779
2.66k
  if (pass == 2) {
780
567
    free(class_id);
781
1.19k
    while ((perm_id = queue_remove(id_queue)) != NULL)
782
628
      free(perm_id);
783
567
    return 0;
784
567
  }
785
786
  /* first add the class if it is not already there */
787
2.09k
  if (class_id == NULL) {
788
1
    yyerror("no class name for class definition?");
789
1
    return -1;
790
1
  }
791
792
2.09k
  if ((datum = calloc(1, sizeof(*datum))) == NULL ||
793
2.09k
      symtab_init(&datum->permissions, PERM_SYMTAB_SIZE)) {
794
0
    yyerror("Out of memory!");
795
0
    class_datum_destroy(datum);
796
0
    return -1;
797
0
  }
798
2.09k
  ret = require_symbol(SYM_CLASSES, class_id, datum, &datum->s.value,
799
2.09k
           &datum->s.value);
800
2.09k
  if (ret < 0) {
801
1
    print_error_msg(ret, SYM_CLASSES);
802
1
    free(class_id);
803
1
    class_datum_destroy(datum);
804
1
    return -1;
805
1
  }
806
807
2.09k
  if (ret == 0) {
808
    /* a new class was added; reindex everything */
809
14
    if (policydb_index_classes(policydbp)) {
810
0
      yyerror("Out of memory!");
811
0
      return -1;
812
0
    }
813
2.07k
  } else {
814
2.07k
    class_datum_destroy(datum);
815
2.07k
    datum = hashtab_search(policydbp->p_classes.table, class_id);
816
2.07k
    assert(datum); /* the class datum should have existed */
817
2.07k
    free(class_id);
818
2.07k
  }
819
820
  /* now add each of the permissions to this class's requirements */
821
4.42k
  while ((perm_id = queue_remove(id_queue)) != NULL) {
822
2.33k
    int allocated = 0;
823
824
    /* Is the permission already in the table? */
825
2.33k
    perm = hashtab_search(datum->permissions.table, perm_id);
826
2.33k
    if (!perm && datum->comdatum)
827
0
      perm = hashtab_search(
828
0
        datum->comdatum->permissions.table, perm_id);
829
2.33k
    if (perm) {
830
      /* Yes, drop the name. */
831
2.32k
      free(perm_id);
832
2.32k
    } else {
833
      /* No - allocate and insert an entry for it. */
834
10
      if (policydbp->policy_type == POLICY_BASE) {
835
10
        yyerror2(
836
10
          "Base policy - require of permission %s without prior declaration.",
837
10
          perm_id);
838
10
        free(perm_id);
839
10
        return -1;
840
10
      }
841
0
      if (datum->permissions.nprim >= PERM_SYMTAB_SIZE) {
842
0
        yyerror2(
843
0
          "Class %s would have too many permissions "
844
0
          "to fit in an access vector with permission %s",
845
0
          policydbp->p_class_val_to_name
846
0
            [datum->s.value - 1],
847
0
          perm_id);
848
0
        free(perm_id);
849
0
        return -1;
850
0
      }
851
0
      allocated = 1;
852
0
      if ((perm = calloc(1, sizeof(*perm))) == NULL) {
853
0
        yyerror("Out of memory!");
854
0
        free(perm_id);
855
0
        return -1;
856
0
      }
857
0
      ret = hashtab_insert(datum->permissions.table, perm_id,
858
0
               perm);
859
0
      if (ret) {
860
0
        yyerror("Out of memory!");
861
0
        free(perm_id);
862
0
        free(perm);
863
0
        return -1;
864
0
      }
865
0
      perm->s.value = datum->permissions.nprim + 1;
866
0
    }
867
868
2.32k
    if (add_perm_to_class(perm->s.value, datum->s.value) == -1) {
869
0
      yyerror("Out of memory!");
870
0
      return -1;
871
0
    }
872
873
    /* Update number of primitives if we allocated one. */
874
2.32k
    if (allocated)
875
0
      datum->permissions.nprim++;
876
2.32k
  }
877
2.08k
  return 0;
878
2.09k
}
879
880
static int require_role_or_attribute(int pass, unsigned char isattr)
881
114k
{
882
114k
  char *key = NULL;
883
114k
  role_datum_t *role = NULL;
884
114k
  int ret;
885
886
114k
  if (pass == 2) {
887
33.0k
    free(queue_remove(id_queue));
888
33.0k
    return 0;
889
33.0k
  }
890
891
81.1k
  ret = create_role(SCOPE_REQ, isattr, &role, &key);
892
81.1k
  if (ret < 0) {
893
3
    return -1;
894
3
  }
895
896
81.1k
  free(key);
897
898
81.1k
  if (ret == 0) {
899
8.51k
    ret = ebitmap_set_bit(&role->dominates, role->s.value - 1, 1);
900
8.51k
    if (ret != 0) {
901
0
      yyerror("Out of memory");
902
0
      return -1;
903
0
    }
904
72.6k
  } else {
905
72.6k
    role_datum_destroy(role);
906
72.6k
    free(role);
907
72.6k
  }
908
909
81.1k
  return 0;
910
81.1k
}
911
912
int require_role(int pass)
913
106k
{
914
106k
  return require_role_or_attribute(pass, 0);
915
106k
}
916
917
int require_attribute_role(int pass)
918
7.79k
{
919
7.79k
  return require_role_or_attribute(pass, 1);
920
7.79k
}
921
922
static int require_type_or_attribute(int pass, unsigned char isattr)
923
112k
{
924
112k
  type_datum_t *type = NULL;
925
112k
  int ret;
926
927
112k
  if (pass == 2) {
928
45.3k
    free(queue_remove(id_queue));
929
45.3k
    return 0;
930
45.3k
  }
931
932
66.6k
  ret = create_type(SCOPE_REQ, isattr, &type);
933
934
66.6k
  if (ret < 0) {
935
7
    return -1;
936
7
  }
937
938
66.6k
  return 0;
939
66.6k
}
940
941
int require_type(int pass)
942
73.1k
{
943
73.1k
  return require_type_or_attribute(pass, 0);
944
73.1k
}
945
946
int require_attribute(int pass)
947
38.8k
{
948
38.8k
  return require_type_or_attribute(pass, 1);
949
38.8k
}
950
951
int require_user(int pass)
952
16.6k
{
953
16.6k
  char *key = NULL;
954
16.6k
  user_datum_t *user = NULL;
955
16.6k
  int ret;
956
957
16.6k
  if (pass == 1) {
958
8.75k
    free(queue_remove(id_queue));
959
8.75k
    return 0;
960
8.75k
  }
961
962
7.94k
  ret = create_user(SCOPE_REQ, &user, &key);
963
7.94k
  if (ret < 0) {
964
2
    return -1;
965
2
  }
966
967
7.94k
  free(key);
968
969
7.94k
  if (ret == 1) {
970
4.17k
    user_datum_destroy(user);
971
4.17k
    free(user);
972
4.17k
  }
973
974
7.94k
  return 0;
975
7.94k
}
976
977
static int require_bool_tunable(int pass, int is_tunable)
978
169k
{
979
169k
  char *id = queue_remove(id_queue);
980
169k
  cond_bool_datum_t *booldatum = NULL;
981
169k
  int retval;
982
169k
  if (pass == 2) {
983
61.2k
    free(id);
984
61.2k
    return 0;
985
61.2k
  }
986
108k
  if (id == NULL) {
987
1
    yyerror("no boolean name");
988
1
    return -1;
989
1
  }
990
108k
  if ((booldatum = calloc(1, sizeof(*booldatum))) == NULL) {
991
0
    cond_destroy_bool(id, booldatum, NULL);
992
0
    yyerror("Out of memory!");
993
0
    return -1;
994
0
  }
995
108k
  if (is_tunable)
996
6.95k
    booldatum->flags |= COND_BOOL_FLAGS_TUNABLE;
997
108k
  retval = require_symbol(SYM_BOOLS, id, booldatum, &booldatum->s.value,
998
108k
        &booldatum->s.value);
999
108k
  if (retval != 0) {
1000
96.8k
    cond_destroy_bool(id, booldatum, NULL);
1001
96.8k
    if (retval < 0) {
1002
1
      print_error_msg(retval, SYM_BOOLS);
1003
1
      return -1;
1004
1
    }
1005
96.8k
  }
1006
1007
108k
  return 0;
1008
108k
}
1009
1010
int require_bool(int pass)
1011
156k
{
1012
156k
  return require_bool_tunable(pass, 0);
1013
156k
}
1014
1015
int require_tunable(int pass)
1016
13.4k
{
1017
13.4k
  return require_bool_tunable(pass, 1);
1018
13.4k
}
1019
1020
int require_sens(int pass)
1021
18.3k
{
1022
18.3k
  char *id = queue_remove(id_queue);
1023
18.3k
  level_datum_t *level = NULL;
1024
18.3k
  int retval;
1025
18.3k
  if (pass == 2) {
1026
6.07k
    free(id);
1027
6.07k
    return 0;
1028
6.07k
  }
1029
12.3k
  if (!id) {
1030
1
    yyerror("no sensitivity name");
1031
1
    return -1;
1032
1
  }
1033
12.3k
  level = malloc(sizeof(level_datum_t));
1034
12.3k
  if (!level) {
1035
0
    free(id);
1036
0
    yyerror("Out of memory!");
1037
0
    return -1;
1038
0
  }
1039
12.3k
  level_datum_init(level);
1040
12.3k
  level->level = malloc(sizeof(mls_level_t));
1041
12.3k
  if (!level->level) {
1042
0
    free(id);
1043
0
    level_datum_destroy(level);
1044
0
    free(level);
1045
0
    yyerror("Out of memory!");
1046
0
    return -1;
1047
0
  }
1048
12.3k
  mls_level_init(level->level);
1049
12.3k
  retval = require_symbol(SYM_LEVELS, id, level, &level->level->sens,
1050
12.3k
        &level->level->sens);
1051
12.3k
  if (retval != 0) {
1052
7.57k
    free(id);
1053
7.57k
    mls_level_destroy(level->level);
1054
7.57k
    free(level->level);
1055
7.57k
    level_datum_destroy(level);
1056
7.57k
    free(level);
1057
7.57k
    if (retval < 0) {
1058
1
      print_error_msg(retval, SYM_LEVELS);
1059
1
      return -1;
1060
1
    }
1061
7.57k
  }
1062
1063
12.3k
  return 0;
1064
12.3k
}
1065
1066
int require_cat(int pass)
1067
8.76k
{
1068
8.76k
  char *id = queue_remove(id_queue);
1069
8.76k
  cat_datum_t *cat = NULL;
1070
8.76k
  int retval;
1071
8.76k
  if (pass == 2) {
1072
3.11k
    free(id);
1073
3.11k
    return 0;
1074
3.11k
  }
1075
5.64k
  if (!id) {
1076
1
    yyerror("no category name");
1077
1
    return -1;
1078
1
  }
1079
5.64k
  cat = malloc(sizeof(cat_datum_t));
1080
5.64k
  if (!cat) {
1081
0
    free(id);
1082
0
    yyerror("Out of memory!");
1083
0
    return -1;
1084
0
  }
1085
5.64k
  cat_datum_init(cat);
1086
1087
5.64k
  retval =
1088
5.64k
    require_symbol(SYM_CATS, id, cat, &cat->s.value, &cat->s.value);
1089
5.64k
  if (retval != 0) {
1090
2.04k
    free(id);
1091
2.04k
    cat_datum_destroy(cat);
1092
2.04k
    free(cat);
1093
2.04k
    if (retval < 0) {
1094
1
      print_error_msg(retval, SYM_CATS);
1095
1
      return -1;
1096
1
    }
1097
2.04k
  }
1098
1099
5.64k
  return 0;
1100
5.64k
}
1101
1102
static int is_scope_in_stack(const scope_datum_t *scope,
1103
           const scope_stack_t *stack)
1104
834k
{
1105
834k
  uint32_t i;
1106
834k
  if (stack == NULL) {
1107
84
    return 0; /* no matching scope found */
1108
84
  }
1109
833k
  if (stack->type == 1) {
1110
833k
    const avrule_decl_t *decl = stack->decl;
1111
3.59M
    for (i = 0; i < scope->decl_ids_len; i++) {
1112
3.15M
      if (scope->decl_ids[i] == decl->decl_id) {
1113
392k
        return 1;
1114
392k
      }
1115
3.15M
    }
1116
833k
  } else {
1117
    /* note that conditionals can't declare or require
1118
     * symbols, so skip this level */
1119
0
  }
1120
1121
  /* not within scope of this stack, so try its parent */
1122
441k
  return is_scope_in_stack(scope, stack->parent);
1123
833k
}
1124
1125
int is_id_in_scope(uint32_t symbol_type, const_hashtab_key_t id)
1126
394k
{
1127
394k
  const scope_datum_t *scope = (scope_datum_t *)hashtab_search(
1128
394k
    policydbp->scope[symbol_type].table, id);
1129
394k
  if (scope == NULL) {
1130
2.42k
    return 1; /* id is not known, so return success */
1131
2.42k
  }
1132
392k
  return is_scope_in_stack(scope, stack_top);
1133
394k
}
1134
1135
static int is_perm_in_scope_index(uint32_t perm_value, uint32_t class_value,
1136
          const scope_index_t *scope)
1137
6.48k
{
1138
6.48k
  if (class_value > scope->class_perms_len) {
1139
4.73k
    return 1;
1140
4.73k
  }
1141
1.75k
  if (ebitmap_get_bit(scope->class_perms_map + class_value - 1,
1142
1.75k
          perm_value - 1)) {
1143
1.68k
    return 1;
1144
1.68k
  }
1145
74
  return 0;
1146
1.75k
}
1147
1148
static int is_perm_in_stack(uint32_t perm_value, uint32_t class_value,
1149
          const scope_stack_t *stack)
1150
6.41k
{
1151
6.41k
  if (stack == NULL) {
1152
0
    return 0; /* no matching scope found */
1153
0
  }
1154
6.41k
  if (stack->type == 1) {
1155
6.41k
    avrule_decl_t *decl = stack->decl;
1156
6.41k
    if (is_perm_in_scope_index(perm_value, class_value,
1157
6.41k
             &decl->required) ||
1158
74
        is_perm_in_scope_index(perm_value, class_value,
1159
6.41k
             &decl->declared)) {
1160
6.41k
      return 1;
1161
6.41k
    }
1162
6.41k
  } else {
1163
    /* note that conditionals can't declare or require
1164
     * symbols, so skip this level */
1165
0
  }
1166
1167
  /* not within scope of this stack, so try its parent */
1168
0
  return is_perm_in_stack(perm_value, class_value, stack->parent);
1169
6.41k
}
1170
1171
int is_perm_in_scope(const_hashtab_key_t perm_id, const_hashtab_key_t class_id)
1172
6.41k
{
1173
6.41k
  const class_datum_t *cladatum = (class_datum_t *)hashtab_search(
1174
6.41k
    policydbp->p_classes.table, class_id);
1175
6.41k
  const perm_datum_t *perdatum;
1176
6.41k
  if (cladatum == NULL) {
1177
0
    return 1;
1178
0
  }
1179
6.41k
  perdatum = (perm_datum_t *)hashtab_search(cladatum->permissions.table,
1180
6.41k
              perm_id);
1181
6.41k
  if (perdatum == NULL) {
1182
0
    return 1;
1183
0
  }
1184
6.41k
  return is_perm_in_stack(perdatum->s.value, cladatum->s.value,
1185
6.41k
        stack_top);
1186
6.41k
}
1187
1188
cond_list_t *get_current_cond_list(cond_list_t *cond)
1189
13.1k
{
1190
  /* FIX ME: do something different here if in a nested
1191
   * conditional? */
1192
13.1k
  avrule_decl_t *decl = stack_top->decl;
1193
13.1k
  return get_decl_cond_list(policydbp, decl, cond);
1194
13.1k
}
1195
1196
/* Append the new conditional node to the existing ones.  During
1197
 * expansion the list will be reversed -- i.e., the last AV rule will
1198
 * be the first one listed in the policy.  This matches the behavior
1199
 * of the upstream compiler. */
1200
void append_cond_list(cond_list_t *cond)
1201
6.57k
{
1202
6.57k
  cond_list_t *old_cond = get_current_cond_list(cond);
1203
6.57k
  avrule_t *tmp;
1204
6.57k
  assert(old_cond != NULL); /* probably out of memory */
1205
6.57k
  if (old_cond->avtrue_list == NULL) {
1206
4.37k
    old_cond->avtrue_list = cond->avtrue_list;
1207
4.37k
  } else {
1208
35.6k
    for (tmp = old_cond->avtrue_list; tmp->next != NULL;
1209
33.4k
         tmp = tmp->next)
1210
33.4k
      ;
1211
2.19k
    tmp->next = cond->avtrue_list;
1212
2.19k
  }
1213
6.57k
  if (old_cond->avfalse_list == NULL) {
1214
5.10k
    old_cond->avfalse_list = cond->avfalse_list;
1215
5.10k
  } else {
1216
88.3k
    for (tmp = old_cond->avfalse_list; tmp->next != NULL;
1217
86.8k
         tmp = tmp->next)
1218
86.8k
      ;
1219
1.46k
    tmp->next = cond->avfalse_list;
1220
1.46k
  }
1221
1222
6.57k
  old_cond->flags |= cond->flags;
1223
6.57k
}
1224
1225
void append_avrule(avrule_t *avrule)
1226
21.0k
{
1227
21.0k
  avrule_decl_t *decl = stack_top->decl;
1228
1229
  /* currently avrules follow a completely different code path
1230
   * for handling avrules and compute types
1231
   * (define_cond_avrule_te_avtab, define_cond_compute_type);
1232
   * therefore there ought never be a conditional on top of the
1233
   * scope stack */
1234
21.0k
  assert(stack_top->type == 1);
1235
1236
21.0k
  if (stack_top->last_avrule == NULL) {
1237
1.31k
    decl->avrules = avrule;
1238
19.6k
  } else {
1239
19.6k
    stack_top->last_avrule->next = avrule;
1240
19.6k
  }
1241
21.0k
  stack_top->last_avrule = avrule;
1242
21.0k
}
1243
1244
/* this doesn't actually append, but really prepends it */
1245
void append_role_trans(role_trans_rule_t *role_tr_rules)
1246
831
{
1247
831
  avrule_decl_t *decl = stack_top->decl;
1248
1249
  /* role transitions are not allowed within conditionals */
1250
831
  assert(stack_top->type == 1);
1251
1252
831
  role_tr_rules->next = decl->role_tr_rules;
1253
831
  decl->role_tr_rules = role_tr_rules;
1254
831
}
1255
1256
/* this doesn't actually append, but really prepends it */
1257
void append_role_allow(role_allow_rule_t *role_allow_rules)
1258
7.81k
{
1259
7.81k
  avrule_decl_t *decl = stack_top->decl;
1260
1261
  /* role allows are not allowed within conditionals */
1262
7.81k
  assert(stack_top->type == 1);
1263
1264
7.81k
  role_allow_rules->next = decl->role_allow_rules;
1265
7.81k
  decl->role_allow_rules = role_allow_rules;
1266
7.81k
}
1267
1268
/* this doesn't actually append, but really prepends it */
1269
void append_filename_trans(filename_trans_rule_t *filename_trans_rules)
1270
3.21k
{
1271
3.21k
  avrule_decl_t *decl = stack_top->decl;
1272
1273
  /* filename transitions are not allowed within conditionals */
1274
3.21k
  assert(stack_top->type == 1);
1275
1276
3.21k
  filename_trans_rules->next = decl->filename_trans_rules;
1277
3.21k
  decl->filename_trans_rules = filename_trans_rules;
1278
3.21k
}
1279
1280
/* this doesn't actually append, but really prepends it */
1281
void append_range_trans(range_trans_rule_t *range_tr_rules)
1282
0
{
1283
0
  avrule_decl_t *decl = stack_top->decl;
1284
1285
  /* range transitions are not allowed within conditionals */
1286
0
  assert(stack_top->type == 1);
1287
1288
0
  range_tr_rules->next = decl->range_tr_rules;
1289
0
  decl->range_tr_rules = range_tr_rules;
1290
0
}
1291
1292
int begin_optional(int pass)
1293
56.7k
{
1294
56.7k
  avrule_block_t *block = NULL;
1295
56.7k
  avrule_decl_t *decl;
1296
56.7k
  if (pass == 1) {
1297
    /* allocate a new avrule block for this optional block */
1298
38.2k
    if ((block = avrule_block_create()) == NULL ||
1299
38.2k
        (decl = avrule_decl_create(next_decl_id)) == NULL) {
1300
0
      goto cleanup;
1301
0
    }
1302
38.2k
    block->flags |= AVRULE_OPTIONAL;
1303
38.2k
    block->branch_list = decl;
1304
38.2k
    last_block->next = block;
1305
38.2k
  } else {
1306
    /* select the next block from the chain built during pass 1 */
1307
18.5k
    block = last_block->next;
1308
18.5k
    assert(block != NULL && block->branch_list != NULL &&
1309
18.5k
           block->branch_list->decl_id == next_decl_id);
1310
18.5k
    decl = block->branch_list;
1311
18.5k
  }
1312
56.7k
  if (push_stack(1, block, decl) == -1) {
1313
0
    goto cleanup;
1314
0
  }
1315
56.7k
  stack_top->last_avrule = NULL;
1316
56.7k
  last_block = block;
1317
56.7k
  next_decl_id++;
1318
56.7k
  return 0;
1319
0
cleanup:
1320
0
  yyerror("Out of memory!");
1321
0
  avrule_block_destroy(block);
1322
0
  return -1;
1323
56.7k
}
1324
1325
int end_optional(int pass __attribute__((unused)))
1326
44.4k
{
1327
  /* once nested conditionals are allowed, do the stack unfolding here */
1328
44.4k
  pop_stack();
1329
44.4k
  return 0;
1330
44.4k
}
1331
1332
int begin_optional_else(int pass)
1333
1.30k
{
1334
1.30k
  avrule_decl_t *decl;
1335
1.30k
  assert(stack_top->type == 1 && stack_top->in_else == 0);
1336
1.30k
  if (pass == 1) {
1337
    /* allocate a new declaration and add it to the
1338
     * current chain */
1339
973
    if ((decl = avrule_decl_create(next_decl_id)) == NULL) {
1340
0
      yyerror("Out of memory!");
1341
0
      return -1;
1342
0
    }
1343
973
    stack_top->decl->next = decl;
1344
973
  } else {
1345
    /* pick the (hopefully last) declaration of this
1346
       avrule block, built from pass 1 */
1347
334
    decl = stack_top->decl->next;
1348
334
    assert(decl != NULL && decl->next == NULL &&
1349
334
           decl->decl_id == next_decl_id);
1350
334
  }
1351
1.30k
  stack_top->in_else = 1;
1352
1.30k
  stack_top->decl = decl;
1353
1.30k
  stack_top->last_avrule = NULL;
1354
1.30k
  stack_top->require_given = 0;
1355
1.30k
  next_decl_id++;
1356
1.30k
  return 0;
1357
1.30k
}
1358
1359
static int copy_requirements(avrule_decl_t *dest, const scope_stack_t *stack)
1360
437k
{
1361
437k
  uint32_t i;
1362
437k
  if (stack == NULL) {
1363
14.7k
    return 0;
1364
14.7k
  }
1365
422k
  if (stack->type == 1) {
1366
422k
    const scope_index_t *src_scope = &stack->decl->required;
1367
422k
    scope_index_t *dest_scope = &dest->required;
1368
3.80M
    for (i = 0; i < SYM_NUM; i++) {
1369
3.38M
      const ebitmap_t *src_bitmap = &src_scope->scope[i];
1370
3.38M
      ebitmap_t *dest_bitmap = &dest_scope->scope[i];
1371
3.38M
      if (ebitmap_union(dest_bitmap, src_bitmap)) {
1372
0
        yyerror("Out of memory!");
1373
0
        return -1;
1374
0
      }
1375
3.38M
    }
1376
    /* now copy class permissions */
1377
422k
    if (src_scope->class_perms_len > dest_scope->class_perms_len) {
1378
14.5k
      ebitmap_t *new_map = realloc(
1379
14.5k
        dest_scope->class_perms_map,
1380
14.5k
        src_scope->class_perms_len * sizeof(*new_map));
1381
14.5k
      if (new_map == NULL) {
1382
0
        yyerror("Out of memory!");
1383
0
        return -1;
1384
0
      }
1385
14.5k
      dest_scope->class_perms_map = new_map;
1386
14.5k
      for (i = dest_scope->class_perms_len;
1387
33.7k
           i < src_scope->class_perms_len; i++) {
1388
19.2k
        ebitmap_init(dest_scope->class_perms_map + i);
1389
19.2k
      }
1390
14.5k
      dest_scope->class_perms_len =
1391
14.5k
        src_scope->class_perms_len;
1392
14.5k
    }
1393
442k
    for (i = 0; i < src_scope->class_perms_len; i++) {
1394
19.4k
      const ebitmap_t *src_bitmap =
1395
19.4k
        &src_scope->class_perms_map[i];
1396
19.4k
      ebitmap_t *dest_bitmap =
1397
19.4k
        &dest_scope->class_perms_map[i];
1398
19.4k
      if (ebitmap_union(dest_bitmap, src_bitmap)) {
1399
0
        yyerror("Out of memory!");
1400
0
        return -1;
1401
0
      }
1402
19.4k
    }
1403
422k
  }
1404
422k
  return copy_requirements(dest, stack->parent);
1405
422k
}
1406
1407
/* During pass 1, check that at least one thing was required within
1408
 * this block, for those places where a REQUIRED is necessary.  During
1409
 * pass 2, have this block inherit its parents' requirements.  Return
1410
 * 0 on success, -1 on failure. */
1411
int end_avrule_block(int pass)
1412
45.7k
{
1413
45.7k
  avrule_decl_t *decl = stack_top->decl;
1414
45.7k
  assert(stack_top->type == 1);
1415
45.7k
  if (pass == 2) {
1416
    /* this avrule_decl inherits all of its parents'
1417
     * requirements */
1418
14.7k
    if (copy_requirements(decl, stack_top->parent) == -1) {
1419
0
      return -1;
1420
0
    }
1421
14.7k
    return 0;
1422
14.7k
  }
1423
30.9k
  if (!stack_top->in_else && !stack_top->require_given) {
1424
22.2k
    if (policydbp->policy_type == POLICY_BASE &&
1425
22.2k
        stack_top->parent != NULL) {
1426
      /* if this is base no require should be in the global block */
1427
22.2k
      return 0;
1428
22.2k
    } else {
1429
      /* non-ELSE branches must have at least one thing required */
1430
0
      yyerror("This block has no require section.");
1431
0
      return -1;
1432
0
    }
1433
22.2k
  }
1434
8.68k
  return 0;
1435
30.9k
}
1436
1437
/* Push a new scope on to the stack and update the 'last' pointer.
1438
 * Return 0 on success, -1 if out * of memory. */
1439
static int push_stack(int stack_type, ...)
1440
70.1k
{
1441
70.1k
  scope_stack_t *s = calloc(1, sizeof(*s));
1442
70.1k
  va_list ap;
1443
70.1k
  if (s == NULL) {
1444
0
    return -1;
1445
0
  }
1446
70.1k
  va_start(ap, stack_type);
1447
70.1k
  switch (s->type = stack_type) {
1448
70.1k
  case 1: {
1449
70.1k
    va_arg(ap, avrule_block_t *);
1450
70.1k
    s->decl = va_arg(ap, avrule_decl_t *);
1451
70.1k
    break;
1452
0
  }
1453
0
  case 2: {
1454
0
    va_arg(ap, cond_list_t *);
1455
0
    break;
1456
0
  }
1457
0
  default:
1458
    /* invalid stack type given */
1459
0
    assert(0);
1460
70.1k
  }
1461
70.1k
  va_end(ap);
1462
70.1k
  s->parent = stack_top;
1463
70.1k
  stack_top = s;
1464
70.1k
  return 0;
1465
70.1k
}
1466
1467
/* Pop off the most recently added from the stack.  Update the 'last'
1468
 * pointer. */
1469
static void pop_stack(void)
1470
70.1k
{
1471
70.1k
  scope_stack_t *parent;
1472
70.1k
  assert(stack_top != NULL);
1473
70.1k
  parent = stack_top->parent;
1474
70.1k
  free(stack_top);
1475
70.1k
  stack_top = parent;
1476
70.1k
}
1477
1478
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1479
void module_compiler_reset(void)
1480
8.35k
{
1481
29.0k
  while (stack_top)
1482
20.6k
    pop_stack();
1483
1484
  last_block = NULL;
1485
8.35k
  next_decl_id = 1;
1486
8.35k
}
1487
#endif