Coverage Report

Created: 2025-12-14 06:29

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/selinux/libsepol/src/avtab.c
Line
Count
Source
1
2
/* Author : Stephen Smalley, <stephen.smalley.work@gmail.com> */
3
4
/*
5
 * Updated: Yuichi Nakamura <ynakam@hitachisoft.jp>
6
 *  Tuned number of hash slots for avtab to reduce memory usage
7
 */
8
9
/* Updated: Frank Mayer <mayerf@tresys.com>
10
 *          and Karl MacMillan <kmacmillan@mentalrootkit.com>
11
 *
12
 *  Added conditional policy language extensions
13
 *
14
 * Updated: Red Hat, Inc.  James Morris <jmorris@redhat.com>
15
 *
16
 *      Code cleanup
17
 *
18
 * Updated: Karl MacMillan <kmacmillan@mentalrootkit.com>
19
 *
20
 * Copyright (C) 2003 Tresys Technology, LLC
21
 * Copyright (C) 2003,2007 Red Hat, Inc.
22
 *
23
 *  This library is free software; you can redistribute it and/or
24
 *  modify it under the terms of the GNU Lesser General Public
25
 *  License as published by the Free Software Foundation; either
26
 *  version 2.1 of the License, or (at your option) any later version.
27
 *
28
 *  This library is distributed in the hope that it will be useful,
29
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
30
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
31
 *  Lesser General Public License for more details.
32
 *
33
 *  You should have received a copy of the GNU Lesser General Public
34
 *  License along with this library; if not, write to the Free Software
35
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
36
 */
37
38
/* FLASK */
39
40
/* 
41
 * Implementation of the access vector table type.
42
 */
43
44
#include <stdlib.h>
45
#include <sepol/policydb/avtab.h>
46
#include <sepol/policydb/policydb.h>
47
#include <sepol/errcodes.h>
48
49
#include "debug.h"
50
#include "private.h"
51
52
/* Based on MurmurHash3, written by Austin Appleby and placed in the
53
 * public domain.
54
 */
55
ignore_unsigned_overflow_
56
static inline int avtab_hash(struct avtab_key *keyp, uint32_t mask)
57
31.1k
{
58
31.1k
  static const uint32_t c1 = 0xcc9e2d51;
59
31.1k
  static const uint32_t c2 = 0x1b873593;
60
31.1k
  static const uint32_t r1 = 15;
61
31.1k
  static const uint32_t r2 = 13;
62
31.1k
  static const uint32_t m  = 5;
63
31.1k
  static const uint32_t n  = 0xe6546b64;
64
65
31.1k
  uint32_t hash = 0;
66
67
93.4k
#define mix(input) do { \
68
93.4k
  uint32_t v = input; \
69
93.4k
  v *= c1; \
70
93.4k
  v = (v << r1) | (v >> (32 - r1)); \
71
93.4k
  v *= c2; \
72
93.4k
  hash ^= v; \
73
93.4k
  hash = (hash << r2) | (hash >> (32 - r2)); \
74
93.4k
  hash = hash * m + n; \
75
93.4k
} while (0)
76
77
31.1k
  mix(keyp->target_class);
78
31.1k
  mix(keyp->target_type);
79
31.1k
  mix(keyp->source_type);
80
81
31.1k
#undef mix
82
83
31.1k
  hash ^= hash >> 16;
84
31.1k
  hash *= 0x85ebca6b;
85
31.1k
  hash ^= hash >> 13;
86
31.1k
  hash *= 0xc2b2ae35;
87
31.1k
  hash ^= hash >> 16;
88
89
31.1k
  return hash & mask;
90
31.1k
}
91
92
static avtab_ptr_t
93
avtab_insert_node(avtab_t * h, int hvalue, avtab_ptr_t prev, avtab_key_t * key,
94
      avtab_datum_t * datum)
