Coverage Report

Created: 2026-01-10 06:27

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/selinux/libsepol/src/link.c
Line
Count
Source
1
/* Authors: Karl MacMillan <kmacmillan@mentalrootkit.com>
2
 *      Joshua Brindle <jbrindle@tresys.com>
3
 *          Jason Tang <jtang@tresys.com>
4
 *
5
 * Copyright (C) 2004-2005 Tresys Technology, LLC
6
 * Copyright (C) 2007 Red Hat, Inc.
7
 *
8
 *  This library is free software; you can redistribute it and/or
9
 *  modify it under the terms of the GNU Lesser General Public
10
 *  License as published by the Free Software Foundation; either
11
 *  version 2.1 of the License, or (at your option) any later version.
12
 *
13
 *  This library is distributed in the hope that it will be useful,
14
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16
 *  Lesser General Public License for more details.
17
 *
18
 *  You should have received a copy of the GNU Lesser General Public
19
 *  License along with this library; if not, write to the Free Software
20
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
21
 */
22
23
#include <sepol/policydb/policydb.h>
24
#include <sepol/policydb/conditional.h>
25
#include <sepol/policydb/hashtab.h>
26
#include <sepol/policydb/avrule_block.h>
27
#include <sepol/policydb/link.h>
28
#include <sepol/policydb/util.h>
29
30
#include <stdlib.h>
31
#include <stdarg.h>
32
#include <stdio.h>
33
#include <string.h>
34
#include <assert.h>
35
36
#include "debug.h"
37
#include "private.h"
38
39
#undef min
40
0
#define min(a,b) (((a) < (b)) ? (a) : (b))
41
42
typedef struct policy_module {
43
  policydb_t *policy;
44
  uint32_t num_decls;
45
  uint32_t *map[SYM_NUM];
46
  uint32_t *avdecl_map;
47
  uint32_t **perm_map;
48
  uint32_t *perm_map_len;
49
50
  /* a pointer to within the base module's avrule_block chain to
51
   * where this module's global now resides */
52
  avrule_block_t *base_global;
53
} policy_module_t;
54
55
typedef struct link_state {
56
  int verbose;
57
  policydb_t *base;
58
  avrule_block_t *last_avrule_block, *last_base_avrule_block;
59
  uint32_t next_decl_id, current_decl_id;
60
61
  /* temporary variables, used during hashtab_map() calls */
62
  policy_module_t *cur;
63
  char *cur_mod_name;
64
  avrule_decl_t *dest_decl;
65
  class_datum_t *src_class, *dest_class;
66
  char *dest_class_name;
67
  char dest_class_req;  /* flag indicating the class was not declared */
68
  uint32_t symbol_num;
69
  /* used to report the name of the module if dependency error occurs */
70
  policydb_t **decl_to_mod;
71
72
  /* error reporting fields */
73
  sepol_handle_t *handle;
74
} link_state_t;
75
76
typedef struct missing_requirement {
77
  uint32_t symbol_type;
78
  uint32_t symbol_value;
79
  uint32_t perm_value;
80
} missing_requirement_t;
81
82
static const char * const symtab_names[SYM_NUM] = {
83
  "common", "class", "role", "type/attribute", "user",
84
  "bool", "level", "category"
85
};
86
87
/* Deallocates all elements within a module, but NOT the policydb_t
88
 * structure within, as well as the pointer itself. */
89
static void policy_module_destroy(policy_module_t * mod)
90
0
{
91
0
  unsigned int i;
92
0
  if (mod == NULL) {
93
0
    return;
94
0
  }
95
0
  for (i = 0; i < SYM_NUM; i++) {
96
0
    free(mod->map[i]);
97
0
  }
98
0
  for (i = 0; mod->perm_map != NULL && i < mod->policy->p_classes.nprim;
99
0
       i++) {
100
0
    free(mod->perm_map[i]);
101
0
  }
102
0
  free(mod->perm_map);
103
0
  free(mod->perm_map_len);
104
0
  free(mod->avdecl_map);
105
0
  free(mod);
106
0
}
107
108
/***** functions that copy identifiers from a module to base *****/
109
110
/* Note: there is currently no scoping for permissions, which causes some
111
 * strange side-effects. The current approach is this:
112
 *
113
 * a) perm is required and the class _and_ perm are declared in base: only add a mapping.
114
 * b) perm is required and the class and perm are _not_ declared in base: simply add the permissions
115
 *    to the object class. This means that the requirements for the decl are the union of the permissions
116
 *    required for all decls, but who cares.
117
 * c) perm is required, the class is declared in base, but the perm is not present. Nothing we can do
118
 *    here because we can't mark a single permission as required, so we bail with a requirement error
119
 *    _even_ if we are in an optional.
120
 *
121
 * A is correct behavior, b is wrong but not too bad, c is totall wrong for optionals. Fixing this requires
122
 * a format change.
123
 */
124
static int permission_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
125
            void *data)
126
0
{
127
0
  char *perm_id = key, *new_id = NULL;
128
0
  perm_datum_t *perm, *new_perm = NULL, *dest_perm;
129
0
  link_state_t *state = (link_state_t *) data;
130
131
0
  class_datum_t *src_class = state->src_class;
132
0
  class_datum_t *dest_class = state->dest_class;
133
0
  policy_module_t *mod = state->cur;
134
0
  uint32_t sclassi = src_class->s.value - 1;
135
0
  int ret;
136
137
0
  perm = (perm_datum_t *) datum;
138
0
  dest_perm = hashtab_search(dest_class->permissions.table, perm_id);
139
0
  if (dest_perm == NULL && dest_class->comdatum != NULL) {
140
0
    dest_perm =
141
0
        hashtab_search(dest_class->comdatum->permissions.table,
142
0
           perm_id);
143
0
  }
144
145
0
  if (dest_perm == NULL) {
146
    /* If the object class was not declared in the base, add the perm
147
     * to the object class. */
148
0
    if (state->dest_class_req) {
149
      /* If the class was required (not declared), insert the new permission */
150
0
      new_id = strdup(perm_id);
151
0
      if (new_id == NULL) {
152
0
        ERR(state->handle, "Memory error");
153
0
        ret = SEPOL_ERR;
154
0
        goto err;
155
0
      }
156
0
      new_perm =
157
0
          (perm_datum_t *) calloc(1, sizeof(perm_datum_t));
158
0
      if (new_perm == NULL) {
159
0
        ERR(state->handle, "Memory error");
160
0
        ret = SEPOL_ERR;
161
0
        goto err;
162
0
      }
163
0
      ret = hashtab_insert(dest_class->permissions.table,
164
0
               (hashtab_key_t) new_id,
165
0
               (hashtab_datum_t) new_perm);
166
0
      if (ret) {
167
0
        ERR(state->handle,
168
0
            "could not insert permission into class");
169
0
        goto err;
170
0
      }
171
0
      new_perm->s.value = dest_class->permissions.nprim + 1;
172
0
      dest_perm = new_perm;
173
0
    } else {
174
      /* this is case c from above */
175
0
      ERR(state->handle,
176
0
          "Module %s depends on permission %s in class %s, not satisfied",
177
0
          state->cur_mod_name, perm_id,
178
0
          state->dest_class_name);
179
0
      return SEPOL_EREQ;
180
0
    }
181
0
  }
182
183
  /* build the mapping for permissions encompassing this class.
184
   * unlike symbols, the permission map translates between
185
   * module permission bit to target permission bit.  that bit
186
   * may have originated from the class -or- it could be from
187
   * the class's common parent.*/
188
0
  if (perm->s.value > mod->perm_map_len[sclassi]) {
189
0
    uint32_t *newmap = calloc(perm->s.value, sizeof(*newmap));
190
0
    if (newmap == NULL) {
191
0
      ERR(state->handle, "Out of memory!");
192
0
      return -1;
193
0
    }
194
0
    if (mod->perm_map_len[sclassi] > 0) {
195
0
      memcpy(newmap, mod->perm_map[sclassi], mod->perm_map_len[sclassi] * sizeof(*newmap));
196
0
    }
197
0
    free(mod->perm_map[sclassi]);
198
0
    mod->perm_map[sclassi] = newmap;
199
0
    mod->perm_map_len[sclassi] = perm->s.value;
200
0
  }
201
0
  mod->perm_map[sclassi][perm->s.value - 1] = dest_perm->s.value;
202
203
0
  return 0;
204
0
      err:
205
0
  free(new_id);
206
0
  free(new_perm);
207
0
  return ret;
208
0
}
209
210
static int class_copy_default_new_object(link_state_t *state,
211
           class_datum_t *olddatum,
212
           class_datum_t *newdatum)
213
0
{
214
0
  if (olddatum->default_user) {
215
0
    if (newdatum->default_user && olddatum->default_user != newdatum->default_user) {
216
0
      ERR(state->handle, "Found conflicting default user definitions");
217
0
      return SEPOL_ENOTSUP;
218
0
    }
219
0
    newdatum->default_user = olddatum->default_user;
220
0
  }
221
0
  if (olddatum->default_role) {
222
0
    if (newdatum->default_role && olddatum->default_role != newdatum->default_role) {
223
0
      ERR(state->handle, "Found conflicting default role definitions");
224
0
      return SEPOL_ENOTSUP;
225
0
    }
226
0
    newdatum->default_role = olddatum->default_role;
227
0
  }
228
0
  if (olddatum->default_type) {
229
0
    if (newdatum->default_type && olddatum->default_type != newdatum->default_type) {
230
0
      ERR(state->handle, "Found conflicting default type definitions");
231
0
      return SEPOL_ENOTSUP;
232
0
    }
233
0
    newdatum->default_type = olddatum->default_type;
234
0
  }
235
0
  if (olddatum->default_range) {
236
0
    if (newdatum->default_range && olddatum->default_range != newdatum->default_range) {
237
0
      ERR(state->handle, "Found conflicting default range definitions");
238
0
      return SEPOL_ENOTSUP;
239
0
    }
240
0
    newdatum->default_range = olddatum->default_range;
241
0
  }
242
0
  return 0;
243
0
}
244
245
static int class_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
246
             void *data)
247
0
{
248
0
  char *id = key, *new_id = NULL;
249
0
  class_datum_t *cladatum, *new_class = NULL;
250
0
  link_state_t *state = (link_state_t *) data;
251
0
  scope_datum_t *scope = NULL;
252
0
  int ret;
253
254
0
  cladatum = (class_datum_t *) datum;
255
0
  state->dest_class_req = 0;
256
257
0
  new_class = hashtab_search(state->base->p_classes.table, id);
258
  /* If there is not an object class already in the base symtab that means
259
   * that either a) a module is trying to declare a new object class (which
260
   * the compiler should prevent) or b) an object class was required that is
261
   * not in the base.
262
   */
263
0
  if (new_class == NULL) {
264
0
    scope =
265
0
        hashtab_search(state->cur->policy->p_classes_scope.table,
266
0
           id);
267
0
    if (scope == NULL) {
268
0
      ret = SEPOL_ERR;
269
0
      goto err;
270
0
    }
271
0
    if (scope->scope == SCOPE_DECL) {
272
      /* disallow declarations in modules */
273
0
      ERR(state->handle,
274
0
          "%s: Modules may not yet declare new classes.",
275
0
          state->cur_mod_name);
276
0
      ret = SEPOL_ENOTSUP;
277
0
      goto err;
278
0
    } else {
279
      /* It would be nice to error early here because the requirement is
280
       * not met, but we cannot because the decl might be optional (in which
281
       * case we should record the requirement so that it is just turned
282
       * off). Note: this will break horribly if modules can declare object
283
       * classes because the class numbers will be all wrong (i.e., they
284
       * might be assigned in the order they were required rather than the
285
       * current scheme which ensures correct numbering by ordering the 
286
       * declarations properly). This can't be fixed until some infrastructure
287
       * for querying the object class numbers is in place. */
288
0
      state->dest_class_req = 1;
289
0
      new_class =
290
0
          (class_datum_t *) calloc(1, sizeof(class_datum_t));
291
0
      if (new_class == NULL) {
292
0
        ERR(state->handle, "Memory error");
293
0
        ret = SEPOL_ERR;
294
0
        goto err;
295
0
      }
296
0
      if (symtab_init
297
0
          (&new_class->permissions, PERM_SYMTAB_SIZE)) {
298
0
        ret = SEPOL_ERR;
299
0
        goto err;
300
0
      }
301
0
      new_id = strdup(id);
302
0
      if (new_id == NULL) {
303
0
        ERR(state->handle, "Memory error");
304
0
        symtab_destroy(&new_class->permissions);
305
0
        ret = SEPOL_ERR;
306
0
        goto err;
307
0
      }
308
0
      ret = hashtab_insert(state->base->p_classes.table,
309
0
               (hashtab_key_t) new_id,
310
0
               (hashtab_datum_t) new_class);
311
0
      if (ret) {
312
0
        ERR(state->handle,
313
0
            "could not insert new class into symtab");
314
0
        symtab_destroy(&new_class->permissions);
315
0
        goto err;
316
0
      }
317
0
      new_class->s.value = ++(state->base->p_classes.nprim);
318
0
    }
319
0
  }
320
321
0
  state->cur->map[SYM_CLASSES][cladatum->s.value - 1] =
322
0
      new_class->s.value;
323
324
  /* copy permissions */
325
0
  state->src_class = cladatum;
326
0
  state->dest_class = new_class;
327
0
  state->dest_class_name = (char *)key;
328
329
  /* copy default new object rules */
330
0
  ret = class_copy_default_new_object(state, cladatum, new_class);
331
0
  if (ret)
332
0
    return ret;
333
334
0
  ret =
335
0
      hashtab_map(cladatum->permissions.table, permission_copy_callback,
336
0
      state);
337
0
  if (ret != 0) {
338
0
    return ret;
339
0
  }
340
341
0
  return 0;
342
0
      err:
343
0
  free(new_class);
344
0
  free(new_id);
345
0
  return ret;
346
0
}
347
348
static int role_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
349
            void *data)
