Coverage Report

Created: 2026-05-23 07:04

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/selinux/libsepol/src/avrule_block.c
Line
Count
Source
1
/* Authors: Jason Tang <jtang@tresys.com>
2
 *
3
 * Functions that manipulate a logical block (conditional, optional,
4
 * or global scope) for a policy module.
5
 *
6
 * Copyright (C) 2005 Tresys Technology, LLC
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/avrule_block.h>
26
27
#include <assert.h>
28
#include <stdlib.h>
29
30
/* It is anticipated that there be less declarations within an avrule
31
 * block than the global policy.  Thus the symbol table sizes are
32
 * smaller than those listed in policydb.c */
33
static const unsigned int symtab_sizes[SYM_NUM] = {
34
  2,
35
  4,
36
  8,
37
  32,
38
  16,
39
  4,
40
  2,
41
  2,
42
};
43
44
avrule_block_t *avrule_block_create(void)
45
12.3k
{
46
12.3k
  avrule_block_t *block;
47
12.3k
  if ((block = calloc(1, sizeof(*block))) == NULL) {
48
0
    return NULL;
49
0
  }
50
12.3k
  return block;
51
12.3k
}
52
53
avrule_decl_t *avrule_decl_create(uint32_t decl_id)
54
17.4k
{
55
17.4k
  avrule_decl_t *decl;
56
17.4k
  int i;
57
17.4k
  if ((decl = calloc(1, sizeof(*decl))) == NULL) {
58
0
    return NULL;
59
0
  }
60
17.4k
  decl->decl_id = decl_id;
61
157k
  for (i = 0; i < SYM_NUM; i++) {
62
139k
    if (symtab_init(&decl->symtab[i], symtab_sizes[i])) {
63
0
      avrule_decl_destroy(decl);
64
0
      return NULL;
65
0
    }
66
139k
  }
67
68
157k
  for (i = 0; i < SYM_NUM; i++) {
69
139k
    ebitmap_init(&decl->required.scope[i]);
70
139k
    ebitmap_init(&decl->declared.scope[i]);
71
139k
  }
72
17.4k
  return decl;
73
17.4k
}
74
75
/* note that unlike the other destroy functions, this one does /NOT/
76
 * destroy the pointer itself */
77
static void scope_index_destroy(scope_index_t * scope)
78
34.9k
{
79
34.9k
  unsigned int i;
80
34.9k
  if (scope == NULL) {
81
0
    return;
82
0
  }
83
314k
  for (i = 0; i < SYM_NUM; i++) {
84
279k
    ebitmap_destroy(scope->scope + i);
85
279k
  }
86
34.9k
  if (scope->class_perms_map) {
87
14.3k
    for (i = 0; i < scope->class_perms_len; i++) {
88
12.8k
      ebitmap_destroy(scope->class_perms_map + i);
89
12.8k
    }
90
1.49k
  }
91
34.9k
  free(scope->class_perms_map);
92
34.9k
}
93
94
void avrule_decl_destroy(avrule_decl_t * x)
95
17.4k
{
96
17.4k
  if (x == NULL) {
97
0
    return;
98
0
  }
99
17.4k
  cond_list_destroy(x->cond_list);
100
17.4k
  avrule_list_destroy(x->avrules);
101
17.4k
  role_trans_rule_list_destroy(x->role_tr_rules);
102
17.4k
  filename_trans_rule_list_destroy(x->filename_trans_rules);
103
17.4k
  role_allow_rule_list_destroy(x->role_allow_rules);
104
17.4k
  range_trans_rule_list_destroy(x->range_tr_rules);
105
17.4k
  scope_index_destroy(&x->required);
106
17.4k
  scope_index_destroy(&x->declared);
107
17.4k
  symtabs_destroy(x->symtab);
108
17.4k
  free(x->module_name);
109
17.4k
  free(x);
110
17.4k
}
111
112
void avrule_block_destroy(avrule_block_t * x)
113
43.2k
{
114
43.2k
  avrule_decl_t *decl;
115
43.2k
  if (x == NULL) {
116
0
    return;
117
0
  }
118
43.2k
  decl = x->branch_list;
119
59.7k
  while (decl != NULL) {
120
16.5k
    avrule_decl_t *next_decl = decl->next;
121
16.5k
    avrule_decl_destroy(decl);
122
16.5k
    decl = next_decl;
123
16.5k
  }
124
43.2k
  free(x);
125
43.2k
}
126
127
void avrule_block_list_destroy(avrule_block_t * x)
128
24.5k
{
129
64.3k
  while (x != NULL) {
130
39.7k
    avrule_block_t *next = x->next;
131
39.7k
    avrule_block_destroy(x);
132
39.7k
    x = next;
133
39.7k
  }
134
24.5k
}
135
136
/* Get a conditional node from a avrule_decl with the same expression.
137
 * If that expression does not exist then create one. */