95
20.6k
{
96
20.6k
  avtab_ptr_t newnode;
97
20.6k
  avtab_extended_perms_t *xperms;
98
99
20.6k
  newnode = (avtab_ptr_t) malloc(sizeof(struct avtab_node));
100
20.6k
  if (newnode == NULL)
101
0
    return NULL;
102
20.6k
  memset(newnode, 0, sizeof(struct avtab_node));
103
20.6k
  newnode->key = *key;
104
105
20.6k
  if (key->specified & AVTAB_XPERMS) {
106
7.09k
    xperms = calloc(1, sizeof(avtab_extended_perms_t));
107
7.09k
    if (xperms == NULL) {
108
0
      free(newnode);
109
0
      return NULL;
110
0
    }
111
7.09k
    if (datum->xperms) /* else caller populates xperms */
112
4.06k
      *xperms = *(datum->xperms);
113
114
7.09k
    newnode->datum.xperms = xperms;
115
    /* data is usually ignored with xperms, except in the case of
116
     * neverallow checking, which requires permission bits to be set.
117
     * So copy data so it is set in the avtab
118
     */
119
7.09k
    newnode->datum.data = datum->data;
120
13.5k
  } else {
121
13.5k
    newnode->datum = *datum;
122
13.5k
  }
123
124
20.6k
  if (prev) {
125
8.79k
    newnode->next = prev->next;
126
8.79k
    prev->next = newnode;
127
11.8k
  } else {
128
11.8k
    newnode->next = h->htable[hvalue];
129
11.8k
    h->htable[hvalue] = newnode;
130
11.8k
  }
131
132
20.6k
  h->nel++;
133
20.6k
  return newnode;
134
20.6k
}
135
136
int avtab_insert(avtab_t * h, avtab_key_t * key, avtab_datum_t * datum)
137
10.0k
{
138
10.0k
  int hvalue;
139
10.0k
  avtab_ptr_t prev, cur, newnode;
140
10.0k
  uint16_t specified =
141
10.0k
      key->specified & ~(AVTAB_ENABLED | AVTAB_ENABLED_OLD);
142
143
10.0k
  if (!h || !h->htable)
144
0
    return SEPOL_ENOMEM;
145
146
10.0k
  hvalue = avtab_hash(key, h->mask);
147
10.0k
  for (prev = NULL, cur = h->htable[hvalue];
148
15.1k
       cur; prev = cur, cur = cur->next) {
149
6.39k
    if (key->source_type == cur->key.source_type &&
150
5.23k
        key->target_type == cur->key.target_type &&
151
3.92k
        key->target_class == cur->key.target_class &&
152
3.42k
        (specified & cur->key.specified)) {
153
      /* Extended permissions are not necessarily unique */
154
862
      if (specified & AVTAB_XPERMS)
155
860
        break;
156
2
      return SEPOL_EEXIST;
157
862
    }
158
5.53k
    if (key->source_type < cur->key.source_type)
159
214
      break;
160
5.31k
    if (key->source_type == cur->key.source_type &&
161
4.36k
        key->target_type < cur->key.target_type)
162
190
      break;
163
5.12k
    if (key->source_type == cur->key.source_type &&
164
4.17k
        key->target_type == cur->key.target_type &&
165
3.06k
        key->target_class < cur->key.target_class)
166
64
      break;
167
5.12k
  }
168
169
10.0k
  newnode = avtab_insert_node(h, hvalue, prev, key, datum);
170
10.0k
  if (!newnode)
171
0
    return SEPOL_ENOMEM;
172
173
10.0k
  return 0;
174
10.0k
}
175
176
/* Unlike avtab_insert(), this function allow multiple insertions of the same 
177
 * key/specified mask into the table, as needed by the conditional avtab.  
178
 * It also returns a pointer to the node inserted.
179
 */