350
0
{
351
0
  int ret;
352
0
  char *id = key, *new_id = NULL;
353
0
  role_datum_t *role, *base_role, *new_role = NULL;
354
0
  link_state_t *state = (link_state_t *) data;
355
356
0
  role = (role_datum_t *) datum;
357
358
0
  base_role = hashtab_search(state->base->p_roles.table, id);
359
0
  if (base_role != NULL) {
360
    /* role already exists.  check that it is what this
361
     * module expected.  duplicate declarations (e.g., two
362
     * modules both declare role foo_r) is checked during
363
     * scope_copy_callback(). */
364
0
    if (role->flavor == ROLE_ATTRIB
365
0
        && base_role->flavor != ROLE_ATTRIB) {
366
0
      ERR(state->handle,
367
0
          "%s: Expected %s to be a role attribute, but it was already declared as a regular role.",
368
0
          state->cur_mod_name, id);
369
0
      return -1;
370
0
    } else if (role->flavor != ROLE_ATTRIB
371
0
         && base_role->flavor == ROLE_ATTRIB) {
372
0
      ERR(state->handle,
373
0
          "%s: Expected %s to be a regular role, but it was already declared as a role attribute.",
374
0
          state->cur_mod_name, id);
375
0
      return -1;
376
0
    }
377
0
  } else {
378
0
    if (state->verbose)
379
0
      INFO(state->handle, "copying role %s", id);
380
381
0
    if ((new_id = strdup(id)) == NULL) {
382
0
      goto cleanup;
383
0
    }
384
385
0
    if ((new_role =
386
0
         (role_datum_t *) malloc(sizeof(*new_role))) == NULL) {
387
0
      goto cleanup;
388
0
    }
389
0
    role_datum_init(new_role);
390
391
    /* new_role's dominates, types and roles field will be copied
392
     * during role_fix_callback() */
393
0
    new_role->flavor = role->flavor;
394
0
    new_role->s.value = state->base->p_roles.nprim + 1;
395
396
0
    ret = hashtab_insert(state->base->p_roles.table,
397
0
             (hashtab_key_t) new_id,
398
0
             (hashtab_datum_t) new_role);
399
0
    if (ret) {
400
0
      goto cleanup;
401
0
    }
402
0
    state->base->p_roles.nprim++;
403
0
    base_role = new_role;
404
0
  }
405
406
0
  if (state->dest_decl) {
407
0
    new_id = NULL;
408
0
    if ((new_role = malloc(sizeof(*new_role))) == NULL) {
409
0
      goto cleanup;
410
0
    }
411
0
    role_datum_init(new_role);
412
0
    new_role->flavor = base_role->flavor;
413
0
    new_role->s.value = base_role->s.value;
414
0
    if ((new_id = strdup(id)) == NULL) {
415
0
      goto cleanup;
416
0
    }
417
0
    if (hashtab_insert
418
0
        (state->dest_decl->p_roles.table, new_id, new_role)) {
419
0
      goto cleanup;
420
0
    }
421
0
    state->dest_decl->p_roles.nprim++;
422
0
  }
423
424
0
  state->cur->map[SYM_ROLES][role->s.value - 1] = base_role->s.value;
425
0
  return 0;
426
427
0
      cleanup:
428
0
  ERR(state->handle, "Out of memory!");
429
0
  role_datum_destroy(new_role);
430
0
  free(new_id);
431
0
  free(new_role);
432
0
  return -1;
433
0
}
434
435
/* Copy types and attributes from a module into the base module. The
436
 * attributes are copied, but the types that make up this attribute
437
 * are delayed type_fix_callback(). */
438
static int type_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
439
            void *data)
440
0
{
441
0
  int ret;
442
0
  char *id = key, *new_id = NULL;
443
0
  type_datum_t *type, *base_type, *new_type = NULL;
444
0
  link_state_t *state = (link_state_t *) data;
445
446
0
  type = (type_datum_t *) datum;
447
0
  if ((type->flavor == TYPE_TYPE && !type->primary)
448
0
      || type->flavor == TYPE_ALIAS) {
449
    /* aliases are handled later, in alias_copy_callback() */
450
0
    return 0;
451
0
  }
452
453
0
  base_type = hashtab_search(state->base->p_types.table, id);
454
0
  if (base_type != NULL) {
455
    /* type already exists.  check that it is what this
456
     * module expected.  duplicate declarations (e.g., two
457
     * modules both declare type foo_t) is checked during
458
     * scope_copy_callback(). */
459
0
    if (type->flavor == TYPE_ATTRIB
460
0
        && base_type->flavor != TYPE_ATTRIB) {
461
0
      ERR(state->handle,
462
0
          "%s: Expected %s to be an attribute, but it was already declared as a type.",
463
0
          state->cur_mod_name, id);
464
0
      return -1;
465
0
    } else if (type->flavor != TYPE_ATTRIB
466
0
         && base_type->flavor == TYPE_ATTRIB) {
467
0
      ERR(state->handle,
468
0
          "%s: Expected %s to be a type, but it was already declared as an attribute.",
469
0
          state->cur_mod_name, id);
470
0
      return -1;
471
0
    }
472
473
0
    base_type->flags |= type->flags;
474
0
  } else {
475
0
    if (state->verbose)
476
0
      INFO(state->handle, "copying type %s", id);
477
478
0
    if ((new_id = strdup(id)) == NULL) {
479
0
      goto cleanup;
480
0
    }
481
482
0
    if ((new_type =
483
0
         (type_datum_t *) calloc(1, sizeof(*new_type))) == NULL) {
484
0
      goto cleanup;
485
0
    }
486
0
    new_type->primary = type->primary;
487
0
    new_type->flags = type->flags;
488
0
    new_type->flavor = type->flavor;
489
    /* for attributes, the writing of new_type->types is
490
       done in type_fix_callback() */
491
492
0
    new_type->s.value = state->base->p_types.nprim + 1;
493
494
0
    ret = hashtab_insert(state->base->p_types.table,
495
0
             (hashtab_key_t) new_id,
496
0
             (hashtab_datum_t) new_type);
497
0
    if (ret) {
498
0
      goto cleanup;
499
0
    }
500
0
    state->base->p_types.nprim++;
501
0
    base_type = new_type;
502
0
  }
503
504
0
  if (state->dest_decl) {
505
0
    new_id = NULL;
506
0
    if ((new_type = calloc(1, sizeof(*new_type))) == NULL) {
507
0
      goto cleanup;
508
0
    }
509
0
    new_type->primary = type->primary;
510
0
    new_type->flavor = type->flavor;
511
0
    new_type->flags = type->flags;
512
0
    new_type->s.value = base_type->s.value;
513
0
    if ((new_id = strdup(id)) == NULL) {
514
0
      goto cleanup;
515
0
    }
516
0
    if (hashtab_insert
517
0
        (state->dest_decl->p_types.table, new_id, new_type)) {
518
0
      goto cleanup;
519
0
    }
520
0
    state->dest_decl->p_types.nprim++;
521
0
  }
522
523
0
  state->cur->map[SYM_TYPES][type->s.value - 1] = base_type->s.value;
524
0
  return 0;
525
526
0
      cleanup:
527
0
  ERR(state->handle, "Out of memory!");
528
0
  free(new_id);
529
0
  free(new_type);
530
0
  return -1;
531
0
}
532
533
static int user_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
534
            void *data)
535
0
{
536
0
  int ret;
537
0
  char *id = key, *new_id = NULL;
538
0
  user_datum_t *user, *base_user, *new_user = NULL;
539
0
  link_state_t *state = (link_state_t *) data;
540
541
0
  user = (user_datum_t *) datum;
542
543
0
  base_user = hashtab_search(state->base->p_users.table, id);
544
0
  if (base_user == NULL) {
545
0
    if (state->verbose)
546
0
      INFO(state->handle, "copying user %s", id);
547
548
0
    if ((new_id = strdup(id)) == NULL) {
549
0
      goto cleanup;
550
0
    }
551
552
0
    if ((new_user =
553
0
         (user_datum_t *) malloc(sizeof(*new_user))) == NULL) {
554
0
      goto cleanup;
555
0
    }
556
0
    user_datum_init(new_user);
557
    /* new_users's roles and MLS fields will be copied during
558
       user_fix_callback(). */
559
560
0
    new_user->s.value = state->base->p_users.nprim + 1;
561
562
0
    ret = hashtab_insert(state->base->p_users.table,
563
0
             (hashtab_key_t) new_id,
564
0
             (hashtab_datum_t) new_user);
565
0
    if (ret) {
566
0
      goto cleanup;
567
0
    }
568
0
    state->base->p_users.nprim++;
569
0
    base_user = new_user;
570
0
  }
571
572
0
  if (state->dest_decl) {
573
0
    new_id = NULL;
574
0
    if ((new_user = malloc(sizeof(*new_user))) == NULL) {
575
0
      goto cleanup;
576
0
    }
577
0
    user_datum_init(new_user);
578
0
    new_user->s.value = base_user->s.value;
579
0
    if ((new_id = strdup(id)) == NULL) {
580
0
      goto cleanup;
581
0
    }
582
0
    if (hashtab_insert
583
0
        (state->dest_decl->p_users.table, new_id, new_user)) {
584
0
      goto cleanup;
585
0
    }
586
0
    state->dest_decl->p_users.nprim++;
587
0
  }
588
589
0
  state->cur->map[SYM_USERS][user->s.value - 1] = base_user->s.value;
590
0
  return 0;
591
592
0
      cleanup:
593
0
  ERR(state->handle, "Out of memory!");
594
0
  user_datum_destroy(new_user);
595
0
  free(new_id);
596
0
  free(new_user);
597
0
  return -1;
598
0
}
599
600
static int bool_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
601
            void *data)
