Coverage Report

Created: 2025-11-11 06:44

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/selinux/libsepol/src/sidtab.c
Line
Count
Source
1
2
/* Author : Stephen Smalley, <stephen.smalley.work@gmail.com> */
3
4
/* FLASK */
5
6
/*
7
 * Implementation of the SID table type.
8
 */
9
10
#include <stdlib.h>
11
#include <errno.h>
12
#include <limits.h>
13
#include <stdio.h>
14
15
#include <sepol/policydb/sidtab.h>
16
17
#include "flask.h"
18
#include "private.h"
19
20
228
#define SIDTAB_HASH(sid) \
21
228
(sid & SIDTAB_HASH_MASK)
22
23
#define INIT_SIDTAB_LOCK(s)
24
#define SIDTAB_LOCK(s)
25
#define SIDTAB_UNLOCK(s)
26
27
int sepol_sidtab_init(sidtab_t * s)
28
1.32k
{
29
1.32k
  s->htable = calloc(SIDTAB_SIZE, sizeof(sidtab_ptr_t));
30
1.32k
  if (!s->htable)
31
0
    return -ENOMEM;
32
1.32k
  s->nel = 0;
33
1.32k
  s->next_sid = 1;
34
1.32k
  s->shutdown = 0;
35
1.32k
  INIT_SIDTAB_LOCK(s);
36
1.32k
  return 0;
37
1.32k
}
38
39
int sepol_sidtab_insert(sidtab_t * s, sepol_security_id_t sid,
40
      context_struct_t * context)
41
228
{
42
228
  int hvalue;
43
228
  sidtab_node_t *prev, *cur, *newnode;
44
45
228
  if (!s || !s->htable)
46
0
    return -ENOMEM;
47
48
228
  hvalue = SIDTAB_HASH(sid);
49
228
  prev = NULL;
50
228
  cur = s->htable[hvalue];
51
228
  while (cur != NULL && sid > cur->sid) {
52
0
    prev = cur;
53
0
    cur = cur->next;
54
0
  }
55
56
228
  if (cur && sid == cur->sid) {
57
5
    errno = EEXIST;
58
5
    return -EEXIST;
59
5
  }
60
61
223
  newnode = (sidtab_node_t *) malloc(sizeof(sidtab_node_t));
62
223
  if (newnode == NULL)
63
0
    return -ENOMEM;
64
223
  newnode->sid = sid;
65
223
  if (context_cpy(&newnode->context, context)) {
66
0
    free(newnode);
67
0
    return -ENOMEM;
68
0
  }
69
70
223
  if (prev) {
71
0
    newnode->next = prev->next;
72
0
    prev->next = newnode;
73
223
  } else {
74
223
    newnode->next = s->htable[hvalue];
75
223
    s->htable[hvalue] = newnode;
76
223
  }
77
78
223
  s->nel++;
79
223
  if (sid >= s->next_sid)
80
95
    s->next_sid = sid + 1;
81
223
  return 0;
82
223
}
83
84
context_struct_t *sepol_sidtab_search(sidtab_t * s, sepol_security_id_t sid)
85
0
{
86
0
  int hvalue;
87
0
  sidtab_node_t *cur;
88
89
0
  if (!s || !s->htable)
90
0
    return NULL;
91
92
0
  hvalue = SIDTAB_HASH(sid);
93
0
  cur = s->htable[hvalue];
94
0
  while (cur != NULL && sid > cur->sid)
95
0
    cur = cur->next;
96
97
0
  if (cur == NULL || sid != cur->sid) {
98
    /* Remap invalid SIDs to the unlabeled SID. */
99
0
    sid = SECINITSID_UNLABELED;
100
0
    hvalue = SIDTAB_HASH(sid);
101
0
    cur = s->htable[hvalue];
102
0
    while (cur != NULL && sid > cur->sid)
103
0
      cur = cur->next;
104
0
    if (!cur || sid != cur->sid)
105
0
      return NULL;
106
0
  }
107
108
0
  return &cur->context;
109
0
}
110
111
int sepol_sidtab_map(sidtab_t * s,
112
         int (*apply) (sepol_security_id_t sid,
113
           context_struct_t * context,
114
           void *args), void *args)
115
0
{
116
0
  int i, ret;
117
0
  sidtab_node_t *cur;
118
119
0
  if (!s || !s->htable)
120
0
    return 0;
121
122
0
  for (i = 0; i < SIDTAB_SIZE; i++) {
123
0
    cur = s->htable[i];
124
0
    while (cur != NULL) {
125
0
      ret = apply(cur->sid, &cur->context, args);
126
0
      if (ret)
127
0
        return ret;
128
0
      cur = cur->next;
129
0
    }
130
0
  }
131
0
  return 0;
132
0
}
133
134
void sepol_sidtab_map_remove_on_error(sidtab_t * s,
135
              int (*apply) (sepol_security_id_t sid,
136
                context_struct_t * context,
137
                void *args), void *args)