180
avtab_ptr_t
181
avtab_insert_nonunique(avtab_t * h, avtab_key_t * key, avtab_datum_t * datum)
182
10.5k
{
183
10.5k
  int hvalue;
184
10.5k
  avtab_ptr_t prev, cur, newnode;
185
10.5k
  uint16_t specified =
186
10.5k
      key->specified & ~(AVTAB_ENABLED | AVTAB_ENABLED_OLD);
187
188
10.5k
  if (!h || !h->htable)
189
0
    return NULL;
190
10.5k
  hvalue = avtab_hash(key, h->mask);
191
10.5k
  for (prev = NULL, cur = h->htable[hvalue];
192
462k
       cur; prev = cur, cur = cur->next) {
193
459k
    if (key->source_type == cur->key.source_type &&
194
440k
        key->target_type == cur->key.target_type &&
195
254k
        key->target_class == cur->key.target_class &&
196
214k
        (specified & cur->key.specified))
197
5.97k
      break;
198
453k
    if (key->source_type < cur->key.source_type)
199
756
      break;
200
452k
    if (key->source_type == cur->key.source_type &&
201
434k
        key->target_type < cur->key.target_type)
202
531
      break;
203
452k
    if (key->source_type == cur->key.source_type &&
204
433k
        key->target_type == cur->key.target_type &&
205
248k
        key->target_class < cur->key.target_class)
206
479
      break;
207
452k
  }
208
10.5k
  newnode = avtab_insert_node(h, hvalue, prev, key, datum);
209
210
10.5k
  return newnode;
211
10.5k
}
212
213
avtab_datum_t *avtab_search(avtab_t * h, avtab_key_t * key)
214
9.42k
{
215
9.42k
  int hvalue;
216
9.42k
  avtab_ptr_t cur;
217
9.42k
  uint16_t specified =
218
9.42k
      key->specified & ~(AVTAB_ENABLED | AVTAB_ENABLED_OLD);
219
220
9.42k
  if (!h || !h->htable)
221
99
    return NULL;
222
223
9.32k
  hvalue = avtab_hash(key, h->mask);
224
19.1k
  for (cur = h->htable[hvalue]; cur; cur = cur->next) {
225
14.9k
    if (key->source_type == cur->key.source_type &&
226
11.3k
        key->target_type == cur->key.target_type &&
227
7.41k
        key->target_class == cur->key.target_class &&
228
5.74k
        (specified & cur->key.specified))
229
3.35k
      return &cur->datum;
230
231
11.5k
    if (key->source_type < cur->key.source_type)
232
1.14k
      break;
233
10.4k
    if (key->source_type == cur->key.source_type &&
234
7.96k
        key->target_type < cur->key.target_type)
235
427
      break;
236
9.98k
    if (key->source_type == cur->key.source_type &&
237
7.54k
        key->target_type == cur->key.target_type &&
238
4.06k
        key->target_class < cur->key.target_class)
239
175
      break;
240
9.98k
  }
241
242
5.97k
  return NULL;
243
9.32k
}
244
245
/* This search function returns a node pointer, and can be used in
246
 * conjunction with avtab_search_next_node()
247
 */