602
0
{
603
0
  int ret;
604
0
  char *id = key, *new_id = NULL;
605
0
  cond_bool_datum_t *booldatum, *base_bool, *new_bool = NULL;
606
0
  link_state_t *state = (link_state_t *) data;
607
0
  scope_datum_t *scope;
608
609
0
  booldatum = (cond_bool_datum_t *) datum;
610
611
0
  base_bool = hashtab_search(state->base->p_bools.table, id);
612
0
  if (base_bool == NULL) {
613
0
    if (state->verbose)
614
0
      INFO(state->handle, "copying boolean %s", id);
615
616
0
    if ((new_id = strdup(id)) == NULL) {
617
0
      goto cleanup;
618
0
    }
619
620
0
    if ((new_bool =
621
0
         (cond_bool_datum_t *) malloc(sizeof(*new_bool))) == NULL) {
622
0
      goto cleanup;
623
0
    }
624
0
    new_bool->s.value = state->base->p_bools.nprim + 1;
625
626
0
    ret = hashtab_insert(state->base->p_bools.table,
627
0
             (hashtab_key_t) new_id,
628
0
             (hashtab_datum_t) new_bool);
629
0
    if (ret) {
630
0
      goto cleanup;
631
0
    }
632
0
    state->base->p_bools.nprim++;
633
0
    base_bool = new_bool;
634
0
    base_bool->flags = booldatum->flags;
635
0
    base_bool->state = booldatum->state;
636
0
  } else if ((booldatum->flags & COND_BOOL_FLAGS_TUNABLE) !=
637
0
       (base_bool->flags & COND_BOOL_FLAGS_TUNABLE)) {
638
      /* A mismatch between boolean/tunable declaration
639
       * and usage(for example a boolean used in the
640
       * tunable_policy() or vice versa).
641
       *
642
       * This is not allowed and bail out with errors */
643
0
      ERR(state->handle,
644
0
          "%s: Mismatch between boolean/tunable definition "
645
0
          "and usage for %s", state->cur_mod_name, id);
646
0
      return -1;
647
0
  }
648
649
  /* Get the scope info for this boolean to see if this is the declaration, 
650
   * if so set the state */
651
0
  scope = hashtab_search(state->cur->policy->p_bools_scope.table, id);
652
0
  if (!scope)
653
0
    return SEPOL_ERR;
654
0
  if (scope->scope == SCOPE_DECL) {
655
0
    base_bool->state = booldatum->state;
656
    /* Only the declaration rather than requirement
657
     * decides if it is a boolean or tunable. */
658
0
    base_bool->flags = booldatum->flags;
659
0
  }
660
0
  state->cur->map[SYM_BOOLS][booldatum->s.value - 1] = base_bool->s.value;
661
0
  return 0;
662
663
0
      cleanup:
664
0
  ERR(state->handle, "Out of memory!");
665
0
  cond_destroy_bool(new_id, new_bool, NULL);
666
0
  return -1;
667
0
}
668
669
static int sens_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
670
            void *data)
671
0
{
672
0
  char *id = key;
673
0
  level_datum_t *level, *base_level;
674
0
  link_state_t *state = (link_state_t *) data;
675
0
  scope_datum_t *scope;
676
677
0
  level = (level_datum_t *) datum;
678
679
0
  base_level = hashtab_search(state->base->p_levels.table, id);
680
0
  if (!base_level) {
681
0
    scope =
682
0
        hashtab_search(state->cur->policy->p_sens_scope.table, id);
683
0
    if (!scope)
684
0
      return SEPOL_ERR;
685
0
    if (scope->scope == SCOPE_DECL) {
686
      /* disallow declarations in modules */
687
0
      ERR(state->handle,
688
0
          "%s: Modules may not declare new sensitivities.",
689
0
          state->cur_mod_name);
690
0
      return SEPOL_ENOTSUP;
691
0
    } else if (scope->scope == SCOPE_REQ) {
692
      /* unmet requirement */
693
0
      ERR(state->handle,
694
0
          "%s: Sensitivity %s not declared by base.",
695
0
          state->cur_mod_name, id);
696
0
      return SEPOL_ENOTSUP;
697
0
    } else {
698
0
      ERR(state->handle,
699
0
          "%s: has an unknown scope: %d",
700
0
          state->cur_mod_name, scope->scope);
701
0
      return SEPOL_ENOTSUP;
702
0
    }
703
0
  }
704
705
0
  state->cur->map[SYM_LEVELS][level->level->sens - 1] =
706
0
      base_level->level->sens;
707
708
0
  return 0;
709
0
}
710
711
static int cat_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
712
           void *data)
713
0
{
714
0
  char *id = key;
715
0
  cat_datum_t *cat, *base_cat;
716
0
  link_state_t *state = (link_state_t *) data;
717
0
  scope_datum_t *scope;
718
719
0
  cat = (cat_datum_t *) datum;
720
721
0
  base_cat = hashtab_search(state->base->p_cats.table, id);
722
0
  if (!base_cat) {
723
0
    scope = hashtab_search(state->cur->policy->p_cat_scope.table, id);
724
0
    if (!scope)
725
0
      return SEPOL_ERR;
726
0
    if (scope->scope == SCOPE_DECL) {
727
      /* disallow declarations in modules */
728
0
      ERR(state->handle,
729
0
          "%s: Modules may not declare new categories.",
730
0
          state->cur_mod_name);
731
0
      return SEPOL_ENOTSUP;
732
0
    } else if (scope->scope == SCOPE_REQ) {
733
      /* unmet requirement */
734
0
      ERR(state->handle,
735
0
          "%s: Category %s not declared by base.",
736
0
          state->cur_mod_name, id);
737
0
      return SEPOL_ENOTSUP;
738
0
    } else {
739
      /* unknown scope?  malformed policy? */
740
0
      ERR(state->handle,
741
0
          "%s: has an unknown scope: %d",
742
0
          state->cur_mod_name, scope->scope);
743
0
      return SEPOL_ENOTSUP;
744
0
    }
745
0
  }
746
747
0
  state->cur->map[SYM_CATS][cat->s.value - 1] = base_cat->s.value;
748
749
0
  return 0;
750
0
}
751
752
static int (*const copy_callback_f[SYM_NUM]) (hashtab_key_t key,
753
          hashtab_datum_t datum, void *datap) = {
754
NULL, class_copy_callback, role_copy_callback, type_copy_callback,
755
      user_copy_callback, bool_copy_callback, sens_copy_callback,
756
      cat_copy_callback};
757
758
/*
759
 * The boundaries have to be copied after the types/roles/users are copied,
760
 * because it refers hashtab to lookup destinated objects.
761
 */
762
static int type_bounds_copy_callback(hashtab_key_t key,
763
             hashtab_datum_t datum, void *data)
764
0
{
765
0
  link_state_t *state = (link_state_t *) data;
766
0
  type_datum_t *type = (type_datum_t *) datum;
767
0
  type_datum_t *dest;
768
0
  uint32_t bounds_val;
769
0
  hashtab_t type_tab;
770
771
0
  if (!type->bounds)
772
0
    return 0;
773
774
0
  if (state->dest_decl == NULL)
775
0
    type_tab = state->base->p_types.table;
776
0
  else
777
0
    type_tab = state->dest_decl->p_types.table;
778
779
0
  bounds_val = state->cur->map[SYM_TYPES][type->bounds - 1];
780
781
0
  dest = hashtab_search(type_tab, key);
782
0
  if (!dest) {
783
0
    ERR(state->handle,
784
0
        "Type lookup failed for %s", (char *)key);
785
0
    return -1;
786
0
  }
787
0
  if (dest->bounds != 0 && dest->bounds != bounds_val) {
788
0
    ERR(state->handle,
789
0
        "Inconsistent boundary for %s", (char *)key);
790
0
    return -1;
791
0
  }
792
0
  dest->bounds = bounds_val;
793
794
0
  return 0;
795
0
}
796
797
static int role_bounds_copy_callback(hashtab_key_t key,
798
             hashtab_datum_t datum, void *data)
799
0
{
800
0
  link_state_t *state = (link_state_t *) data;
801
0
  role_datum_t *role = (role_datum_t *) datum;
802
0
  role_datum_t *dest;
803
0
  uint32_t bounds_val;
804
0
  hashtab_t role_tab;
805
806
0
  if (!role->bounds)
807
0
    return 0;
808
809
0
  if (state->dest_decl == NULL)
810
0
    role_tab = state->base->p_roles.table;
811
0
  else
812
0
    role_tab = state->dest_decl->p_roles.table;
813
814
0
  bounds_val = state->cur->map[SYM_ROLES][role->bounds - 1];
815
816
0
  dest = hashtab_search(role_tab, key);
817
0
  if (!dest) {
818
0
    ERR(state->handle,
819
0
        "Role lookup failed for %s", (char *)key);
820
0
    return -1;
821
0
  }
822
0
  if (dest->bounds != 0 && dest->bounds != bounds_val) {
823
0
    ERR(state->handle,
824
0
        "Inconsistent boundary for %s", (char *)key);
825
0
    return -1;
826
0
  }
827
0
  dest->bounds = bounds_val;
828
829
0
  return 0;
830
0
}
831
832
static int user_bounds_copy_callback(hashtab_key_t key,
833
             hashtab_datum_t datum, void *data)
834
0
{
835
0
  link_state_t *state = (link_state_t *) data;
836
0
  user_datum_t *user = (user_datum_t *) datum;
837
0
  user_datum_t *dest;
838
0
  uint32_t bounds_val;
839
0
  hashtab_t user_tab;
840
841
0
  if (!user->bounds)
842
0
    return 0;
843
844
0
  if (state->dest_decl == NULL)
845
0
    user_tab = state->base->p_users.table;
846
0
  else
847
0
    user_tab = state->dest_decl->p_users.table;
848
849
0
  bounds_val = state->cur->map[SYM_USERS][user->bounds - 1];
850
851
0
  dest = hashtab_search(user_tab, key);
852
0
  if (!dest) {
853
0
    ERR(state->handle,
854
0
        "User lookup failed for %s", (char *)key);
855
0
    return -1;
856
0
  }
857
0
  if (dest->bounds != 0 && dest->bounds != bounds_val) {
858
0
    ERR(state->handle,
859
0
        "Inconsistent boundary for %s", (char *)key);
860
0
    return -1;
861
0
  }
862
0
  dest->bounds = bounds_val;
863
864
0
  return 0;
865
0
}
866
867
/* The aliases have to be copied after the types and attributes to be
868
 * certain that the base symbol table will have the type that the
869
 * alias refers. Otherwise, we won't be able to find the type value
870
 * for the alias. We can't depend on the declaration ordering because
871
 * of the hash table.
872
 */
873
static int alias_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
874
             void *data)
875
0
{
876
0
  char *id = key, *new_id = NULL, *target_id;
877
0
  type_datum_t *type, *base_type, *new_type = NULL, *target_type;
878
0
  link_state_t *state = (link_state_t *) data;
879
0
  policy_module_t *mod = state->cur;
880
0
  int primval;
881
882
0
  type = (type_datum_t *) datum;
883
  /* there are 2 kinds of aliases. Ones with their own value (TYPE_ALIAS)
884
   * and ones with the value of their primary (TYPE_TYPE && type->primary = 0)
885
   */
886
0
  if (!
887
0
      (type->flavor == TYPE_ALIAS
888
0
       || (type->flavor == TYPE_TYPE && !type->primary))) {
889
    /* ignore types and attributes -- they were handled in
890
     * type_copy_callback() */
891
0
    return 0;
892
0
  }
893
894
0
  if (type->flavor == TYPE_ALIAS)
895
0
    primval = type->primary;
896
0
  else
897
0
    primval = type->s.value;
898
899
0
  target_id = mod->policy->p_type_val_to_name[primval - 1];
900
0
  target_type = hashtab_search(state->base->p_types.table, target_id);
901
0
  if (target_type == NULL) {
902
0
    ERR(state->handle, "%s: Could not find type %s for alias %s.",
903
0
        state->cur_mod_name, target_id, id);
904
0
    return -1;
905
0
  }
906
907
0
  if (!strcmp(id, target_id)) {
908
0
    ERR(state->handle, "%s: Self aliasing of %s.",
909
0
        state->cur_mod_name, id);
910
0
    return -1;
911
0
  }
912
913
0
  target_type->flags |= type->flags;
914
915
0
  base_type = hashtab_search(state->base->p_types.table, id);
916
0
  if (base_type == NULL) {
917
0
    if (state->verbose)
918
0
      INFO(state->handle, "copying alias %s", id);
919
920
0
    if ((new_type =
921
0
         (type_datum_t *) calloc(1, sizeof(*new_type))) == NULL) {
922
0
      goto cleanup;
923
0
    }
924
    /* the linked copy always has TYPE_ALIAS style aliases */
925
0
    new_type->primary = target_type->s.value;
926
0
    new_type->flags = target_type->flags;
927
0
    new_type->flavor = TYPE_ALIAS;
928
0
    new_type->s.value = state->base->p_types.nprim + 1;
929
0
    if ((new_id = strdup(id)) == NULL) {
930
0
      goto cleanup;
931
0
    }
932
0
    if (hashtab_insert
933
0
        (state->base->p_types.table, new_id, new_type)) {
934
0
      goto cleanup;
935
0
    }
936
0
    state->base->p_types.nprim++;
937
0
    base_type = new_type;
938
0
  } else {
939
940
    /* if this already exists and isn't an alias it was required by another module (or base)
941
     * and inserted into the hashtable as a type, fix it up now */
942
943
0
    if (base_type->flavor == TYPE_ALIAS) {
944
      /* error checking */
945
0
      assert(base_type->primary == target_type->s.value);
946
0
      assert(base_type->primary ==
947
0
             mod->map[SYM_TYPES][primval - 1]);
948
0
      assert(mod->map[SYM_TYPES][type->s.value - 1] ==
949
0
             base_type->primary);
950
0
      return 0;
951
0
    }
952
953
0
    if (base_type->flavor == TYPE_ATTRIB) {
954
0
      ERR(state->handle,
955
0
          "%s is an alias of an attribute, not allowed", id);
956
0
      return -1;
957
0
    }
958
959
0
    base_type->flavor = TYPE_ALIAS;
960
0
    base_type->primary = target_type->s.value;
961
0
    base_type->flags |= target_type->flags;
962
963
0
  }
964
  /* the aliases map points from its value to its primary so when this module 
965
   * references this type the value it gets back from the map is the primary */
966
0
  mod->map[SYM_TYPES][type->s.value - 1] = base_type->primary;
967
968
0
  return 0;
969
970
0
      cleanup:
971
0
  ERR(state->handle, "Out of memory!");
972
0
  free(new_id);
973
0
  free(new_type);
974
0
  return -1;
975
0
}
976
977
/*********** callbacks that fix bitmaps ***********/
978
979
static int ebitmap_convert(const ebitmap_t *src, ebitmap_t *dst, const uint32_t *map)
980
0
{
981
0
  unsigned int bit;
982
0
  ebitmap_node_t *node;
983
0
  ebitmap_for_each_positive_bit(src, node, bit) {
984
0
    assert(map[bit]);
985
0
    if (ebitmap_set_bit(dst, map[bit] - 1, 1))
986
0
      return -1;
987
0
  }
988
989
0
  return 0;
990
0
}
991
992
static int type_set_convert(const type_set_t * types, type_set_t * dst,
993
          const policy_module_t * mod)
