Coverage Report

Created: 2026-09-03 06:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/selinux/libsepol/cil/src/cil_symtab.c
Line
Count
Source
1
/*
2
 * Copyright 2011 Tresys Technology, LLC. All rights reserved.
3
 * 
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions are met:
6
 * 
7
 *    1. Redistributions of source code must retain the above copyright notice,
8
 *       this list of conditions and the following disclaimer.
9
 * 
10
 *    2. Redistributions in binary form must reproduce the above copyright notice,
11
 *       this list of conditions and the following disclaimer in the documentation
12
 *       and/or other materials provided with the distribution.
13
 * 
14
 * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS
15
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
16
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
17
 * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
18
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
19
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
21
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
22
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
23
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24
 * 
25
 * The views and conclusions contained in the software and documentation are those
26
 * of the authors and should not be interpreted as representing official policies,
27
 * either expressed or implied, of Tresys Technology, LLC.
28
 */
29
30
#include <stdlib.h>
31
#include <string.h>
32
#include <stdarg.h>
33
34
#include <sepol/errcodes.h>
35
#include <sepol/policydb/hashtab.h>
36
#include <sepol/policydb/symtab.h>
37
38
#include "cil_internal.h"
39
#include "cil_tree.h"
40
#include "cil_symtab.h"
41
#include "cil_mem.h"
42
#include "cil_strpool.h"
43
#include "cil_log.h"
44
45
__attribute__((noreturn)) __attribute__((format(printf, 1, 2))) static void
46
cil_symtab_error(const char *msg, ...)
47
0
{
48
0
  va_list ap;
49
0
  va_start(ap, msg);
50
0
  cil_vlog(CIL_ERR, msg, ap);
51
0
  va_end(ap);
52
0
  exit(1);
53
0
}
54
55
void cil_symtab_init(symtab_t *symtab, unsigned int size)
56
0
{
57
0
  int rc = symtab_init(symtab, size);
58
0
  if (rc != SEPOL_OK) {
59
0
    cil_symtab_error("Failed to create symtab\n");
60
0
  }
61
0
}
62
63
void cil_symtab_datum_init(struct cil_symtab_datum *datum)
64
0
{
65
0
  datum->name = NULL;
66
0
  datum->fqn = NULL;
67
0
  datum->symtab = NULL;
68
0
  cil_list_init(&datum->nodes, CIL_LIST_ITEM);
69
0
}
70
71
void cil_symtab_datum_destroy(struct cil_symtab_datum *datum)
72
0
{
73
0
  cil_list_destroy(&datum->nodes, 0);
74
0
  cil_symtab_remove_datum(datum);
75
0
}
76
77
void cil_symtab_datum_remove_node(struct cil_symtab_datum *datum,
78
          struct cil_tree_node *node)
79
0
{
80
0
  if (datum && datum->nodes != NULL) {
81
0
    cil_list_remove(datum->nodes, CIL_NODE, node, 0);
82
0
    if (datum->nodes->head == NULL) {
83
0
      cil_symtab_datum_destroy(datum);
84
0
    }
85
0
  }
86
0
}
87
88
/* This both initializes the datum and inserts it into the symtab.
89
   Note that cil_symtab_datum_destroy() is the analog to the initializer portion */
90
int cil_symtab_insert(symtab_t *symtab, hashtab_key_t key,
91
          struct cil_symtab_datum *datum,
92
          struct cil_tree_node *node)
93
0
{
94
0
  int rc = hashtab_insert(symtab->table, key, (hashtab_datum_t)datum);
95
0
  if (rc == SEPOL_OK) {
96
0
    datum->name = key;
97
0
    datum->fqn = key;
98
0
    datum->symtab = symtab;
99
0
    symtab->nprim++;
100
0
    if (node) {
101
0
      cil_list_append(datum->nodes, CIL_NODE, node);
102
0
    }
103
0
  } else if (rc != SEPOL_EEXIST) {
104
0
    cil_symtab_error("Failed to insert datum into hashtab\n");
105
0
  }
106
107
0
  return rc;
108
0
}
109
110
void cil_symtab_remove_datum(struct cil_symtab_datum *datum)
111
0
{
112
0
  symtab_t *symtab = datum->symtab;
113
114
0
  if (symtab == NULL) {
115
0
    return;
116
0
  }
117
118
0
  hashtab_remove(symtab->table, datum->name, NULL, NULL);
119
0
  symtab->nprim--;
120
0
  datum->symtab = NULL;
121
0
}
122
123
int cil_symtab_get_datum(symtab_t *symtab, char *key,
124
       struct cil_symtab_datum **datum)
125
0
{
126
0
  *datum = (struct cil_symtab_datum *)hashtab_search(symtab->table,
127
0
                 (hashtab_key_t)key);
128
0
  if (*datum == NULL) {
129
0
    return SEPOL_ENOENT;
130
0
  }
131
132
0
  return SEPOL_OK;
133
0
}
134
135
int cil_symtab_map(symtab_t *symtab,
136
       int (*apply)(hashtab_key_t k, hashtab_datum_t d, void *args),
137
       void *args)
138
0
{
139
0
  return hashtab_map(symtab->table, apply, args);
140
0
}
141
142
static int __cil_symtab_destroy_helper(__attribute__((unused)) hashtab_key_t k,
143
               hashtab_datum_t d,
144
               __attribute__((unused)) void *args)
145
0
{
146
0
  struct cil_symtab_datum *datum = d;
147
0
  datum->symtab = NULL;
148
0
  return SEPOL_OK;
149
0
}
150
151
void cil_symtab_destroy(symtab_t *symtab)
152
0
{
153
0
  if (symtab->table != NULL) {
154
0
    cil_symtab_map(symtab, __cil_symtab_destroy_helper, NULL);
155
0
    hashtab_destroy(symtab->table);
156
0
    symtab->table = NULL;
157
0
  }
158
0
}
159
160
static void cil_complex_symtab_hash(struct cil_complex_symtab_key *ckey,
161
            int mask, intptr_t *hash)