138
0
{
139
0
  int i, ret;
140
0
  sidtab_node_t *last, *cur, *temp;
141
142
0
  if (!s || !s->htable)
143
0
    return;
144
145
0
  for (i = 0; i < SIDTAB_SIZE; i++) {
146
0
    last = NULL;
147
0
    cur = s->htable[i];
148
0
    while (cur != NULL) {
149
0
      ret = apply(cur->sid, &cur->context, args);
150
0
      if (ret) {
151
0
        if (last) {
152
0
          last->next = cur->next;
153
0
        } else {
154
0
          s->htable[i] = cur->next;
155
0
        }
156
157
0
        temp = cur;
158
0
        cur = cur->next;
159
0
        context_destroy(&temp->context);
160
0
        free(temp);
161
0
        s->nel--;
162
0
      } else {
163
0
        last = cur;
164
0
        cur = cur->next;
165
0
      }
166
0
    }
167
0
  }
168
169
0
  return;
170
0
}
171
172
static inline sepol_security_id_t sepol_sidtab_search_context(sidtab_t * s,
173
                    context_struct_t *
174
                    context)
175
0
{
176
0
  int i;
177
0
  sidtab_node_t *cur;
178
179
0
  for (i = 0; i < SIDTAB_SIZE; i++) {
180
0
    cur = s->htable[i];
181
0
    while (cur != NULL) {
182
0
      if (context_cmp(&cur->context, context))
183
0
        return cur->sid;
184
0
      cur = cur->next;
185
0
    }
186
0
  }
187
0
  return 0;
188
0
}
189
190
int sepol_sidtab_context_to_sid(sidtab_t * s,
191
        context_struct_t * context,
192
        sepol_security_id_t * out_sid)
193
0
{
194
0
  sepol_security_id_t sid;
195
0
  int ret = 0;
196
197
0
  *out_sid = SEPOL_SECSID_NULL;
198
199
0
  sid = sepol_sidtab_search_context(s, context);
200
0
  if (!sid) {
201
0
    SIDTAB_LOCK(s);
202
    /* Rescan now that we hold the lock. */
203
0
    sid = sepol_sidtab_search_context(s, context);
204
0
    if (sid)
205
0
      goto unlock_out;
206
    /* No SID exists for the context.  Allocate a new one. */
207
0
    if (s->next_sid == UINT_MAX || s->shutdown) {
208
0
      ret = -ENOMEM;
209
0
      goto unlock_out;
210
0
    }
211
0
    sid = s->next_sid++;
212
0
    ret = sepol_sidtab_insert(s, sid, context);
213
0
    if (ret)
214
0
      s->next_sid--;
215
0
        unlock_out:
216
0
    SIDTAB_UNLOCK(s);
217
0
  }
218
219
0
  if (ret)
220
0
    return ret;
221
222
0
  *out_sid = sid;
223
0
  return 0;
224
0
}
225
226
void sepol_sidtab_hash_eval(sidtab_t * h, char *tag)
227
0
{
228
0
  int i, chain_len, slots_used, max_chain_len;
229
0
  sidtab_node_t *cur;
230
231
0
  slots_used = 0;
232
0
  max_chain_len = 0;
233
0
  for (i = 0; i < SIDTAB_SIZE; i++) {
234
0
    cur = h->htable[i];
235
0
    if (cur) {
236
0
      slots_used++;
237
0
      chain_len = 0;
238
0
      while (cur) {
239
0
        chain_len++;
240
0
        cur = cur->next;
241
0
      }
242
243
0
      if (chain_len > max_chain_len)
244
0
        max_chain_len = chain_len;
245
0
    }
246
0
  }
247
248
0
  printf
249
0
      ("%s:  %d entries and %d/%d buckets used, longest chain length %d\n",
250
0
       tag, h->nel, slots_used, SIDTAB_SIZE, max_chain_len);
251
0
}
252
253
void sepol_sidtab_destroy(sidtab_t * s)
254
12.7k
{
255
12.7k
  int i;
256
12.7k
  sidtab_ptr_t cur, temp;
257
258
12.7k
  if (!s || !s->htable)
259
11.4k
    return;
260
261
171k
  for (i = 0; i < SIDTAB_SIZE; i++) {
262
169k
    cur = s->htable[i];
263
170k
    while (cur != NULL) {
264
223
      temp = cur;
265
223
      cur = cur->next;
266
223
      context_destroy(&temp->context);
267
223
      free(temp);
268
223
    }
269
169k
    s->htable[i] = NULL;
270
169k
  }
271
1.32k
  free(s->htable);
272
1.32k
  s->htable = NULL;
273
1.32k
  s->nel = 0;
274
1.32k
  s->next_sid = 1;
275
1.32k
}
276
277
void sepol_sidtab_set(sidtab_t * dst, sidtab_t * src)
278
0
{
279
0
  SIDTAB_LOCK(src);
280
0
  dst->htable = src->htable;
281
0
  dst->nel = src->nel;
282
0
  dst->next_sid = src->next_sid;
283
0
  dst->shutdown = 0;
284
0
  SIDTAB_UNLOCK(src);
285
0
}
286
287
void sepol_sidtab_shutdown(sidtab_t * s)
288
0
{
289
0
  SIDTAB_LOCK(s);
290
0
  s->shutdown = 1;
291
0
  SIDTAB_UNLOCK(s);
292
0
}
293
294
/* FLASK */