994
0
{
995
0
  if (ebitmap_convert(&types->types, &dst->types, mod->map[SYM_TYPES]))
996
0
    goto cleanup;
997
998
0
  if (ebitmap_convert(&types->negset, &dst->negset, mod->map[SYM_TYPES]))
999
0
    goto cleanup;
1000
1001
0
  dst->flags = types->flags;
1002
0
  return 0;
1003
1004
0
      cleanup:
1005
0
  return -1;
1006
0
}
1007
1008
/* OR 2 typemaps together and at the same time map the src types to
1009
 * the correct values in the dst typeset.
1010
 */
1011
static int type_set_or_convert(const type_set_t * types, type_set_t * dst,
1012
             const policy_module_t * mod)
1013
0
{
1014
0
  type_set_t ts_tmp;
1015
1016
0
  type_set_init(&ts_tmp);
1017
0
  if (type_set_convert(types, &ts_tmp, mod) == -1) {
1018
0
    goto cleanup;
1019
0
  }
1020
0
  if (type_set_or_eq(dst, &ts_tmp)) {
1021
0
    goto cleanup;
1022
0
  }
1023
0
  type_set_destroy(&ts_tmp);
1024
0
  return 0;
1025
1026
0
      cleanup:
1027
0
  type_set_destroy(&ts_tmp);
1028
0
  return -1;
1029
0
}
1030
1031
static int role_set_or_convert(role_set_t * roles, role_set_t * dst,
1032
             policy_module_t * mod, link_state_t * state)
1033
0
{
1034
0
  ebitmap_t tmp;
1035
1036
0
  ebitmap_init(&tmp);
1037
0
  if (ebitmap_convert(&roles->roles, &tmp, mod->map[SYM_ROLES]))
1038
0
    goto cleanup;
1039
0
  if (ebitmap_union(&dst->roles, &tmp)) {
1040
0
    goto cleanup;
1041
0
  }
1042
0
  dst->flags |= roles->flags;
1043
0
  ebitmap_destroy(&tmp);
1044
0
  return 0;
1045
0
      cleanup:
1046
0
  ERR(state->handle, "Out of memory!");
1047
0
  ebitmap_destroy(&tmp);
1048
0
  return -1;
1049
0
}
1050
1051
static int mls_level_convert(mls_semantic_level_t * src, mls_semantic_level_t * dst,
1052
           policy_module_t * mod, link_state_t * state)
1053
0
{
1054
0
  mls_semantic_cat_t *src_cat, *new_cat;
1055
1056
0
  if (!mod->policy->mls)
1057
0
    return 0;
1058
1059
  /* Required not declared. */
1060
0
  if (!src->sens)
1061
0
    return 0;
1062
1063
0
  assert(mod->map[SYM_LEVELS][src->sens - 1]);
1064
0
  dst->sens = mod->map[SYM_LEVELS][src->sens - 1];
1065
1066
0
  for (src_cat = src->cat; src_cat; src_cat = src_cat->next) {
1067
0
    new_cat =
1068
0
        (mls_semantic_cat_t *) malloc(sizeof(mls_semantic_cat_t));
1069
0
    if (!new_cat) {
1070
0
      ERR(state->handle, "Out of memory");
1071
0
      return -1;
1072
0
    }
1073
0
    mls_semantic_cat_init(new_cat);
1074
1075
0
    new_cat->next = dst->cat;
1076
0
    dst->cat = new_cat;
1077
1078
0
    assert(mod->map[SYM_CATS][src_cat->low - 1]);
1079
0
    dst->cat->low = mod->map[SYM_CATS][src_cat->low - 1];
1080
0
    assert(mod->map[SYM_CATS][src_cat->high - 1]);
1081
0
    dst->cat->high = mod->map[SYM_CATS][src_cat->high - 1];
1082
0
  }
1083
1084
0
  return 0;
1085
0
}
1086
1087
static int mls_range_convert(mls_semantic_range_t * src, mls_semantic_range_t * dst,
1088
           policy_module_t * mod, link_state_t * state)
1089
0
{
1090
0
  int ret;
1091
0
  ret = mls_level_convert(&src->level[0], &dst->level[0], mod, state);
1092
0
  if (ret)
1093
0
    return ret;
1094
0
  ret = mls_level_convert(&src->level[1], &dst->level[1], mod, state);
1095
0
  if (ret)
1096
0
    return ret;
1097
0
  return 0;
1098
0
}
1099
1100
static int role_fix_callback(hashtab_key_t key, hashtab_datum_t datum,
1101
           void *data)
1102
0
{
1103
0
  char *id = key;
1104
0
  role_datum_t *role, *dest_role = NULL;
1105
0
  link_state_t *state = (link_state_t *) data;
1106
0
  ebitmap_t e_tmp;
1107
0
  policy_module_t *mod = state->cur;
1108
0
  hashtab_t role_tab;
1109
1110
0
  role = (role_datum_t *) datum;
1111
0
  if (state->dest_decl == NULL)
1112
0
    role_tab = state->base->p_roles.table;
1113
0
  else
1114
0
    role_tab = state->dest_decl->p_roles.table;
1115
1116
0
  dest_role = hashtab_search(role_tab, id);
1117
0
  assert(dest_role != NULL);
1118
1119
0
  if (state->verbose) {
1120
0
    INFO(state->handle, "fixing role %s", id);
1121
0
  }
1122
1123
0
  ebitmap_init(&e_tmp);
1124
0
  if (ebitmap_convert(&role->dominates, &e_tmp, mod->map[SYM_ROLES]))
1125
0
    goto cleanup;
1126
0
  if (ebitmap_union(&dest_role->dominates, &e_tmp)) {
1127
0
    goto cleanup;
1128
0
  }
1129
0
  if (type_set_or_convert(&role->types, &dest_role->types, mod)) {
1130
0
    goto cleanup;
1131
0
  }
1132
0
  ebitmap_destroy(&e_tmp);
1133
  
1134
0
  if (role->flavor == ROLE_ATTRIB) {
1135
0
    ebitmap_init(&e_tmp);
1136
0
    if (ebitmap_convert(&role->roles, &e_tmp, mod->map[SYM_ROLES]))
1137
0
      goto cleanup;
1138
0
    if (ebitmap_union(&dest_role->roles, &e_tmp)) {
1139
0
      goto cleanup;
1140
0
    }
1141
0
    ebitmap_destroy(&e_tmp);
1142
0
  }
1143
1144
0
  return 0;
1145
1146
0
      cleanup:
1147
0
  ERR(state->handle, "Out of memory!");
1148
0
  ebitmap_destroy(&e_tmp);
1149
0
  return -1;
1150
0
}
1151
1152
static int type_fix_callback(hashtab_key_t key, hashtab_datum_t datum,
1153
           void *data)
1154
0
{
1155
0
  char *id = key;
1156
0
  type_datum_t *type, *new_type = NULL;
1157
0
  link_state_t *state = (link_state_t *) data;
1158
0
  ebitmap_t e_tmp;
1159
0
  policy_module_t *mod = state->cur;
1160
0
  symtab_t *typetab;
1161
1162
0
  type = (type_datum_t *) datum;
1163
1164
0
  if (state->dest_decl == NULL)
1165
0
    typetab = &state->base->p_types;
1166
0
  else
1167
0
    typetab = &state->dest_decl->p_types;
1168
1169
  /* only fix attributes */
1170
0
  if (type->flavor != TYPE_ATTRIB) {
1171
0
    return 0;
1172
0
  }
1173
1174
0
  new_type = hashtab_search(typetab->table, id);
1175
0
  assert(new_type != NULL && new_type->flavor == TYPE_ATTRIB);
1176
1177
0
  if (state->verbose) {
1178
0
    INFO(state->handle, "fixing attribute %s", id);
1179
0
  }
1180
1181
0
  ebitmap_init(&e_tmp);
1182
0
  if (ebitmap_convert(&type->types, &e_tmp, mod->map[SYM_TYPES]))
1183
0
    goto cleanup;
1184
0
  if (ebitmap_union(&new_type->types, &e_tmp)) {
1185
0
    goto cleanup;
1186
0
  }
1187
0
  ebitmap_destroy(&e_tmp);
1188
0
  return 0;
1189
1190
0
      cleanup:
1191
0
  ERR(state->handle, "Out of memory!");
1192
0
  ebitmap_destroy(&e_tmp);
1193
0
  return -1;
1194
0
}
1195
1196
static int user_fix_callback(hashtab_key_t key, hashtab_datum_t datum,
1197
           void *data)
1198
0
{
1199
0
  char *id = key;
1200
0
  user_datum_t *user, *new_user = NULL;
1201
0
  link_state_t *state = (link_state_t *) data;
1202
0
  policy_module_t *mod = state->cur;
1203
0
  symtab_t *usertab;
1204
1205
0
  user = (user_datum_t *) datum;
1206
1207
0
  if (state->dest_decl == NULL)
1208
0
    usertab = &state->base->p_users;
1209
0
  else
1210
0
    usertab = &state->dest_decl->p_users;
1211
1212
0
  new_user = hashtab_search(usertab->table, id);
1213
0
  assert(new_user != NULL);
1214
1215
0
  if (state->verbose) {
1216
0
    INFO(state->handle, "fixing user %s", id);
1217
0
  }
1218
1219
0
  if (role_set_or_convert(&user->roles, &new_user->roles, mod, state)) {
1220
0
    goto cleanup;
1221
0
  }
1222
1223
0
  if (mls_range_convert(&user->range, &new_user->range, mod, state))
1224
0
    goto cleanup;
1225
1226
0
  if (mls_level_convert(&user->dfltlevel, &new_user->dfltlevel, mod, state))
1227
0
    goto cleanup;
1228
1229
0
  return 0;
1230
1231
0
      cleanup:
1232
0
  ERR(state->handle, "Out of memory!");
1233
0
  return -1;
1234
0
}
1235
1236
static int (*const fix_callback_f[SYM_NUM]) (hashtab_key_t key, hashtab_datum_t datum,
1237
               void *datap) = {
1238
NULL, NULL, role_fix_callback, type_fix_callback, user_fix_callback,
1239
      NULL, NULL, NULL};
1240
1241
/*********** functions that copy AV rules ***********/
1242
1243
static int copy_avrule_list(avrule_t * list, avrule_t ** dst,
1244
          policy_module_t * module, link_state_t * state)