248
avtab_ptr_t avtab_search_node(avtab_t * h, avtab_key_t * key)
249
1.21k
{
250
1.21k
  int hvalue;
251
1.21k
  avtab_ptr_t cur;
252
1.21k
  uint16_t specified =
253
1.21k
      key->specified & ~(AVTAB_ENABLED | AVTAB_ENABLED_OLD);
254
255
1.21k
  if (!h || !h->htable)
256
0
    return NULL;
257
258
1.21k
  hvalue = avtab_hash(key, h->mask);
259
8.08k
  for (cur = h->htable[hvalue]; cur; cur = cur->next) {
260
7.60k
    if (key->source_type == cur->key.source_type &&
261
4.50k
        key->target_type == cur->key.target_type &&
262
2.75k
        key->target_class == cur->key.target_class &&
263
1.97k
        (specified & cur->key.specified))
264
382
      return cur;
265
266
7.22k
    if (key->source_type < cur->key.source_type)
267
144
      break;
268
7.08k
    if (key->source_type == cur->key.source_type &&
269
4.11k
        key->target_type < cur->key.target_type)
270
123
      break;
271
6.95k
    if (key->source_type == cur->key.source_type &&
272
3.99k
        key->target_type == cur->key.target_type &&
273
2.37k
        key->target_class < cur->key.target_class)
274
90
      break;
275
6.95k
  }
276
833
  return NULL;
277
1.21k
}
278
279
avtab_ptr_t avtab_search_node_next(avtab_ptr_t node, int specified)
280
718
{
281
718
  avtab_ptr_t cur;
282
283
718
  if (!node)
284
0
    return NULL;
285
286
718
  specified &= ~(AVTAB_ENABLED | AVTAB_ENABLED_OLD);
287
1.38k
  for (cur = node->next; cur; cur = cur->next) {
288
1.16k
    if (node->key.source_type == cur->key.source_type &&
289
1.04k
        node->key.target_type == cur->key.target_type &&
290
938
        node->key.target_class == cur->key.target_class &&
291
897
        (specified & cur->key.specified))
292
226
      return cur;
293
294
942
    if (node->key.source_type < cur->key.source_type)
295
121
      break;
296
821
    if (node->key.source_type == cur->key.source_type &&
297
821
        node->key.target_type < cur->key.target_type)
298
109
      break;
299
712
    if (node->key.source_type == cur->key.source_type &&
300
712
        node->key.target_type == cur->key.target_type &&
301
712
        node->key.target_class < cur->key.target_class)
302
41
      break;
303
712
  }
304
492
  return NULL;
305
718
}
306
307
void avtab_destroy(avtab_t * h)
308
51.8k
{
309
51.8k
  unsigned int i;
310
51.8k
  avtab_ptr_t cur, temp;
311
312
51.8k
  if (!h || !h->htable)
313
38.1k
    return;
314
315
428M
  for (i = 0; i < h->nslot; i++) {
316
428M
    cur = h->htable[i];
317
428M
    while (cur != NULL) {
318
20.3k
      if (cur->key.specified & AVTAB_XPERMS) {
319
6.80k
        free(cur->datum.xperms);
320
6.80k
      }
321
20.3k
      temp = cur;
322
20.3k
      cur = cur->next;
323
20.3k
      free(temp);
324
20.3k
    }
325
428M
    h->htable[i] = NULL;
326
428M
  }
327
13.6k
  free(h->htable);
328
13.6k
  h->htable = NULL;
329
13.6k
  h->nslot = 0;
330
13.6k
  h->mask = 0;
331
13.6k
}
332
333
int avtab_map(const avtab_t * h,
334
        int (*apply) (avtab_key_t * k,
335
          avtab_datum_t * d, void *args), void *args)
