Coverage Report

Created: 2026-06-10 07:00

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