1245
0
{
1246
0
  unsigned int i;
1247
0
  avrule_t *cur, *new_rule = NULL, *tail;
1248
0
  class_perm_node_t *cur_perm, *new_perm, *tail_perm = NULL;
1249
1250
0
  tail = *dst;
1251
0
  while (tail && tail->next) {
1252
0
    tail = tail->next;
1253
0
  }
1254
1255
0
  cur = list;
1256
0
  while (cur) {
1257
0
    if ((new_rule = (avrule_t *) malloc(sizeof(avrule_t))) == NULL) {
1258
0
      goto cleanup;
1259
0
    }
1260
0
    avrule_init(new_rule);
1261
1262
0
    new_rule->specified = cur->specified;
1263
0
    new_rule->flags = cur->flags;
1264
0
    if (type_set_convert
1265
0
        (&cur->stypes, &new_rule->stypes, module) == -1
1266
0
        || type_set_convert(&cur->ttypes, &new_rule->ttypes, module) == -1) {
1267
0
      goto cleanup;
1268
0
    }
1269
1270
0
    cur_perm = cur->perms;
1271
0
    tail_perm = NULL;
1272
0
    while (cur_perm) {
1273
0
      if ((new_perm = (class_perm_node_t *)
1274
0
           malloc(sizeof(class_perm_node_t))) == NULL) {
1275
0
        goto cleanup;
1276
0
      }
1277
0
      class_perm_node_init(new_perm);
1278
1279
0
      new_perm->tclass =
1280
0
          module->map[SYM_CLASSES][cur_perm->tclass - 1];
1281
0
      assert(new_perm->tclass);
1282
1283
0
      if (new_rule->specified & AVRULE_AV) {
1284
0
        for (i = 0;
1285
0
             i <
1286
0
             module->perm_map_len[cur_perm->tclass - 1];
1287
0
             i++) {
1288
0
          if (!(cur_perm->data & (UINT32_C(1) << i)))
1289
0
            continue;
1290
0
          new_perm->data |=
1291
0
              (UINT32_C(1) <<
1292
0
               (module->
1293
0
                perm_map[cur_perm->tclass - 1][i] -
1294
0
                1));
1295
0
        }
1296
0
      } else {
1297
0
        new_perm->data =
1298
0
            module->map[SYM_TYPES][cur_perm->data - 1];
1299
0
      }
1300
1301
0
      if (new_rule->perms == NULL) {
1302
0
        new_rule->perms = new_perm;
1303
0
      } else {
1304
0
        assert(tail_perm);
1305
0
        tail_perm->next = new_perm;
1306
0
      }
1307
0
      tail_perm = new_perm;
1308
0
      cur_perm = cur_perm->next;
1309
0
    }
1310
1311
0
    if (cur->xperms) {
1312
0
      new_rule->xperms = calloc(1, sizeof(*new_rule->xperms));
1313
0
      if (!new_rule->xperms)
1314
0
        goto cleanup;
1315
0
      memcpy(new_rule->xperms, cur->xperms,
1316
0
             sizeof(*new_rule->xperms));
1317
0
    }
1318
1319
0
    new_rule->line = cur->line;
1320
0
    new_rule->source_line = cur->source_line;
1321
0
    if (cur->source_filename) {
1322
0
      new_rule->source_filename = strdup(cur->source_filename);
1323
0
      if (!new_rule->source_filename)
1324
0
        goto cleanup;
1325
0
    }
1326
1327
0
    cur = cur->next;
1328
1329
0
    if (*dst == NULL) {
1330
0
      *dst = new_rule;
1331
0
    } else {
1332
0
      tail->next = new_rule;
1333
0
    }
1334
0
    tail = new_rule;
1335
0
  }
1336
1337
0
  return 0;
1338
0
      cleanup:
1339
0
  ERR(state->handle, "Out of memory!");
1340
0
  avrule_destroy(new_rule);
1341
0
  free(new_rule);
1342
0
  return -1;
1343
0
}
1344
1345
static int copy_role_trans_list(role_trans_rule_t * list,
1346
        role_trans_rule_t ** dst,
1347
        policy_module_t * module, link_state_t * state)
1348
0
{
1349
0
  role_trans_rule_t *cur, *new_rule = NULL, *tail;
1350
1351
0
  cur = list;
1352
0
  tail = *dst;
1353
0
  while (tail && tail->next) {
1354
0
    tail = tail->next;
1355
0
  }
1356
0
  while (cur) {
1357
0
    if ((new_rule =
1358
0
         (role_trans_rule_t *) malloc(sizeof(role_trans_rule_t))) ==
1359
0
        NULL) {
1360
0
      goto cleanup;
1361
0
    }
1362
0
    role_trans_rule_init(new_rule);
1363
1364
0
    if (role_set_or_convert
1365
0
        (&cur->roles, &new_rule->roles, module, state)
1366
0
        || type_set_or_convert(&cur->types, &new_rule->types,
1367
0
             module)) {
1368
0
      goto cleanup;
1369
0
    }
1370
1371
0
    if (ebitmap_convert(&cur->classes, &new_rule->classes, module->map[SYM_CLASSES]))
1372
0
      goto cleanup;
1373
1374
0
    new_rule->new_role = module->map[SYM_ROLES][cur->new_role - 1];
1375
1376
0
    if (*dst == NULL) {
1377
0
      *dst = new_rule;
1378
0
    } else {
1379
0
      tail->next = new_rule;
1380
0
    }
1381
0
    tail = new_rule;
1382
0
    cur = cur->next;
1383
0
  }
1384
0
  return 0;
1385
0
      cleanup:
1386
0
  ERR(state->handle, "Out of memory!");
1387
0
  role_trans_rule_list_destroy(new_rule);
1388
0
  return -1;
1389
0
}
1390
1391
static int copy_role_allow_list(role_allow_rule_t * list,
1392
        role_allow_rule_t ** dst,
1393
        policy_module_t * module, link_state_t * state)
1394
0
{
1395
0
  role_allow_rule_t *cur, *new_rule = NULL, *tail;
1396
1397
0
  cur = list;
1398
0
  tail = *dst;
1399
0
  while (tail && tail->next) {
1400
0
    tail = tail->next;
1401
0
  }
1402
1403
0
  while (cur) {
1404
0
    if ((new_rule =
1405
0
         (role_allow_rule_t *) malloc(sizeof(role_allow_rule_t))) ==
1406
0
        NULL) {
1407
0
      goto cleanup;
1408
0
    }
1409
0
    role_allow_rule_init(new_rule);
1410
1411
0
    if (role_set_or_convert
1412
0
        (&cur->roles, &new_rule->roles, module, state)
1413
0
        || role_set_or_convert(&cur->new_roles,
1414
0
             &new_rule->new_roles, module,
1415
0
             state)) {
1416
0
      goto cleanup;
1417
0
    }
1418
0
    if (*dst == NULL) {
1419
0
      *dst = new_rule;
1420
0
    } else {
1421
0
      tail->next = new_rule;
1422
0
    }
1423
0
    tail = new_rule;
1424
0
    cur = cur->next;
1425
0
  }
1426
0
  return 0;
1427
0
      cleanup:
1428
0
  ERR(state->handle, "Out of memory!");
1429
0
  role_allow_rule_list_destroy(new_rule);
1430
0
  return -1;
1431
0
}
1432
1433
static int copy_filename_trans_list(filename_trans_rule_t * list,
1434
            filename_trans_rule_t ** dst,
1435
            policy_module_t * module,
1436
            link_state_t * state)
1437
0
{
1438
0
  filename_trans_rule_t *cur, *new_rule, *tail;
1439
1440
0
  cur = list;
1441
0
  tail = *dst;
1442
0
  while (tail && tail->next)
1443
0
    tail = tail->next;
1444
1445
0
  while (cur) {
1446
0
    new_rule = malloc(sizeof(*new_rule));
1447
0
    if (!new_rule)
1448
0
      goto err;
1449
1450
0
    filename_trans_rule_init(new_rule);
1451
1452
0
    if (*dst == NULL)
1453
0
      *dst = new_rule;
1454
0
    else
1455
0
      tail->next = new_rule;
1456
0
    tail = new_rule;
1457
1458
0
    new_rule->name = strdup(cur->name);
1459
0
    if (!new_rule->name)
1460
0
      goto err;
1461
1462
0
    if (type_set_or_convert(&cur->stypes, &new_rule->stypes, module) ||
1463
0
        type_set_or_convert(&cur->ttypes, &new_rule->ttypes, module))
1464
0
      goto err;
1465
1466
0
    new_rule->tclass = module->map[SYM_CLASSES][cur->tclass - 1];
1467
0
    new_rule->otype = module->map[SYM_TYPES][cur->otype - 1];
1468
0
    new_rule->flags = cur->flags;
1469
1470
0
    cur = cur->next;
1471
0
  }
1472
0
  return 0;
1473
0
err:
1474
0
  ERR(state->handle, "Out of memory!");
1475
0
  return -1;
1476
0
}
1477
1478
static int copy_range_trans_list(range_trans_rule_t * rules,
1479
         range_trans_rule_t ** dst,
1480
         policy_module_t * mod, link_state_t * state)
1481
0
{
1482
0
  range_trans_rule_t *rule, *new_rule = NULL;
1483
1484
0
  for (rule = rules; rule; rule = rule->next) {
1485
0
    new_rule =
1486
0
        (range_trans_rule_t *) malloc(sizeof(range_trans_rule_t));
1487
0
    if (!new_rule)
1488
0
      goto cleanup;
1489
1490
0
    range_trans_rule_init(new_rule);
1491
1492
0
    new_rule->next = *dst;
1493
0
    *dst = new_rule;
1494
1495
0
    if (type_set_convert(&rule->stypes, &new_rule->stypes,
1496
0
             mod))
1497
0
      goto cleanup;
1498
1499
0
    if (type_set_convert(&rule->ttypes, &new_rule->ttypes,
1500
0
             mod))
1501
0
      goto cleanup;
1502
1503
0
    if (ebitmap_convert(&rule->tclasses, &new_rule->tclasses, mod->map[SYM_CLASSES]))
1504
0
      goto cleanup;
1505
1506
0
    if (mls_range_convert(&rule->trange, &new_rule->trange, mod, state))
1507
0
      goto cleanup;
1508
0
  }
1509
0
  return 0;
1510
1511
0
      cleanup:
1512
0
  ERR(state->handle, "Out of memory!");
1513
0
  range_trans_rule_list_destroy(new_rule);
1514
0
  return -1;
1515
0
}
1516
1517
static int copy_cond_list(cond_node_t * list, cond_node_t ** dst,
1518
        policy_module_t * module, link_state_t * state)
1519
0
{
1520
0
  unsigned i;
1521
0
  cond_node_t *cur, *new_node = NULL, *tail;
1522
0
  cond_expr_t *cur_expr;
1523
0
  tail = *dst;
1524
0
  while (tail && tail->next)
1525
0
    tail = tail->next;
1526
1527
0
  cur = list;
1528
0
  while (cur) {
1529
0
    new_node = (cond_node_t *) malloc(sizeof(cond_node_t));
1530
0
    if (!new_node) {
1531
0
      goto cleanup;
1532
0
    }
1533
0
    memset(new_node, 0, sizeof(cond_node_t));
1534
1535
0
    new_node->cur_state = cur->cur_state;
1536
0
    new_node->expr = cond_copy_expr(cur->expr);
1537
0
    if (!new_node->expr)
1538
0
      goto cleanup;
1539
    /* go back through and remap the expression */
1540
0
    for (cur_expr = new_node->expr; cur_expr != NULL;
1541
0
         cur_expr = cur_expr->next) {
1542
      /* expression nodes don't have a bool value of 0 - don't map them */
1543
0
      if (cur_expr->expr_type != COND_BOOL)
1544
0
        continue;
1545
0
      assert(module->map[SYM_BOOLS][cur_expr->boolean - 1] != 0);
1546
0
      cur_expr->boolean =
1547
0
          module->map[SYM_BOOLS][cur_expr->boolean - 1];
1548
0
    }
1549
0
    new_node->nbools = cur->nbools;
1550
    /* FIXME should COND_MAX_BOOLS be used here? */
1551
0
    for (i = 0; i < min(cur->nbools, COND_MAX_BOOLS); i++) {
1552
0
      uint32_t remapped_id =
1553
0
          module->map[SYM_BOOLS][cur->bool_ids[i] - 1];
1554
0
      assert(remapped_id != 0);
1555
0
      new_node->bool_ids[i] = remapped_id;
1556
0
    }
1557
0
    new_node->expr_pre_comp = cur->expr_pre_comp;
1558
1559
0
    if (copy_avrule_list
1560
0
        (cur->avtrue_list, &new_node->avtrue_list, module, state)
1561
0
        || copy_avrule_list(cur->avfalse_list,
1562
0
          &new_node->avfalse_list, module,
1563
0
          state)) {
1564
0
      goto cleanup;
1565
0
    }
1566
1567
0
    if (*dst == NULL) {
1568
0
      *dst = new_node;
1569
0
    } else {
1570
0
      tail->next = new_node;
1571
0
    }
1572
0
    tail = new_node;
1573
0
    cur = cur->next;
1574
0
  }
1575
0
  return 0;
1576
0
      cleanup:
1577
0
  ERR(state->handle, "Out of memory!");
1578
0
  cond_node_destroy(new_node);
1579
0
  free(new_node);
1580
0
  return -1;
1581
1582
0
}
1583
1584
/*********** functions that copy avrule_decls from module to base ***********/
1585
1586
static int copy_identifiers(link_state_t * state, symtab_t * src_symtab,
1587
          avrule_decl_t * dest_decl)