138
cond_list_t *get_decl_cond_list(policydb_t * p, avrule_decl_t * decl,
139
        cond_list_t * cond)
140
0
{
141
0
  cond_list_t *result;
142
0
  int was_created;
143
0
  result = cond_node_find(p, cond, decl->cond_list, &was_created);
144
0
  if (result != NULL && was_created) {
145
0
    result->next = decl->cond_list;
146
0
    decl->cond_list = result;
147
0
  }
148
0
  return result;
149
0
}
150
151
/* Look up an identifier in a policy's scoping table.  If it is there,
152
 * marked as SCOPE_DECL, and any of its declaring block has been enabled,
153
 * then return 1.  Otherwise return 0. Can only be called after the 
154
 * decl_val_to_struct index has been created */
155
int is_id_enabled(const char *id, const policydb_t * p, int symbol_table)
156
9
{
157
9
  const scope_datum_t *scope =
158
9
      (scope_datum_t *) hashtab_search(p->scope[symbol_table].table, id);
159
9
  const avrule_decl_t *decl;
160
9
  uint32_t len;
161
162
9
  if (scope == NULL) {
163
9
    return 0;
164
9
  }
165
0
  if (scope->scope != SCOPE_DECL) {
166
0
    return 0;
167
0
  }
168
169
0
  len = scope->decl_ids_len;
170
0
  if (len < 1) {
171
0
    return 0;
172
0
  }
173
174
0
  if (symbol_table == SYM_ROLES || symbol_table == SYM_USERS) {
175
0
    uint32_t i;
176
0
    for (i = 0; i < len; i++) {
177
0
      decl = p->decl_val_to_struct[scope->decl_ids[i] - 1];
178
0
      if (decl != NULL && decl->enabled) {
179
0
        return 1;
180
0
      }
181
0
    }
182
0
  } else {
183
0
    decl = p->decl_val_to_struct[scope->decl_ids[len-1] - 1];
184
0
    if (decl != NULL && decl->enabled) {
185
0
      return 1;
186
0
    }
187
0
  }
188
189
0
  return 0;
190
0
}
191
192
/* Check if a particular permission is present within the given class.
193
 * Whether the class is enabled is NOT checked.
194
 * Returns 1 if permission is present, 0 otherwise */
195
int is_perm_existent(const class_datum_t *cladatum, const char *perm_id)
196
0
{
197
0
  const perm_datum_t *perm;
198
199
0
  perm = hashtab_search(cladatum->permissions.table, perm_id);
200
0
  if (perm == NULL && cladatum->comdatum != 0) {
201
    /* permission was not in this class.  before giving
202
     * up, check the class's parent */
203
0
    perm =
204
0
        hashtab_search(cladatum->comdatum->permissions.table,
205
0
           perm_id);
206
0
  }
207
0
  if (perm == NULL) {
208
0
    return 0;
209
0
  }
210
0
  return 1;
211
0
}