162
0
{
163
0
  intptr_t sum = ckey->key1 + ckey->key2 + ckey->key3 + ckey->key4;
164
0
  *hash = (intptr_t)((sum >> 2) & mask);
165
0
}
166
167
void cil_complex_symtab_init(struct cil_complex_symtab *symtab,
168
           unsigned int size)
169
0
{
170
0
  symtab->htable = cil_calloc(size, sizeof(struct cil_complex_symtab *));
171
172
0
  symtab->nelems = 0;
173
0
  symtab->nslots = size;
174
0
  symtab->mask = size - 1;
175
0
}
176
177
int cil_complex_symtab_insert(struct cil_complex_symtab *symtab,
178
            struct cil_complex_symtab_key *ckey,
179
            struct cil_complex_symtab_datum *datum)
180
0
{
181
0
  intptr_t hash;
182
0
  struct cil_complex_symtab_node *node = NULL;
183
0
  struct cil_complex_symtab_node *prev = NULL;
184
0
  struct cil_complex_symtab_node *curr = NULL;
185
186
0
  node = cil_malloc(sizeof(*node));
187
0
  memset(node, 0, sizeof(*node));
188
189
0
  node->ckey = ckey;
190
0
  node->datum = datum;
191
192
0
  cil_complex_symtab_hash(ckey, symtab->mask, &hash);
193
194
0
  for (prev = NULL, curr = symtab->htable[hash]; curr != NULL;
195
0
       prev = curr, curr = curr->next) {
196
0
    if (ckey->key1 == curr->ckey->key1 &&
197
0
        ckey->key2 == curr->ckey->key2 &&
198
0
        ckey->key3 == curr->ckey->key3 &&
199
0
        ckey->key4 == curr->ckey->key4) {
200
0
      free(node);
201
0
      return SEPOL_EEXIST;
202
0
    }
203
204
0
    if (ckey->key1 == curr->ckey->key1 &&
205
0
        ckey->key2 < curr->ckey->key2) {
206
0
      break;
207
0
    }
208
209
0
    if (ckey->key1 == curr->ckey->key1 &&
210
0
        ckey->key2 == curr->ckey->key2 &&
211
0
        ckey->key3 < curr->ckey->key3) {
212
0
      break;
213
0
    }
214
215
0
    if (ckey->key1 == curr->ckey->key1 &&
216
0
        ckey->key2 == curr->ckey->key2 &&
217
0
        ckey->key3 == curr->ckey->key3 &&
218
0
        ckey->key4 < curr->ckey->key4) {
219
0
      break;
220
0
    }
221
0
  }
222
223
0
  if (prev != NULL) {
224
0
    node->next = prev->next;
225
0
    prev->next = node;
226
0
  } else {
227
0
    node->next = symtab->htable[hash];
228
0
    symtab->htable[hash] = node;
229
0
  }
230
231
0
  symtab->nelems++;
232
233
0
  return SEPOL_OK;
234
0
}
235
236
void cil_complex_symtab_search(struct cil_complex_symtab *symtab,
237
             struct cil_complex_symtab_key *ckey,
238
             struct cil_complex_symtab_datum **out)
239
0
{
240
0
  intptr_t hash;
241
0
  struct cil_complex_symtab_node *curr = NULL;
242
243
0
  cil_complex_symtab_hash(ckey, symtab->mask, &hash);
244
0
  for (curr = symtab->htable[hash]; curr != NULL; curr = curr->next) {
245
0
    if (ckey->key1 == curr->ckey->key1 &&
246
0
        ckey->key2 == curr->ckey->key2 &&
247
0
        ckey->key3 == curr->ckey->key3 &&
248
0
        ckey->key4 == curr->ckey->key4) {
249
0
      *out = curr->datum;
250
0
      return;
251
0
    }
252
253
0
    if (ckey->key1 == curr->ckey->key1 &&
254
0
        ckey->key2 < curr->ckey->key2) {
255
0
      break;
256
0
    }
257
258
0
    if (ckey->key1 == curr->ckey->key1 &&
259
0
        ckey->key2 == curr->ckey->key2 &&
260
0
        ckey->key3 < curr->ckey->key3) {
261
0
      break;
262
0
    }
263
264
0
    if (ckey->key1 == curr->ckey->key1 &&
265
0
        ckey->key2 == curr->ckey->key2 &&
266
0
        ckey->key3 == curr->ckey->key3 &&
267
0
        ckey->key4 < curr->ckey->key4) {
268
0
      break;
269
0
    }
270
0
  }
271
272
0
  *out = NULL;
273
0
}
274
275
void cil_complex_symtab_destroy(struct cil_complex_symtab *symtab)
276
0
{
277
0
  struct cil_complex_symtab_node *curr = NULL;
278
0
  struct cil_complex_symtab_node *temp = NULL;
279
0
  unsigned int i;
280
281
0
  if (symtab == NULL) {
282
0
    return;
283
0
  }
284
285
0
  for (i = 0; i < symtab->nslots; i++) {
286
0
    curr = symtab->htable[i];
287
0
    while (curr != NULL) {
288
0
      temp = curr;
289
0
      curr = curr->next;
290
0
      free(temp);
291
0
    }
292
0
    symtab->htable[i] = NULL;
293
0
  }
294
0
  free(symtab->htable);
295
  symtab->htable = NULL;
296
0
  symtab->nelems = 0;
297
0
  symtab->nslots = 0;
298
0
  symtab->mask = 0;
299
0
}