1588
0
{
1589
0
  int i, ret;
1590
1591
0
  state->dest_decl = dest_decl;
1592
0
  for (i = 0; i < SYM_NUM; i++) {
1593
0
    if (copy_callback_f[i] != NULL) {
1594
0
      ret =
1595
0
          hashtab_map(src_symtab[i].table, copy_callback_f[i],
1596
0
          state);
1597
0
      if (ret) {
1598
0
        return ret;
1599
0
      }
1600
0
    }
1601
0
  }
1602
1603
0
  if (hashtab_map(src_symtab[SYM_TYPES].table,
1604
0
      type_bounds_copy_callback, state))
1605
0
    return -1;
1606
1607
0
  if (hashtab_map(src_symtab[SYM_TYPES].table,
1608
0
      alias_copy_callback, state))
1609
0
    return -1;
1610
1611
0
  if (hashtab_map(src_symtab[SYM_ROLES].table,
1612
0
      role_bounds_copy_callback, state))
1613
0
    return -1;
1614
1615
0
  if (hashtab_map(src_symtab[SYM_USERS].table,
1616
0
      user_bounds_copy_callback, state))
1617
0
    return -1;
1618
1619
  /* then fix bitmaps associated with those newly copied identifiers */
1620
0
  for (i = 0; i < SYM_NUM; i++) {
1621
0
    if (fix_callback_f[i] != NULL &&
1622
0
        hashtab_map(src_symtab[i].table, fix_callback_f[i],
1623
0
        state)) {
1624
0
      return -1;
1625
0
    }
1626
0
  }
1627
0
  return 0;
1628
0
}
1629
1630
static int copy_scope_index(scope_index_t * src, scope_index_t * dest,
1631
          policy_module_t * module, link_state_t * state)
1632
0
{
1633
0
  unsigned int i, j;
1634
0
  uint32_t largest_mapped_class_value = 0;
1635
0
  ebitmap_node_t *node;
1636
  /* copy the scoping information for this avrule decl block */
1637
0
  for (i = 0; i < SYM_NUM; i++) {
1638
0
    ebitmap_t *srcmap = src->scope + i;
1639
0
    ebitmap_t *destmap = dest->scope + i;
1640
0
    if (copy_callback_f[i] == NULL) {
1641
0
      continue;
1642
0
    }
1643
0
    ebitmap_for_each_positive_bit(srcmap, node, j) {
1644
0
      assert(module->map[i][j] != 0);
1645
0
      if (ebitmap_set_bit
1646
0
          (destmap, module->map[i][j] - 1, 1) != 0) {
1647
1648
0
        goto cleanup;
1649
0
      }
1650
0
      if (i == SYM_CLASSES &&
1651
0
          largest_mapped_class_value <
1652
0
          module->map[SYM_CLASSES][j]) {
1653
0
        largest_mapped_class_value =
1654
0
            module->map[SYM_CLASSES][j];
1655
0
      }
1656
0
    }
1657
0
  }
1658
1659
  /* next copy the enabled permissions data  */
1660
0
  if ((dest->class_perms_map = calloc(largest_mapped_class_value,
1661
0
              sizeof(*dest->class_perms_map))) == NULL) {
1662
0
    goto cleanup;
1663
0
  }
1664
0
  dest->class_perms_len = largest_mapped_class_value;
1665
0
  for (i = 0; i < src->class_perms_len; i++) {
1666
0
    const ebitmap_t *srcmap = src->class_perms_map + i;
1667
0
    ebitmap_t *destmap =
1668
0
        dest->class_perms_map + module->map[SYM_CLASSES][i] - 1;
1669
1670
0
    if (ebitmap_convert(srcmap, destmap, module->perm_map[i]))
1671
0
      goto cleanup;
1672
0
  }
1673
1674
0
  return 0;
1675
1676
0
      cleanup:
1677
0
  ERR(state->handle, "Out of memory!");
1678
0
  return -1;
1679
0
}
1680
1681
static int copy_avrule_decl(link_state_t * state, policy_module_t * module,
1682
          avrule_decl_t * src_decl, avrule_decl_t * dest_decl)
1683
0
{
1684
0
  int ret;
1685
1686
  /* copy all of the RBAC and TE rules */
1687
0
  if (copy_avrule_list
1688
0
      (src_decl->avrules, &dest_decl->avrules, module, state) == -1
1689
0
      || copy_role_trans_list(src_decl->role_tr_rules,
1690
0
            &dest_decl->role_tr_rules, module,
1691
0
            state) == -1
1692
0
      || copy_role_allow_list(src_decl->role_allow_rules,
1693
0
            &dest_decl->role_allow_rules, module,
1694
0
            state) == -1
1695
0
      || copy_cond_list(src_decl->cond_list, &dest_decl->cond_list,
1696
0
            module, state) == -1) {
1697
0
    return -1;
1698
0
  }
1699
1700
0
  if (copy_filename_trans_list(src_decl->filename_trans_rules,
1701
0
             &dest_decl->filename_trans_rules,
1702
0
             module, state))
1703
0
    return -1;
1704
1705
0
  if (copy_range_trans_list(src_decl->range_tr_rules,
1706
0
          &dest_decl->range_tr_rules, module, state))
1707
0
    return -1;
1708
1709
  /* finally copy any identifiers local to this declaration */
1710
0
  ret = copy_identifiers(state, src_decl->symtab, dest_decl);
1711
0
  if (ret < 0) {
1712
0
    return ret;
1713
0
  }
1714
1715
  /* then copy required and declared scope indices here */
1716
0
  if (copy_scope_index(&src_decl->required, &dest_decl->required,
1717
0
           module, state) == -1 ||
1718
0
      copy_scope_index(&src_decl->declared, &dest_decl->declared,
1719
0
           module, state) == -1) {
1720
0
    return -1;
1721
0
  }
1722
1723
0
  return 0;
1724
0
}
1725
1726
static int copy_avrule_block(link_state_t * state, policy_module_t * module,
1727
           avrule_block_t * block)
1728
0
{
1729
0
  avrule_block_t *new_block = avrule_block_create();
1730
0
  avrule_decl_t *decl, *last_decl = NULL;
1731
0
  int ret;
1732
1733
0
  if (new_block == NULL) {
1734
0
    ERR(state->handle, "Out of memory!");
1735
0
    ret = -1;
1736
0
    goto cleanup;
1737
0
  }
1738
1739
0
  new_block->flags = block->flags;
1740
1741
0
  for (decl = block->branch_list; decl != NULL; decl = decl->next) {
1742
0
    avrule_decl_t *new_decl =
1743
0
        avrule_decl_create(state->next_decl_id);
1744
0
    if (new_decl == NULL) {
1745
0
      ERR(state->handle, "Out of memory!");
1746
0
      ret = -1;
1747
0
      goto cleanup;
1748
0
    }
1749
1750
0
    if (module->policy->name != NULL) {
1751
0
      new_decl->module_name = strdup(module->policy->name);
1752
0
      if (new_decl->module_name == NULL) {
1753
0
        ERR(state->handle, "Out of memory");
1754
0
        avrule_decl_destroy(new_decl);
1755
0
        ret = -1;
1756
0
        goto cleanup;
1757
0
      }
1758
0
    }
1759
1760
0
    if (last_decl == NULL) {
1761
0
      new_block->branch_list = new_decl;
1762
0
    } else {
1763
0
      last_decl->next = new_decl;
1764
0
    }
1765
0
    last_decl = new_decl;
1766
0
    state->base->decl_val_to_struct[state->next_decl_id - 1] =
1767
0
        new_decl;
1768
0
    state->decl_to_mod[state->next_decl_id] = module->policy;
1769
1770
0
    module->avdecl_map[decl->decl_id] = new_decl->decl_id;
1771
1772
0
    ret = copy_avrule_decl(state, module, decl, new_decl);
1773
0
    if (ret) {
1774
0
      avrule_decl_destroy(new_decl);
1775
0
      goto cleanup;
1776
0
    }
1777
1778
0
    state->next_decl_id++;
1779
0
  }
1780
0
  state->last_avrule_block->next = new_block;
1781
0
  state->last_avrule_block = new_block;
1782
0
  return 0;
1783
1784
0
      cleanup:
1785
0
  avrule_block_list_destroy(new_block);
1786
0
  return ret;
1787
0
}
1788
1789
static int scope_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
1790
             void *data)
1791
0
{
1792
0
  unsigned int i;
1793
0
  int ret;
1794
0
  char *id = key, *new_id = NULL;
1795
0
  scope_datum_t *scope, *base_scope;
1796
0
  link_state_t *state = (link_state_t *) data;
1797
0
  uint32_t symbol_num = state->symbol_num;
1798
0
  uint32_t *avdecl_map = state->cur->avdecl_map;
1799
1800
0
  scope = (scope_datum_t *) datum;
1801
1802
  /* check if the base already has a scope entry */
1803
0
  base_scope = hashtab_search(state->base->scope[symbol_num].table, id);
1804
0
  if (base_scope == NULL) {
1805
0
    scope_datum_t *new_scope;
1806
0
    if ((new_id = strdup(id)) == NULL) {
1807
0
      goto cleanup;
1808
0
    }
1809
1810
0
    if ((new_scope =
1811
0
         (scope_datum_t *) calloc(1, sizeof(*new_scope))) == NULL) {
1812
0
      free(new_id);
1813
0
      goto cleanup;
1814
0
    }
1815
0
    ret = hashtab_insert(state->base->scope[symbol_num].table,
1816
0
             (hashtab_key_t) new_id,
1817
0
             (hashtab_datum_t) new_scope);
1818
0
    if (ret) {
1819
0
      free(new_id);
1820
0
      free(new_scope);
1821
0
      goto cleanup;
1822
0
    }
1823
0
    new_scope->scope = SCOPE_REQ; /* this is reset further down */
1824
0
    base_scope = new_scope;
1825
0
  }
1826
0
  if (base_scope->scope == SCOPE_REQ && scope->scope == SCOPE_DECL) {
1827
    /* this module declared symbol, so overwrite the old
1828
     * list with the new decl ids */
1829
0
    base_scope->scope = SCOPE_DECL;
1830
0
    free(base_scope->decl_ids);
1831
0
    base_scope->decl_ids = NULL;
1832
0
    base_scope->decl_ids_len = 0;
1833
0
    for (i = 0; i < scope->decl_ids_len; i++) {
1834
0
      if (add_i_to_a(avdecl_map[scope->decl_ids[i]],
1835
0
               &base_scope->decl_ids_len,
1836
0
               &base_scope->decl_ids) == -1) {
1837
0
        goto cleanup;
1838
0
      }
1839
0
    }
1840
0
  } else if (base_scope->scope == SCOPE_DECL && scope->scope == SCOPE_REQ) {
1841
    /* this module depended on a symbol that now exists,
1842
     * so don't do anything */
1843
0
  } else if (base_scope->scope == SCOPE_REQ && scope->scope == SCOPE_REQ) {
1844
    /* symbol is still required, so add to the list */
1845
0
    for (i = 0; i < scope->decl_ids_len; i++) {
1846
0
      if (add_i_to_a(avdecl_map[scope->decl_ids[i]],
1847
0
               &base_scope->decl_ids_len,
1848
0
               &base_scope->decl_ids) == -1) {
1849
0
        goto cleanup;
1850
0
      }
1851
0
    }
1852
0
  } else {
1853
    /* this module declared a symbol, and it was already
1854
     * declared.  only roles and users may be multiply
1855
     * declared; for all others this is an error. */
1856
0
    if (symbol_num != SYM_ROLES && symbol_num != SYM_USERS) {
1857
0
      ERR(state->handle,
1858
0
          "%s: Duplicate declaration in module: %s %s",
1859
0
          state->cur_mod_name,
1860
0
          symtab_names[state->symbol_num], id);
1861
0
      return -1;
1862
0
    }
1863
0
    for (i = 0; i < scope->decl_ids_len; i++) {
1864
0
      if (add_i_to_a(avdecl_map[scope->decl_ids[i]],
1865
0
               &base_scope->decl_ids_len,
1866
0
               &base_scope->decl_ids) == -1) {
1867
0
        goto cleanup;
1868
0
      }
1869
0
    }
1870
0
  }
1871
0
  return 0;
1872
1873
0
      cleanup:
1874
0
  ERR(state->handle, "Out of memory!");
1875
0
  return -1;
1876
0
}
1877
1878
/* Copy a module over to a base, remapping all values within.  After
1879
 * all identifiers and rules are done, copy the scoping information.
1880
 * This is when it checks for duplicate declarations. */