336
25.1k
{
337
25.1k
  unsigned int i;
338
25.1k
  int ret;
339
25.1k
  avtab_ptr_t cur;
340
341
25.1k
  if (!h)
342
0
    return 0;
343
344
3.30G
  for (i = 0; i < h->nslot; i++) {
345
3.30G
    cur = h->htable[i];
346
3.30G
    while (cur != NULL) {
347
38.7k
      ret = apply(&cur->key, &cur->datum, args);
348
38.7k
      if (ret)
349
318
        return ret;
350
38.4k
      cur = cur->next;
351
38.4k
    }
352
3.30G
  }
353
24.8k
  return 0;
354
25.1k
}
355
356
int avtab_init(avtab_t * h)
357
26.6k
{
358
26.6k
  h->htable = NULL;
359
26.6k
  h->nel = 0;
360
26.6k
  return 0;
361
26.6k
}
362
363
int avtab_alloc(avtab_t *h, uint32_t nrules)
364
19.8k
{
365
19.8k
  uint32_t mask = 0;
366
19.8k
  uint32_t shift = 0;
367
19.8k
  uint32_t work = nrules;
368
19.8k
  uint32_t nslot = 0;
369
370
19.8k
  if (nrules == 0)
371
6.25k
    goto out;
372
373
47.2k
  while (work) {
374
33.5k
    work  = work >> 1;
375
33.5k
    shift++;
376
33.5k
  }
377
13.6k
  if (shift > 2)
378
1.68k
    shift = shift - 2;
379
13.6k
  nslot = UINT32_C(1) << shift;
380
13.6k
  if (nslot > MAX_AVTAB_HASH_BUCKETS)
381
0
    nslot = MAX_AVTAB_HASH_BUCKETS;
382
13.6k
  mask = nslot - 1;
383
384
13.6k
  h->htable = calloc(nslot, sizeof(avtab_ptr_t));
385
13.6k
  if (!h->htable)
386
0
    return -1;
387
19.8k
out:
388
19.8k
  h->nel = 0;
389
19.8k
  h->nslot = nslot;
390
19.8k
  h->mask = mask;
391
19.8k
  return 0;
392
13.6k
}
393
394
void avtab_hash_eval(avtab_t * h, char *tag)
395
0
{
396
0
  unsigned int i, chain_len, slots_used, max_chain_len;
397
0
  avtab_ptr_t cur;
398
399
0
  slots_used = 0;
400
0
  max_chain_len = 0;
401
0
  for (i = 0; i < h->nslot; i++) {
402
0
    cur = h->htable[i];
403
0
    if (cur) {
404
0
      slots_used++;
405
0
      chain_len = 0;
406
0
      while (cur) {
407
0
        chain_len++;
408
0
        cur = cur->next;
409
0
      }
410
411
0
      if (chain_len > max_chain_len)
412
0
        max_chain_len = chain_len;
413
0
    }
414
0
  }
415
416
0
  printf
417
0
      ("%s:  %d entries and %d/%d buckets used, longest chain length %d\n",
418
0
       tag, h->nel, slots_used, h->nslot, max_chain_len);
419
0
}
420
421
/* Ordering of datums in the original avtab format in the policy file. */
422
static const uint16_t spec_order[] = {
423
  AVTAB_ALLOWED,
424
  AVTAB_AUDITDENY,
425
  AVTAB_AUDITALLOW,
426
  AVTAB_TRANSITION,
427
  AVTAB_CHANGE,
428
  AVTAB_MEMBER,
429
  AVTAB_XPERMS_ALLOWED,
430
  AVTAB_XPERMS_AUDITALLOW,
431
  AVTAB_XPERMS_DONTAUDIT
432
};
433
434
int avtab_read_item(struct policy_file *fp, uint32_t vers, avtab_t * a,
435
        int (*insertf) (avtab_t * a, avtab_key_t * k,
436
            avtab_datum_t * d, void *p), void *p)