1881
static int copy_module(link_state_t * state, policy_module_t * module)
1882
0
{
1883
0
  int i, ret;
1884
0
  avrule_block_t *cur;
1885
0
  state->cur = module;
1886
0
  state->cur_mod_name = module->policy->name;
1887
1888
  /* first copy all of the identifiers */
1889
0
  ret = copy_identifiers(state, module->policy->symtab, NULL);
1890
0
  if (ret) {
1891
0
    return ret;
1892
0
  }
1893
1894
  /* next copy all of the avrule blocks */
1895
0
  for (cur = module->policy->global; cur != NULL; cur = cur->next) {
1896
0
    ret = copy_avrule_block(state, module, cur);
1897
0
    if (ret) {
1898
0
      return ret;
1899
0
    }
1900
0
  }
1901
1902
  /* then copy the scoping tables */
1903
0
  for (i = 0; i < SYM_NUM; i++) {
1904
0
    state->symbol_num = i;
1905
0
    if (hashtab_map
1906
0
        (module->policy->scope[i].table, scope_copy_callback,
1907
0
         state)) {
1908
0
      return -1;
1909
0
    }
1910
0
  }
1911
1912
0
  return 0;
1913
0
}
1914
1915
/***** functions that check requirements and enable blocks in a module ******/
1916
1917
/* borrowed from checkpolicy.c */
1918
1919
struct find_perm_arg {
1920
  unsigned int valuep;
1921
  hashtab_key_t key;
1922
};
1923
1924
static int find_perm(hashtab_key_t key, hashtab_datum_t datum, void *varg)
1925
0
{
1926
1927
0
  struct find_perm_arg *arg = varg;
1928
1929
0
  perm_datum_t *perdatum = (perm_datum_t *) datum;
1930
0
  if (arg->valuep == perdatum->s.value) {
1931
0
    arg->key = key;
1932
0
    return 1;
1933
0
  }
1934
1935
0
  return 0;
1936
0
}
1937
1938
/* Check if the requirements are met for a single declaration.  If all
1939
 * are met return 1.  For the first requirement found to be missing,
1940
 * if 'missing_sym_num' and 'missing_value' are both not NULL then
1941
 * write to them the symbol number and value for the missing
1942
 * declaration.  Then return 0 to indicate a missing declaration.
1943
 * Note that if a declaration had no requirement at all (e.g., an ELSE
1944
 * block) this returns 1. */
1945
static int is_decl_requires_met(link_state_t * state,
1946
        const avrule_decl_t * decl,
1947
        struct missing_requirement *req)
1948
1
{
1949
  /* (This algorithm is very unoptimized.  It performs many
1950
   * redundant checks.  A very obvious improvement is to cache
1951
   * which symbols have been verified, so that they do not need
1952
   * to be re-checked.) */
1953
1
  unsigned int i, j;
1954
1
  const ebitmap_t *bitmap;
1955
1
  const char *id, *perm_id;
1956
1
  const policydb_t *pol = state->base;
1957
1
  ebitmap_node_t *node;
1958
1959
  /* check that all symbols have been satisfied */
1960
9
  for (i = 0; i < SYM_NUM; i++) {
1961
8
    if (i == SYM_CLASSES) {
1962
      /* classes will be checked during permissions
1963
       * checking phase below */
1964
1
      continue;
1965
1
    }
1966
7
    bitmap = &decl->required.scope[i];
1967
7
    ebitmap_for_each_positive_bit(bitmap, node, j) {
1968
      /* check base's scope table */
1969
0
      id = pol->sym_val_to_name[i][j];
1970
0
      if (!is_id_enabled(id, state->base, i)) {
1971
        /* this symbol was not found */
1972
0
        if (req != NULL) {
1973
0
          req->symbol_type = i;
1974
0
          req->symbol_value = j + 1;
1975
0
        }
1976
0
        return 0;
1977
0
      }
1978
0
    }
1979
7
  }
1980
  /* check that all classes and permissions have been satisfied */
1981
1
  for (i = 0; i < decl->required.class_perms_len; i++) {
1982
0
    const class_datum_t *cladatum = pol->class_val_to_struct[i];
1983
0
    const scope_datum_t *scope;
1984
1985
0
    bitmap = &decl->required.class_perms_map[i];
1986
0
    id = pol->p_class_val_to_name[i];
1987
1988
1989
0
    if (!is_id_enabled(id, state->base, SYM_CLASSES)) {
1990
0
      return 0;
1991
0
    }
1992
1993
0
    scope = hashtab_search(state->base->p_classes_scope.table, id);
1994
0
    if (scope == NULL) {
1995
0
      ERR(state->handle,
1996
0
        "Could not find scope information for class %s",
1997
0
        id);
1998
0
      return -1;
1999
0
    }
2000
2001
0
    ebitmap_for_each_positive_bit(bitmap, node, j) {
2002
0
      struct find_perm_arg fparg;
2003
0
      uint32_t perm_value = j + 1;
2004
0
      int rc;
2005
2006
0
      fparg.valuep = perm_value;
2007
0
      fparg.key = NULL;
2008
2009
0
      (void)hashtab_map(cladatum->permissions.table, find_perm,
2010
0
            &fparg);
2011
0
      if (fparg.key == NULL && cladatum->comdatum != NULL) {
2012
0
        rc = hashtab_map(cladatum->comdatum->permissions.table,
2013
0
             find_perm, &fparg);
2014
0
        assert(rc == 1);
2015
0
      }
2016
0
      perm_id = fparg.key;
2017
2018
0
      assert(perm_id != NULL);
2019
0
      if (!is_perm_existent(cladatum, perm_id)) {
2020
0
        if (req != NULL) {
2021
0
          req->symbol_type = SYM_CLASSES;
2022
0
          req->symbol_value = i + 1;
2023
0
          req->perm_value = perm_value;
2024
0
        }
2025
0
        return 0;
2026
0
      }
2027
0
    }
2028
0
  }
2029
2030
  /* all requirements have been met */
2031
1
  return 1;
2032
1
}
2033
2034
static int debug_requirements(link_state_t * state, policydb_t * p)
2035
0
{
2036
0
  int ret;
2037
0
  avrule_block_t *cur;
2038
0
  missing_requirement_t req;
2039
0
  memset(&req, 0, sizeof(req));
2040
2041
0
  for (cur = p->global; cur != NULL; cur = cur->next) {
2042
0
    if (cur->enabled != NULL || cur->branch_list == NULL)
2043
0
      continue;
2044
2045
0
    ret = is_decl_requires_met(state, cur->branch_list, &req);
2046
0
    if (ret < 0) {
2047
0
      return ret;
2048
0
    } else if (ret == 0) {
2049
0
      const char *mod_name = cur->branch_list->module_name ?
2050
0
          cur->branch_list->module_name : "BASE";
2051
0
      if (req.symbol_type == SYM_CLASSES) {
2052
0
        struct find_perm_arg fparg;
2053
2054
0
        class_datum_t *cladatum;
2055
0
        cladatum = p->class_val_to_struct[req.symbol_value - 1];
2056
2057
0
        fparg.valuep = req.perm_value;
2058
0
        fparg.key = NULL;
2059
0
        (void)hashtab_map(cladatum->permissions.table,
2060
0
              find_perm, &fparg);
2061
2062
0
        if (cur->flags & AVRULE_OPTIONAL) {
2063
0
          ERR(state->handle,
2064
0
              "%s[%d]'s optional requirements were not met: class %s, permission %s",
2065
0
              mod_name, cur->branch_list->decl_id,
2066
0
              p->p_class_val_to_name[req.symbol_value - 1],
2067
0
              fparg.key);
2068
0
        } else {
2069
0
          ERR(state->handle,
2070
0
              "%s[%d]'s global requirements were not met: class %s, permission %s",
2071
0
              mod_name, cur->branch_list->decl_id,
2072
0
              p->p_class_val_to_name[req.symbol_value - 1],
2073
0
              fparg.key);
2074
0
        }
2075
0
      } else {
2076
0
        if (cur->flags & AVRULE_OPTIONAL) {
2077
0
          ERR(state->handle,
2078
0
              "%s[%d]'s optional requirements were not met: %s %s",
2079
0
              mod_name, cur->branch_list->decl_id,
2080
0
              symtab_names[req.symbol_type],
2081
0
              p->sym_val_to_name[req.
2082
0
                     symbol_type][req.
2083
0
                      symbol_value
2084
0
                      -
2085
0
                      1]);
2086
0
        } else {
2087
0
          ERR(state->handle,
2088
0
              "%s[%d]'s global requirements were not met: %s %s",
2089
0
              mod_name, cur->branch_list->decl_id,
2090
0
              symtab_names[req.symbol_type],
2091
0
              p->sym_val_to_name[req.
2092
0
                     symbol_type][req.
2093
0
                      symbol_value
2094
0
                      -
2095
0
                      1]);
2096
0
        }
2097
0
      }
2098
0
    }
2099
0
  }
2100
0
  return 0;
2101
0
}
2102
2103
static void print_missing_requirements(link_state_t * state,
2104
               avrule_block_t * cur,
2105
               missing_requirement_t * req)
2106
0
{
2107
0
  policydb_t *p = state->base;
2108
0
  const char *mod_name = cur->branch_list->module_name ?
2109
0
      cur->branch_list->module_name : "BASE";
2110
2111
0
  if (req->symbol_type == SYM_CLASSES) {
2112
2113
0
    struct find_perm_arg fparg;
2114
2115
0
    class_datum_t *cladatum;
2116
0
    cladatum = p->class_val_to_struct[req->symbol_value - 1];
2117
2118
0
    fparg.valuep = req->perm_value;
2119
0
    fparg.key = NULL;
2120
0
    (void)hashtab_map(cladatum->permissions.table, find_perm, &fparg);
2121
2122
0
    ERR(state->handle,
2123
0
        "%s's global requirements were not met: class %s, permission %s",
2124
0
        mod_name,
2125
0
        p->p_class_val_to_name[req->symbol_value - 1], fparg.key);
2126
0
  } else {
2127
0
    ERR(state->handle,
2128
0
        "%s's global requirements were not met: %s %s",
2129
0
        mod_name,
2130
0
        symtab_names[req->symbol_type],
2131
0
        p->sym_val_to_name[req->symbol_type][req->symbol_value - 1]);
2132
0
  }
2133
0
}
2134
2135
/* Enable all of the avrule_decl blocks for the policy. This simple
2136
 * algorithm is the following:
2137
 *
2138
 * 1) Enable all of the non-else avrule_decls for all blocks.
2139
 * 2) Iterate through the non-else decls looking for decls whose requirements
2140
 *    are not met.
2141
 *    2a) If the decl is non-optional, return immediately with an error.
2142
 *    2b) If the decl is optional, disable the block and mark changed = 1
2143
 * 3) If changed == 1 goto 2.
2144
 * 4) Iterate through all blocks looking for those that have no enabled
2145
 *    decl. If the block has an else decl, enable.
2146
 *
2147
 * This will correctly handle all dependencies, including mutual and
2148
 * circular. The only downside is that it is slow.
2149
 */
2150
static int enable_avrules(link_state_t * state, policydb_t * pol)
2151
3
{
2152
3
  int changed = 1;
2153
3
  avrule_block_t *block;
2154
3
  avrule_decl_t *decl;
2155
3
  missing_requirement_t req;
2156
3
  int ret = 0, rc;
2157
2158
3
  if (state->verbose) {
2159
0
    INFO(state->handle, "Determining which avrules to enable.");
2160
0
  }
2161
2162
  /* 1) enable all of the non-else blocks */
2163
6
  for (block = pol->global; block != NULL; block = block->next) {
2164
5
    block->enabled = block->branch_list;
2165
5
    if (!block->enabled) {
2166
2
      ERR(state->handle, "Global block has no avrules!");
2167
2
      ret = SEPOL_ERR;
2168
2
      goto out;
2169
2
    }
2170
3
    block->enabled->enabled = 1;
2171
3
    for (decl = block->branch_list->next; decl != NULL;
2172
3
         decl = decl->next)
2173
0
      decl->enabled = 0;
2174
3
  }
2175
2176
  /* 2) Iterate */
2177
2
  while (changed) {
2178
1
    changed = 0;
2179
2
    for (block = pol->global; block != NULL; block = block->next) {
2180
1
      if (block->enabled == NULL) {
2181
0
        continue;
2182
0
      }
2183
1
      decl = block->branch_list;
2184
1
      if (state->verbose) {
2185
0
        const char *mod_name = decl->module_name ?
2186
0
            decl->module_name : "BASE";
2187
0
        INFO(state->handle, "check module %s decl %d",
2188
0
             mod_name, decl->decl_id);
2189
0
      }
2190
1
      rc = is_decl_requires_met(state, decl, &req);
2191
1
      if (rc < 0) {
2192
0
        ret = SEPOL_ERR;
2193
0
        goto out;
2194
1
      } else if (rc == 0) {
2195
0
        decl->enabled = 0;
2196
0
        block->enabled = NULL;
2197
0
        changed = 1;
2198
0
        if (!(block->flags & AVRULE_OPTIONAL)) {
2199
0
          print_missing_requirements(state, block,
2200
0
                   &req);
2201
0
          ret = SEPOL_EREQ;
2202
0
          goto out;
2203
0
        }
2204
0
      }
2205
1
    }
2206
1
  }
2207
2208
  /* 4) else handling
2209
   *
2210
   * Iterate through all of the blocks skipping the first (which is the
2211
   * global block, is required to be present, and cannot have an else).
2212
   * If the block is disabled and has an else decl, enable that.
2213
   *
2214
   * This code assumes that the second block in the branch list is the else
2215
   * block. This is currently supported by the compiler.
2216
   */
2217
1
  for (block = pol->global->next; block != NULL; block = block->next) {
2218
0
    if (block->enabled == NULL) {
2219
0
      if (block->branch_list->next != NULL) {
2220
0
        block->enabled = block->branch_list->next;
2221
0
        block->branch_list->next->enabled = 1;
2222
0
      }
2223
0
    }
2224
0
  }
2225
2226
3
      out:
2227
3
  if (state->verbose)
2228
0
    debug_requirements(state, pol);
2229
2230
3
  return ret;
2231
1
}
2232
2233
/*********** the main linking functions ***********/
2234
2235
/* Given a module's policy, normalize all conditional expressions
2236
 * within.  Return 0 on success, -1 on error. */
2237
static int cond_normalize(policydb_t * p)
2238
3
{
2239
3
  avrule_block_t *block;
2240
12
  for (block = p->global; block != NULL; block = block->next) {
2241
9
    avrule_decl_t *decl;
2242
12
    for (decl = block->branch_list; decl != NULL; decl = decl->next) {
2243
3
      cond_list_t *cond = decl->cond_list;
2244
3
      while (cond) {
2245
0
        if (cond_normalize_expr(p, cond) < 0)
2246
0
          return -1;
2247
0
        cond = cond->next;
2248
0
      }
2249
3
    }
2250
9
  }
2251
3
  return 0;
2252
3
}
2253
2254
/* Allocate space for the various remapping arrays. */
2255
static int prepare_module(link_state_t * state, policy_module_t * module)
2256
0
{
2257
0
  int i;
2258
0
  uint32_t items, num_decls = 0;
2259
0
  avrule_block_t *cur;
2260
2261
  /* allocate the maps */
2262
0
  for (i = 0; i < SYM_NUM; i++) {
2263
0
    items = module->policy->symtab[i].nprim;
2264
0
    if ((module->map[i] =
2265
0
         (uint32_t *) calloc(items,
2266
0
           sizeof(*module->map[i]))) == NULL) {
2267
0
      ERR(state->handle, "Out of memory!");
2268
0
      return -1;
2269
0
    }
2270
0
  }
2271
2272
  /* allocate the permissions remap here */
2273
0
  items = module->policy->p_classes.nprim;
2274
0
  if ((module->perm_map_len =
2275
0
       calloc(items, sizeof(*module->perm_map_len))) == NULL) {
2276
0
    ERR(state->handle, "Out of memory!");
2277
0
    return -1;
2278
0
  }
2279
0
  if ((module->perm_map =
2280
0
       calloc(items, sizeof(*module->perm_map))) == NULL) {
2281
0
    ERR(state->handle, "Out of memory!");
2282
0
    return -1;
2283
0
  }
2284
2285
  /* allocate a map for avrule_decls */
2286
0
  for (cur = module->policy->global; cur != NULL; cur = cur->next) {
2287
0
    avrule_decl_t *decl;
2288
0
    for (decl = cur->branch_list; decl != NULL; decl = decl->next) {
2289
0
      if (decl->decl_id > num_decls) {
2290
0
        num_decls = decl->decl_id;
2291
0
      }
2292
0
    }
2293
0
  }
2294
0
  num_decls++;
2295
0
  if ((module->avdecl_map = calloc(num_decls, sizeof(uint32_t))) == NULL) {
2296
0
    ERR(state->handle, "Out of memory!");
2297
0
    return -1;
2298
0
  }
2299
0
  module->num_decls = num_decls;
2300
2301
  /* normalize conditionals within */
2302
0
  if (cond_normalize(module->policy) < 0) {
2303
0
    ERR(state->handle,
2304
0
        "Error while normalizing conditionals within the module %s.",
2305
0
        module->policy->name);
2306
0
    return -1;
2307
0
  }
2308
0
  return 0;
2309
0
}
2310
2311
static int prepare_base(link_state_t * state, uint32_t num_mod_decls)
2312
3
{
2313
3
  avrule_block_t *cur = state->base->global;
2314
3
  assert(cur != NULL);
2315
3
  state->next_decl_id = 0;
2316
2317
  /* iterate through all of the declarations in the base, to
2318
     determine what the next decl_id should be */
2319
12
  while (cur != NULL) {
2320
9
    avrule_decl_t *decl;
2321
12
    for (decl = cur->branch_list; decl != NULL; decl = decl->next) {
2322
3
      if (decl->decl_id > state->next_decl_id) {
2323
3
        state->next_decl_id = decl->decl_id;
2324
3
      }
2325
3
    }
2326
9
    state->last_avrule_block = cur;
2327
9
    cur = cur->next;
2328
9
  }
2329
3
  state->last_base_avrule_block = state->last_avrule_block;
2330
3
  state->next_decl_id++;
2331
2332
  /* allocate the table mapping from base's decl_id to its
2333
   * avrule_decls and set the initial mappings */
2334
3
  free(state->base->decl_val_to_struct);
2335
3
  if ((state->base->decl_val_to_struct =
2336
3
       calloc(state->next_decl_id + num_mod_decls,
2337
3
        sizeof(*(state->base->decl_val_to_struct)))) == NULL) {
2338
0
    ERR(state->handle, "Out of memory!");
2339
0
    return -1;
2340
0
  }
2341
  /* This allocates the decl block to module mapping used for error reporting */
2342
3
  if ((state->decl_to_mod = calloc(state->next_decl_id + num_mod_decls,
2343
3
           sizeof(*(state->decl_to_mod)))) ==
2344
3
      NULL) {
2345
0
    ERR(state->handle, "Out of memory!");
2346
0
    return -1;
2347
0
  }
2348
3
  cur = state->base->global;
2349
12
  while (cur != NULL) {
2350
9
    avrule_decl_t *decl = cur->branch_list;
2351
12
    while (decl != NULL) {
2352
3
      state->base->decl_val_to_struct[decl->decl_id - 1] =
2353
3
          decl;
2354
3
      state->decl_to_mod[decl->decl_id] = state->base;
2355
3
      decl = decl->next;
2356
3
    }
2357
9
    cur = cur->next;
2358
9
  }
2359
2360
  /* normalize conditionals within */
2361
3
  if (cond_normalize(state->base) < 0) {
2362
0
    ERR(state->handle,
2363
0
        "Error while normalizing conditionals within the base module.");
2364
0
    return -1;
2365
0
  }
2366
3
  return 0;
2367
3
}
2368
2369
/* Link a set of modules into a base module. This process is somewhat
2370
 * similar to an actual compiler: it requires a set of order dependent
2371
 * steps.  The base and every module must have been indexed prior to
2372
 * calling this function.
2373
 */
2374
int link_modules(sepol_handle_t * handle,
2375
     policydb_t * b, policydb_t ** mods, int len, int verbose)
2376
3
{
2377
3
  int i, ret, retval = -1;
2378
3
  policy_module_t **modules = NULL;
2379
3
  link_state_t state;
2380
3
  uint32_t num_mod_decls = 0;
2381
2382
3
  memset(&state, 0, sizeof(state));
2383
3
  state.base = b;
2384
3
  state.verbose = verbose;
2385
3
  state.handle = handle;
2386
2387
3
  if (b->policy_type != POLICY_BASE) {
2388
0
    ERR(state.handle, "Target of link was not a base policy.");
2389
0
    return -1;
2390
0
  }
2391
2392
  /* first allocate some space to hold the maps from module
2393
   * symbol's value to the destination symbol value; then do
2394
   * other preparation work */
2395
3
  if ((modules =
2396
3
       (policy_module_t **) calloc(len, sizeof(*modules))) == NULL) {
2397
0
    ERR(state.handle, "Out of memory!");
2398
0
    return -1;
2399
0
  }
2400
3
  for (i = 0; i < len; i++) {
2401
0
    if (mods[i]->policy_type != POLICY_MOD) {
2402
0
      ERR(state.handle,
2403
0
          "Tried to link in a policy that was not a module.");
2404
0
      goto cleanup;
2405
0
    }
2406
2407
0
    if (mods[i]->mls != b->mls) {
2408
0
      if (b->mls)
2409
0
        ERR(state.handle,
2410
0
            "Tried to link in a non-MLS module with an MLS base.");
2411
0
      else
2412
0
        ERR(state.handle,
2413
0
            "Tried to link in an MLS module with a non-MLS base.");
2414
0
      goto cleanup;
2415
0
    }
2416
2417
0
    if (mods[i]->policyvers > b->policyvers) {
2418
0
      WARN(state.handle,
2419
0
           "Upgrading policy version from %u to %u", b->policyvers, mods[i]->policyvers);
2420
0
      b->policyvers = mods[i]->policyvers;
2421
0
    }
2422
2423
0
    if ((modules[i] =
2424
0
         (policy_module_t *) calloc(1,
2425
0
            sizeof(policy_module_t))) ==
2426
0
        NULL) {
2427
0
      ERR(state.handle, "Out of memory!");
2428
0
      goto cleanup;
2429
0
    }
2430
0
    modules[i]->policy = mods[i];
2431
0
    if (prepare_module(&state, modules[i]) == -1) {
2432
0
      goto cleanup;
2433
0
    }
2434
0
    num_mod_decls += modules[i]->num_decls;
2435
0
  }
2436
3
  if (prepare_base(&state, num_mod_decls) == -1) {
2437
0
    goto cleanup;
2438
0
  }
2439
2440
  /* copy and remap the module's data over to base */
2441
3
  for (i = 0; i < len; i++) {
2442
0
    state.cur = modules[i];
2443
0
    ret = copy_module(&state, modules[i]);
2444
0
    if (ret) {
2445
0
      retval = ret;
2446
0
      goto cleanup;
2447
0
    }
2448
0
  }
2449
2450
  /* re-index base, for symbols were added to symbol tables  */
2451
3
  if (policydb_index_classes(state.base)) {
2452
0
    ERR(state.handle, "Error while indexing classes");
2453
0
    goto cleanup;
2454
0
  }
2455
3
  if (policydb_index_others(state.handle, state.base, 0)) {
2456
0
    ERR(state.handle, "Error while indexing others");
2457
0
    goto cleanup;
2458
0
  }
2459
2460
3
  if (enable_avrules(&state, state.base)) {
2461
2
    retval = SEPOL_EREQ;
2462
2
    goto cleanup;
2463
2
  }
2464
2465
2466
1
  retval = 0;
2467
3
      cleanup:
2468
3
  for (i = 0; modules != NULL && i < len; i++) {
2469
0
    policy_module_destroy(modules[i]);
2470
0
  }
2471
3
  free(modules);
2472
3
  free(state.decl_to_mod);
2473
3
  return retval;
2474
1
}