437
15.0k
{
438
15.0k
  uint8_t buf8;
439
15.0k
  uint16_t buf16[4], enabled;
440
15.0k
  uint32_t buf32[8], items, items2, val;
441
15.0k
  avtab_key_t key;
442
15.0k
  avtab_datum_t datum;
443
15.0k
  avtab_extended_perms_t xperms;
444
15.0k
  unsigned int i;
445
15.0k
  int rc;
446
447
15.0k
  memset(&key, 0, sizeof(avtab_key_t));
448
15.0k
  memset(&datum, 0, sizeof(avtab_datum_t));
449
15.0k
  memset(&xperms, 0, sizeof(avtab_extended_perms_t));
450
451
15.0k
  if (vers < POLICYDB_VERSION_AVTAB) {
452
4.96k
    rc = next_entry(buf32, fp, sizeof(uint32_t));
453
4.96k
    if (rc < 0) {
454
245
      ERR(fp->handle, "truncated entry");
455
245
      return -1;
456
245
    }
457
4.71k
    items2 = le32_to_cpu(buf32[0]);
458
459
4.71k
    if (items2 < 5 || items2 > ARRAY_SIZE(buf32)) {
460
82
      ERR(fp->handle, "invalid item count");
461
82
      return -1;
462
82
    }
463
464
4.63k
    rc = next_entry(buf32, fp, sizeof(uint32_t) * items2);
465
4.63k
    if (rc < 0) {
466
4
      ERR(fp->handle, "truncated entry");
467
4
      return -1;
468
4
    }
469
470
4.63k
    items = 0;
471
4.63k
    val = le32_to_cpu(buf32[items++]);
472
4.63k
    key.source_type = (uint16_t) val;
473
4.63k
    if (key.source_type != val) {
474
23
      ERR(fp->handle, "truncated source type");
475
23
      return -1;
476
23
    }
477
4.60k
    val = le32_to_cpu(buf32[items++]);
478
4.60k
    key.target_type = (uint16_t) val;
479
4.60k
    if (key.target_type != val) {
480
27
      ERR(fp->handle, "truncated target type");
481
27
      return -1;
482
27
    }
483
4.58k
    val = le32_to_cpu(buf32[items++]);
484
4.58k
    key.target_class = (uint16_t) val;
485
4.58k
    if (key.target_class != val) {
486
27
      ERR(fp->handle, "truncated target class");
487
27
      return -1;
488
27
    }
489
490
4.55k
    val = le32_to_cpu(buf32[items++]);
491
4.55k
    enabled = (val & AVTAB_ENABLED_OLD) ? AVTAB_ENABLED : 0;
492
493
4.55k
    if (!(val & (AVTAB_AV | AVTAB_TYPE))) {
494
11
      ERR(fp->handle, "null entry");
495
11
      return -1;
496
11
    }
497
4.54k
    if ((val & AVTAB_AV) && (val & AVTAB_TYPE)) {
498
4
      ERR(fp->handle, "entry has both access "
499
4
          "vectors and types");
500
4
      return -1;
501
4
    }
502
503
45.1k
    for (i = 0; i < ARRAY_SIZE(spec_order); i++) {
504
40.7k
      if (val & spec_order[i]) {
505
10.3k
        if (items >= items2) { /* items is index, items2 is total number */
506
76
          ERR(fp->handle, "entry has too many items (%d/%d)",
507
76
              items + 1, items2);
508
76
          return -1;
509
76
        }
510
10.2k
        key.specified = spec_order[i] | enabled;
511
10.2k
        datum.data = le32_to_cpu(buf32[items++]);
512
10.2k
        rc = insertf(a, &key, &datum, p);
513
10.2k
        if (rc)
514
2
          return rc;
515
10.2k
      }
516
40.7k
    }
517
518
4.46k
    if (items != items2) {
519
10
      ERR(fp->handle, "entry only had %d items, "
520
10
          "expected %d", items2, items);
521
10
      return -1;
522
10
    }
523
4.45k
    return 0;
524
4.46k
  }
525
526
10.1k
  rc = next_entry(buf16, fp, sizeof(uint16_t) * 4);
527
10.1k
  if (rc < 0) {
528
312
    ERR(fp->handle, "truncated entry");
529
312
    return -1;
530
312
  }
531
9.80k
  items = 0;
532
9.80k
  key.source_type = le16_to_cpu(buf16[items++]);
533
9.80k
  key.target_type = le16_to_cpu(buf16[items++]);
534
9.80k
  key.target_class = le16_to_cpu(buf16[items++]);
535
9.80k
  key.specified = le16_to_cpu(buf16[items++]);
536
537
9.80k
  if (key.specified & ~(AVTAB_AV | AVTAB_TYPE | AVTAB_XPERMS | AVTAB_ENABLED)) {
538
14
    ERR(fp->handle, "invalid specifier");
539
14
    return -1;
540
14
  }
541
542
9.79k
  if (__builtin_popcount(key.specified & ~AVTAB_ENABLED) != 1) {
543
11
    ERR(fp->handle, "not exactly one specifier");
544
11
    return -1;
545
11
  }
546
547
9.78k
  if ((vers < POLICYDB_VERSION_XPERMS_IOCTL) &&
548
2.59k
      (key.specified & AVTAB_XPERMS)) {
549
4
    ERR(fp->handle, "policy version %u does not support extended "
550
4
        "permissions rules and one was specified", vers);
551
4
    return -1;
552
9.78k
  } else if (key.specified & AVTAB_XPERMS) {
553
4.06k
    rc = next_entry(&buf8, fp, sizeof(uint8_t));
554
4.06k
    if (rc < 0) {
555
1
      ERR(fp->handle, "truncated entry");
556
1
      return -1;
557
1
    }
558
4.06k
    xperms.specified = buf8;
559
4.06k
    rc = next_entry(&buf8, fp, sizeof(uint8_t));
560
4.06k
    if (rc < 0) {
561
1
      ERR(fp->handle, "truncated entry");
562
1
      return -1;
563
1
    }
564
4.06k
    xperms.driver = buf8;
565
4.06k
    rc = next_entry(buf32, fp, sizeof(uint32_t)*8);
566
4.06k
    if (rc < 0) {
567
2
      ERR(fp->handle, "truncated entry");
568
2
      return -1;
569
2
    }
570
36.5k
    for (i = 0; i < ARRAY_SIZE(xperms.perms); i++)
571
32.4k
      xperms.perms[i] = le32_to_cpu(buf32[i]);
572
4.06k
    datum.xperms = &xperms;
573
5.71k
  } else {
574
5.71k
    rc = next_entry(buf32, fp, sizeof(uint32_t));
575
5.71k
    if (rc < 0) {
576
3
      ERR(fp->handle, "truncated entry");
577
3
      return -1;
578
3
    }
579
5.71k
    datum.data = le32_to_cpu(*buf32);
580
5.71k
  }
581
9.77k
  return insertf(a, &key, &datum, p);
582
9.78k
}
583
584
static int avtab_insertf(avtab_t * a, avtab_key_t * k, avtab_datum_t * d,
585
       void *p __attribute__ ((unused)))
586
9.57k
{
587
9.57k
  return avtab_insert(a, k, d);
588
9.57k
}
589
590
int avtab_read(avtab_t * a, struct policy_file *fp, uint32_t vers)
591
6.97k
{
592
6.97k
  unsigned int i;
593
6.97k
  int rc;
594
6.97k
  uint32_t buf[1];
595
6.97k
  uint32_t nel;
596
597
6.97k
  rc = next_entry(buf, fp, sizeof(uint32_t));
598
6.97k
  if (rc < 0) {
599
7
    ERR(fp->handle, "truncated table");
600
7
    goto bad;
601
7
  }
602
6.97k
  nel = le32_to_cpu(buf[0]);
603
6.97k
  if (zero_or_saturated(nel) || exceeds_available_bytes(fp, nel, sizeof(uint32_t) * 3)) {
604
83
    ERR(fp->handle, "table is empty");
605
83
    goto bad;
606
83
  }
607
608
6.88k
  rc = avtab_alloc(a, nel);
609
6.88k
  if (rc) {
610
0
    ERR(fp->handle, "out of memory");
611
0
    goto bad;
612
0
  }
613
614
15.1k
  for (i = 0; i < nel; i++) {
615
8.60k
    rc = avtab_read_item(fp, vers, a, avtab_insertf, NULL);
616
8.60k
    if (rc) {
617
299
      if (rc == SEPOL_ENOMEM)
618
299
        ERR(fp->handle, "out of memory");
619
299
      if (rc == SEPOL_EEXIST)
620
299
        ERR(fp->handle, "duplicate entry");
621
299
      ERR(fp->handle, "failed on entry %d of %u", i, nel);
622
299
      goto bad;
623
299
    }
624
8.60k
  }
625
626
6.58k
  return 0;
627
628
389
      bad:
629
389
  avtab_destroy(a);
630
389
  return -1;
631
6.88k
}