Coverage Report

Created: 2026-01-17 06:07

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/selinux/libsepol/cil/src/cil_deny.c
Line
Count
Source
1
/*
2
 * This file is public domain software, i.e. not copyrighted.
3
 *
4
 * Warranty Exclusion
5
 * ------------------
6
 * You agree that this software is a non-commercially developed program
7
 * that may contain "bugs" (as that term is used in the industry) and
8
 * that it may not function as intended. The software is licensed
9
 * "as is". NSA makes no, and hereby expressly disclaims all, warranties,
10
 * express, implied, statutory, or otherwise with respect to the software,
11
 * including noninfringement and the implied warranties of merchantability
12
 * and fitness for a particular purpose.
13
 *
14
 * Limitation of Liability
15
 *-----------------------
16
 * In no event will NSA be liable for any damages, including loss of data,
17
 * lost profits, cost of cover, or other special, incidental, consequential,
18
 * direct or indirect damages arising from the software or the use thereof,
19
 * however caused and on any theory of liability. This limitation will apply
20
 * even if NSA has been advised of the possibility of such damage. You
21
 * acknowledge that this is a reasonable allocation of risk.
22
 *
23
 * Original author: James Carter
24
 */
25
26
#include <sepol/policydb/ebitmap.h>
27
28
#include "cil_internal.h"
29
#include "cil_find.h"
30
#include "cil_flavor.h"
31
#include "cil_list.h"
32
#include "cil_strpool.h"
33
#include "cil_log.h"
34
#include "cil_symtab.h"
35
#include "cil_build_ast.h"
36
#include "cil_copy_ast.h"
37
#include "cil_deny.h"
38
39
31.9k
#define CIL_DENY_ATTR_PREFIX "deny_rule_attr"
40
41
/*
42
 * A deny rule is like a neverallow rule, except that permissions are
43
 * removed rather than an error reported.
44
 *
45
 * (allow S1 T1 P1)
46
 * (deny  S2 T2 P2)
47
 *
48
 * First, write the allow rule with all of the permissions not in the deny rule
49
 * P3 = P1 and not P2
50
 * (allow S1 T1 P3)
51
 *
52
 * Obviously, the rule is only written if P3 is not an empty list. This goes
53
 * for the rest of the rules as well--they are only written if the source and
54
 * target exist.
55
 *
56
 * The remaining rules will only involve the common permissions
57
 * P4 = P1 and P2
58
 *
59
 * Next, write the allow rule for any types in S1 that are not in S2
60
 * S3 = S1 and not S2
61
 * (allow S3 T1 P4)
62
 *
63
 * Finally, write any allow rules needed to cover the types in T1 that are
64
 * not in T2. Since, T1 and T2 might be "self", "notself", or "other", this
65
 * requires more complicated handling. Any rule with "self" will not match
66
 * a rule with either "notself" or "other".
67
 *
68
 * if (T1 is self and T2 is self) or (T1 is notself and T2 is notself) then
69
 *   Nothing more needs to be done.
70
 *
71
 * The rest of the rules will depend on the intersection of S1 and S2
72
 * which cannot be the empty set since the allow and deny rules match.
73
 * S4 = S1 and S2
74
 *
75
 * if T1 is notself or T1 is other or T2 is notself or T2 is other then
76
 *   if T1 is notself then
77
 *     if T2 is other then
78
 *       T = ALL and not S2
79
 *       (allow S4 T P4)
80
 *     else [T2 is not self, notself, or other]
81
 *       S5 = S4 and not T2
82
 *       S6 = S4 and T2
83
 *       TA = ALL and not T2
84
 *       TB = TA and not S4
85
 *       (allow S6 TA P4)
86
 *       (allow S5 TB P4)
87
 *       if cardinality(S5) > 1 then
88
 *         (allow S5 other P4)
89
 *   else if T1 is other then
90
 *     (allow S3 S4 P4)
91
 *     if T2 is notself then
92
 *       [Nothing else is needed]
93
 *     else if T2 is other then
94
 *       (allow S4 S3 P4)
95
 *     else [T2 is not self, notself, or other]
96
 *       S5 = S4 and not T2
97
 *       S6 = S4 and T2
98
 *       TC = S1 and not T2
99
 *       TD = S3 and not T2
100
 *       (allow S6 TC P4)
101
 *       (allow S5 TD P4)
102
 *       if cardinality(S5) > 1 then
103
 *         (allow S5 other P4)
104
 *   else [T1 is not self, notself, or other]
105
 *     S8 = S4 and T1
106
 *     (allow S8 self P4)
107
 *     if T2 is notself then
108
 *       [Nothing else is needed]
109
 *     else [T2 is other]
110
 *       T = T1 and not S2
111
 *       (allow S4 T P4)
112
 * else [Neither T1 nor T2 are notself or other]
113
 *   if T1 is self and T2 is not self then
114
 *     S5 = S4 and not T2
115
 *     (allow S5 self P4)
116
 *   else if T1 is not self and T2 is self then
117
 *     S7 = S4 and not T1
118
 *     S8 = S4 and T1
119
 *     T8 = T1 and not S4
120
 *     (allow S7 T1 P4)
121
 *     (allow S8 T8 P4)
122
 *     if cardinality(S8) > 1 then
123
 *       (allow S8 other P4)
124
 *   else [Neither T1 nor T2 is self]
125
 *     T3 = T1 and not T2
126
 *     (allow S4 T3 P4)
127
 */
128
129
static int cil_perm_match(const struct cil_perm *p1, const struct cil_list *pl2)
130
1.80M
{
131
1.80M
  struct cil_list_item *curr;
132
133
2.41M
  cil_list_for_each(curr, pl2) {
134
2.41M
    struct cil_perm *p = curr->data;
135
2.41M
    if (p == p1) {
136
1.51M
      return CIL_TRUE;
137
1.51M
    }
138
2.41M
  }
139
293k
  return CIL_FALSE;
140
1.80M
}
141
142
static int cil_class_perm_match(const struct cil_class *c1, const struct cil_perm *p1, const struct cil_list *cpl2)
143
2.95M
{
144
2.95M
  struct cil_list_item *curr;
145
146
3.14M
  cil_list_for_each(curr, cpl2) {
147
3.14M
    if (curr->flavor == CIL_CLASSPERMS) {
148
1.89M
      struct cil_classperms *cp = curr->data;
149
1.89M
      if (FLAVOR(cp->class) == CIL_CLASS) {
150
1.81M
        if (cp->class == c1) {
151
1.80M
          if (cil_perm_match(p1, cp->perms)) {
152
1.51M
            return CIL_TRUE;
153
1.51M
          }
154
1.80M
        }
155
1.81M
      } else { /* MAP */
156
82.8k
        struct cil_list_item *p;
157
104k
        cil_list_for_each(p, cp->perms) {
158
104k
          struct cil_perm *cmp = p->data;
159
104k
          if (cil_class_perm_match(c1, p1, cmp->classperms)) {
160
47.1k
            return CIL_TRUE;
161
47.1k
          }
162
104k
        }
163
82.8k
      }
164
1.89M
    } else { /* SET */
165
1.24M
      struct cil_classperms_set *cp_set = curr->data;
166
1.24M
      struct cil_classpermission *cp = cp_set->set;
167
1.24M
      if (cil_class_perm_match(c1, p1, cp->classperms)) {
168
1.07M
        return CIL_TRUE;
169
1.07M
      }
170
1.24M
    }
171
3.14M
  }
172
317k
  return CIL_FALSE;
173
2.95M
}
174
175
static int cil_classperms_match_any(const struct cil_classperms *cp1, const struct cil_list *cpl2)
176
686k
{
177
686k
  struct cil_list_item *curr;
178
179
702k
  cil_list_for_each(curr, cp1->perms) {
180
702k
    struct cil_perm *perm = curr->data;
181
702k
    if (cil_class_perm_match(cp1->class, perm, cpl2)) {
182
675k
      return CIL_TRUE;
183
675k
    }
184
702k
  }
185
11.5k
  return CIL_FALSE;
186
686k
}
187
188
int cil_classperms_list_match_any(const struct cil_list *cpl1, const struct cil_list *cpl2)
189
436k
{
190
436k
  struct cil_list_item *curr;
191
192
436k
  if (!cpl1 || !cpl2) {
193
0
    return (!cpl1 && !cpl2) ? CIL_TRUE : CIL_FALSE;
194
0
  }
195
196
442k
  cil_list_for_each(curr, cpl1) {
197
442k
    if (curr->flavor == CIL_CLASSPERMS) {
198
431k
      struct cil_classperms *cp = curr->data;
199
431k
      if (FLAVOR(cp->class) == CIL_CLASS) {
200
428k
        if (cil_classperms_match_any(cp, cpl2)) {
201
418k
          return CIL_TRUE;
202
418k
        }
203
428k
      } else { /* MAP */
204
3.25k
        struct cil_list_item *p;
205
4.43k
        cil_list_for_each(p, cp->perms) {
206
4.43k
          struct cil_perm *cmp = p->data;
207
4.43k
          if (cil_classperms_list_match_any(cmp->classperms, cpl2)) {
208
3.22k
            return CIL_TRUE;
209
3.22k
          }
210
4.43k
        }
211
3.25k
      }
212
431k
    } else { /* SET */
213
10.2k
      struct cil_classperms_set *cp_set = curr->data;
214
10.2k
      struct cil_classpermission *cp = cp_set->set;
215
10.2k
      if (cil_classperms_list_match_any(cp->classperms, cpl2)) {
216
7.74k
        return CIL_TRUE;
217
7.74k
      }
218
10.2k
    }
219
442k
  }
220
6.60k
  return CIL_FALSE;
221
436k
}
222
223
static int cil_classperms_match_all(const struct cil_classperms *cp1, const struct cil_list *cpl2)
224
282k
{
225
282k
  struct cil_list_item *curr;
226
227
448k
  cil_list_for_each(curr, cp1->perms) {
228
448k
    struct cil_perm *perm = curr->data;
229
448k
    if (!cil_class_perm_match(cp1->class, perm, cpl2)) {
230
28.0k
      return CIL_FALSE;
231
28.0k
    }
232
448k
  }
233
254k
  return CIL_TRUE;
234
282k
}
235
236
int cil_classperms_list_match_all(const struct cil_list *cpl1, const struct cil_list *cpl2)
237
278k
{
238
278k
  struct cil_list_item *curr;
239
240
278k
  if (!cpl1 || !cpl2) {
241
0
    return (!cpl1 && !cpl2) ? CIL_TRUE : CIL_FALSE;
242
0
  }
243
244
426k
  cil_list_for_each(curr, cpl1) {
245
426k
    if (curr->flavor == CIL_CLASSPERMS) {
246
274k
      struct cil_classperms *cp = curr->data;
247
274k
      if (FLAVOR(cp->class) == CIL_CLASS) {
248
270k
        if (!cil_classperms_match_all(cp, cpl2)) {
249
17.3k
          return CIL_FALSE;
250
17.3k
        }
251
270k
      } else { /* MAP */
252
3.18k
        struct cil_list_item *p;
253
4.28k
        cil_list_for_each(p, cp->perms) {
254
4.28k
          struct cil_perm *cmp = p->data;
255
4.28k
          if (!cil_classperms_list_match_all(cmp->classperms, cpl2)) {
256
1.79k
            return CIL_FALSE;
257
1.79k
          }
258
4.28k
        }
259
3.18k
      }
260
274k
    } else { /* SET */
261
151k
      struct cil_classperms_set *cp_set = curr->data;
262
151k
      struct cil_classpermission *cp = cp_set->set;
263
151k
      if (!cil_classperms_list_match_all(cp->classperms, cpl2)) {
264
3.37k
        return CIL_FALSE;
265
3.37k
      }
266
151k
    }
267
426k
  }
268
255k
  return CIL_TRUE;
269
278k
}
270
271
static void cil_classperms_copy(struct cil_classperms **new, const struct cil_classperms *old)
272
242k
{
273
242k
  cil_classperms_init(new);
274
242k
  (*new)->class_str = old->class_str;
275
242k
  (*new)->class = old->class;
276
242k
  cil_copy_list(old->perm_strs, &(*new)->perm_strs);
277
242k
  cil_copy_list(old->perms, &(*new)->perms);
278
242k
}
279
280
static void cil_classperms_set_copy(struct cil_classperms_set **new, const struct cil_classperms_set *old)
281
4.69k
{
282
4.69k
  cil_classperms_set_init(new);
283
4.69k
  (*new)->set_str = old->set_str;
284
4.69k
  (*new)->set = old->set;
285
4.69k
}
286
287
void cil_classperms_list_copy(struct cil_list **new, const struct cil_list *old)
288
236k
{
289
236k
  struct cil_list_item *curr;
290
291
236k
  if (!new) {
292
0
    return;
293
0
  }
294
295
236k
  if (!old) {
296
0
    *new = NULL;
297
0
    return;
298
0
  }
299
300
236k
  cil_list_init(new, CIL_LIST);
301
302
241k
  cil_list_for_each(curr, old) {
303
241k
    if (curr->flavor == CIL_CLASSPERMS) {
304
239k
      struct cil_classperms *new_cp;
305
239k
      cil_classperms_copy(&new_cp, curr->data);
306
239k
      cil_list_append(*new, CIL_CLASSPERMS, new_cp);
307
239k
    } else { /* SET */
308
1.39k
      struct cil_classperms_set *new_cps;
309
1.39k
      cil_classperms_set_copy(&new_cps, curr->data);
310
1.39k
      cil_list_append(*new, CIL_CLASSPERMS_SET, new_cps);
311
1.39k
    }
312
241k
  }
313
314
236k
  if (cil_list_is_empty(*new)) {
315
0
    cil_list_destroy(new, CIL_FALSE);
316
0
  }
317
236k
}
318
319
/* Append cp1 and cpl2 to result */
320
static void cil_classperms_and(struct cil_list **result, const struct cil_classperms *cp1, const struct cil_list *cpl2)
321
11.7k
{
322
11.7k
  struct cil_classperms *new_cp = NULL;
323
11.7k
  struct cil_list_item *curr;
324
325
11.7k
  if (cil_classperms_match_all(cp1, cpl2)) {
326
973
    cil_classperms_copy(&new_cp, cp1);
327
973
    cil_list_append(*result, CIL_CLASSPERMS, new_cp);
328
973
    return;
329
973
  }
330
331
26.1k
  cil_list_for_each(curr, cp1->perms) {
332
26.1k
    struct cil_perm *perm = curr->data;
333
26.1k
    if (cil_class_perm_match(cp1->class, perm, cpl2)) {
334
5.66k
      if (new_cp == NULL) {
335
5.09k
        cil_classperms_init(&new_cp);
336
5.09k
        new_cp->class_str = cp1->class_str;
337
5.09k
        new_cp->class = cp1->class;
338
5.09k
        cil_list_init(&new_cp->perm_strs, CIL_PERM);
339
5.09k
        cil_list_init(&new_cp->perms, CIL_PERM);
340
5.09k
        cil_list_append(*result, CIL_CLASSPERMS, new_cp);
341
5.09k
      }
342
5.66k
      cil_list_append(new_cp->perm_strs, CIL_STRING, perm->datum.fqn);
343
5.66k
      cil_list_append(new_cp->perms, CIL_DATUM, perm);
344
5.66k
    }
345
26.1k
  }
346
10.7k
}
347
348
/* Append cp1 and cpl2 to result */
349
static void cil_classperms_map_and(struct cil_list **result, const struct cil_classperms *cp1, const struct cil_list *cpl2)
350
3.20k
{
351
3.20k
  struct cil_classperms *new_cp = NULL;
352
3.20k
  struct cil_list_item *p;
353
354
7.86k
  cil_list_for_each(p, cp1->perms) {
355
7.86k
    struct cil_perm *map_perm = p->data;
356
7.86k
    if (cil_classperms_list_match_all(map_perm->classperms, cpl2)) {
357
3.36k
      if (new_cp == NULL) {
358
2.21k
        cil_classperms_init(&new_cp);
359
2.21k
        new_cp->class_str = cp1->class_str;
360
2.21k
        new_cp->class = cp1->class;
361
2.21k
        cil_list_init(&new_cp->perm_strs, CIL_PERM);
362
2.21k
        cil_list_init(&new_cp->perms, CIL_PERM);
363
2.21k
        cil_list_append(*result, CIL_CLASSPERMS, new_cp);
364
2.21k
      }
365
3.36k
      cil_list_append(new_cp->perm_strs, CIL_STRING, map_perm->datum.fqn);
366
3.36k
      cil_list_append(new_cp->perms, CIL_DATUM, map_perm);
367
4.49k
    } else {
368
4.49k
      struct cil_list *new_cpl = NULL;
369
4.49k
      cil_classperms_list_and(&new_cpl, map_perm->classperms, cpl2);
370
4.49k
      if (new_cpl) {
371
2.55k
        struct cil_list_item *i;
372
7.98k
        cil_list_for_each(i, new_cpl) {
373
7.98k
          cil_list_append(*result, i->flavor, i->data);
374
7.98k
        }
375
2.55k
        cil_list_destroy(&new_cpl, CIL_FALSE);
376
2.55k
      }
377
4.49k
    }
378
7.86k
  }
379
3.20k
}
380
381
/* Append cps1 and cpl2 to result */
382
static void cil_classperms_set_and(struct cil_list **result, const struct cil_classperms_set *cps1, const struct cil_list *cpl2)
383
4.43k
{
384
4.43k
  struct cil_classpermission *cp = cps1->set;
385
386
4.43k
  if (cil_classperms_list_match_all(cp->classperms, cpl2)) {
387
2.38k
    struct cil_classperms_set *new_cps;
388
2.38k
    cil_classperms_set_copy(&new_cps, cps1);
389
2.38k
    cil_list_append(*result, CIL_CLASSPERMS_SET, new_cps);
390
2.38k
  } else {
391
2.05k
    struct cil_list *new_cpl;
392
2.05k
    cil_classperms_list_and(&new_cpl, cp->classperms, cpl2);
393
2.05k
    if (new_cpl) {
394
839
      struct cil_list_item *i;
395
1.38k
      cil_list_for_each(i, new_cpl) {
396
1.38k
        cil_list_append(*result, i->flavor, i->data);
397
1.38k
      }
398
839
      cil_list_destroy(&new_cpl, CIL_FALSE);
399
839
    }
400
2.05k
  }
401
4.43k
}
402
403
/* result = cpl1 and cpl2 */
404
void cil_classperms_list_and(struct cil_list **result, const struct cil_list *cpl1, const struct cil_list *cpl2)
405
109k
{
406
109k
  struct cil_list_item *curr;
407
408
109k
  if (!result) {
409
0
    return;
410
0
  }
411
412
109k
  if (!cpl1 || !cpl2) {
413
0
    *result = NULL;
414
0
    return;
415
0
  }
416
417
109k
  if (cil_classperms_list_match_all(cpl1, cpl2)) {
418
98.6k
    cil_classperms_list_copy(result, cpl1);
419
98.6k
    return;
420
98.6k
  }
421
422
10.7k
  cil_list_init(result, CIL_LIST);
423
424
19.3k
  cil_list_for_each(curr, cpl1) {
425
19.3k
    if (curr->flavor == CIL_CLASSPERMS) {
426
14.9k
      struct cil_classperms *cp = curr->data;
427
14.9k
      if (FLAVOR(cp->class) == CIL_CLASS) {
428
11.7k
        cil_classperms_and(result, cp, cpl2);
429
11.7k
      } else { /* MAP */
430
3.20k
        cil_classperms_map_and(result, cp, cpl2);
431
3.20k
      }
432
14.9k
    } else { /* SET */
433
4.43k
      struct cil_classperms_set *cps = curr->data;
434
4.43k
      cil_classperms_set_and(result, cps, cpl2);
435
4.43k
    }
436
19.3k
  }
437
438
10.7k
  if (cil_list_is_empty(*result)) {
439
3.15k
    cil_list_destroy(result, CIL_FALSE);
440
3.15k
  }
441
10.7k
}
442
443
/* Append cp1 and not cpl2 to result */
444
static void cil_classperms_andnot(struct cil_list **result, const struct cil_classperms *cp1, const struct cil_list *cpl2)
445
258k
{
446
258k
  struct cil_classperms *new_cp = NULL;
447
258k
  struct cil_list_item *curr;
448
449
258k
  if (!cil_classperms_match_any(cp1, cpl2)) {
450
1.66k
    cil_classperms_copy(&new_cp, cp1);
451
1.66k
    cil_list_append(*result, CIL_CLASSPERMS, new_cp);
452
1.66k
    return;
453
1.66k
  }
454
455
421k
  cil_list_for_each(curr, cp1->perms) {
456
421k
    struct cil_perm *perm = curr->data;
457
421k
    if (!cil_class_perm_match(cp1->class, perm, cpl2)) {
458
8.33k
      if (new_cp == NULL) {
459
5.09k
        cil_classperms_init(&new_cp);
460
5.09k
        new_cp->class_str = cp1->class_str;
461
5.09k
        new_cp->class = cp1->class;
462
5.09k
        cil_list_init(&new_cp->perm_strs, CIL_PERM);
463
5.09k
        cil_list_init(&new_cp->perms, CIL_PERM);
464
5.09k
        cil_list_append(*result, CIL_CLASSPERMS, new_cp);
465
5.09k
      }
466
8.33k
      cil_list_append(new_cp->perm_strs, CIL_STRING, perm->datum.fqn);
467
8.33k
      cil_list_append(new_cp->perms, CIL_DATUM, perm);
468
8.33k
    }
469
421k
  }
470
256k
}
471
472
/* Append cp1 and not cpl2 to result */
473
static void cil_classperms_map_andnot(struct cil_list **result, const struct cil_classperms *cp1, const struct cil_list *cpl2)
474
4.60k
{
475
4.60k
  struct cil_classperms *new_cp = NULL;
476
4.60k
  struct cil_list_item *p;
477
478
9.93k
  cil_list_for_each(p, cp1->perms) {
479
9.93k
    struct cil_perm *map_perm = p->data;
480
9.93k
    if (!cil_classperms_list_match_any(map_perm->classperms, cpl2)) {
481
1.94k
      if (new_cp == NULL) {
482
1.25k
        cil_classperms_init(&new_cp);
483
1.25k
        new_cp->class_str = cp1->class_str;
484
1.25k
        new_cp->class = cp1->class;
485
1.25k
        cil_list_init(&new_cp->perm_strs, CIL_PERM);
486
1.25k
        cil_list_init(&new_cp->perms, CIL_PERM);
487
1.25k
        cil_list_append(*result, CIL_CLASSPERMS, new_cp);
488
1.25k
      }
489
1.94k
      cil_list_append(new_cp->perm_strs, CIL_STRING, map_perm->datum.fqn);
490
1.94k
      cil_list_append(new_cp->perms, CIL_DATUM, map_perm);
491
7.98k
    } else {
492
7.98k
      struct cil_list *new_cpl = NULL;
493
7.98k
      cil_classperms_list_andnot(&new_cpl, map_perm->classperms, cpl2);
494
7.98k
      if (new_cpl) {
495
2.55k
        struct cil_list_item *i;
496
5.14k
        cil_list_for_each(i, new_cpl) {
497
5.14k
          cil_list_append(*result, i->flavor, i->data);
498
5.14k
        }
499
2.55k
        cil_list_destroy(&new_cpl, CIL_FALSE);
500
2.55k
      }
501
7.98k
    }
502
9.93k
  }
503
4.60k
}
504
505
/* Append cps1 and not cpl2 to result */
506
static void cil_classperms_set_andnot(struct cil_list **result, const struct cil_classperms_set *cps1, const struct cil_list *cpl2)
507
150k
{
508
150k
  struct cil_classpermission *cp = cps1->set;
509
510
150k
  if (!cil_classperms_list_match_any(cp->classperms, cpl2)) {
511
914
    struct cil_classperms_set *new_cps;
512
914
    cil_classperms_set_copy(&new_cps, cps1);
513
914
    cil_list_append(*result, CIL_CLASSPERMS_SET, new_cps);
514
149k
  } else {
515
149k
    struct cil_list *new_cpl;
516
149k
    cil_classperms_list_andnot(&new_cpl, cp->classperms, cpl2);
517
149k
    if (new_cpl) {
518
839
      struct cil_list_item *i;
519
1.59k
      cil_list_for_each(i, new_cpl) {
520
1.59k
        cil_list_append(*result, i->flavor, i->data);
521
1.59k
      }
522
839
      cil_list_destroy(&new_cpl, CIL_FALSE);
523
839
    }
524
149k
  }
525
150k
}
526
527
/* result = cpl1 and not cpl2 */
528
void cil_classperms_list_andnot(struct cil_list **result, const struct cil_list *cpl1, const struct cil_list *cpl2)
529
260k
{
530
260k
  struct cil_list_item *curr;
531
532
260k
  if (!result) {
533
0
    return;
534
0
  }
535
536
260k
  if (!cpl1) {
537
0
    *result = NULL;
538
0
    return;
539
0
  }
540
541
260k
  if (!cpl2 || !cil_classperms_list_match_any(cpl1, cpl2)) {
542
0
    cil_classperms_list_copy(result, cpl1);
543
0
    return;
544
0
  }
545
546
260k
  cil_list_init(result, CIL_LIST);
547
548
413k
  cil_list_for_each(curr, cpl1) {
549
413k
    if (curr->flavor == CIL_CLASSPERMS) {
550
263k
      struct cil_classperms *cp = curr->data;
551
263k
      if (FLAVOR(cp->class) == CIL_CLASS) {
552
258k
        cil_classperms_andnot(result, cp, cpl2);
553
258k
      } else { /* MAP */
554
4.60k
        cil_classperms_map_andnot(result, cp, cpl2);
555
4.60k
      }
556
263k
    } else { /* SET */
557
150k
      struct cil_classperms_set *cps = curr->data;
558
150k
      cil_classperms_set_andnot(result, cps, cpl2);
559
150k
    }
560
413k
  }
561
562
260k
  if (cil_list_is_empty(*result)) {
563
253k
    cil_list_destroy(result, CIL_FALSE);
564
253k
  }
565
260k
}
566
567
static int cil_datum_cardinality(const struct cil_symtab_datum *d)
568
19.5k
{
569
19.5k
  if (!d) {
570
734
    return 0;
571
734
  }
572
18.7k
  if (FLAVOR(d) != CIL_TYPEATTRIBUTE) {
573
10.0k
    return 1;
574
10.0k
  } else {
575
8.77k
    struct cil_typeattribute *a = (struct cil_typeattribute *)d;
576
8.77k
    return ebitmap_cardinality(a->types);
577
8.77k
  }
578
18.7k
}
579
580
/* result = ALL and not d2 */
581
static int cil_datum_not(ebitmap_t *result, const struct cil_symtab_datum *d, int max)
582
20.9k
{
583
20.9k
  int rc = SEPOL_OK;
584
585
20.9k
  if (FLAVOR(d) != CIL_TYPEATTRIBUTE) {
586
11.4k
    struct cil_type *t = (struct cil_type *)d;
587
11.4k
    ebitmap_t e;
588
589
11.4k
    ebitmap_init(&e);
590
11.4k
    rc = ebitmap_set_bit(&e, t->value, 1);
591
11.4k
    if (rc != SEPOL_OK) {
592
0
      ebitmap_destroy(&e);
593
0
      goto exit;
594
0
    }
595
596
11.4k
    ebitmap_init(result);
597
11.4k
    rc = ebitmap_not(result, &e, max);
598
11.4k
    if (rc != SEPOL_OK) {
599
0
      ebitmap_destroy(&e);
600
0
      ebitmap_destroy(result);
601
0
      goto exit;
602
0
    }
603
11.4k
    ebitmap_destroy(&e);
604
11.4k
  } else {
605
9.49k
    struct cil_typeattribute *a = (struct cil_typeattribute *)d;
606
607
9.49k
    ebitmap_init(result);
608
9.49k
    rc = ebitmap_not(result, a->types, max);
609
9.49k
    if (rc != SEPOL_OK) {
610
0
      ebitmap_destroy(result);
611
0
      goto exit;
612
0
    }
613
9.49k
  }
614
20.9k
exit:
615
20.9k
  return rc;
616
20.9k
}
617
618
/* result = d1 and d2 */
619
static int cil_datums_and(ebitmap_t *result, const struct cil_symtab_datum *d1, const struct cil_symtab_datum *d2)
620
109k
{
621
109k
  int rc = SEPOL_OK;
622
109k
  enum cil_flavor f1 = FLAVOR(d1);
623
109k
  enum cil_flavor f2 = FLAVOR(d2);
624
625
109k
  if (f1 != CIL_TYPEATTRIBUTE && f2 != CIL_TYPEATTRIBUTE) {
626
7.28k
    struct cil_type *t1 = (struct cil_type *)d1;
627
7.28k
    struct cil_type *t2 = (struct cil_type *)d2;
628
7.28k
    ebitmap_init(result);
629
7.28k
    if (t1->value == t2->value) {
630
0
      rc = ebitmap_set_bit(result, t1->value, 1);
631
0
      if (rc != SEPOL_OK) {
632
0
        ebitmap_destroy(result);
633
0
        goto exit;
634
0
      }
635
0
    }
636
101k
  } else if (f1 == CIL_TYPEATTRIBUTE && f2 != CIL_TYPEATTRIBUTE) {
637
11.9k
    struct cil_typeattribute *a1 = (struct cil_typeattribute *)d1;
638
11.9k
    struct cil_type *t2 = (struct cil_type *)d2;
639
11.9k
    ebitmap_init(result);
640
11.9k
    if (ebitmap_get_bit(a1->types, t2->value)) {
641
7.87k
      rc = ebitmap_set_bit(result, t2->value, 1);
642
7.87k
      if (rc != SEPOL_OK) {
643
0
        ebitmap_destroy(result);
644
0
        goto exit;
645
0
      }
646
7.87k
    }
647
89.8k
  } else if (f1 != CIL_TYPEATTRIBUTE && f2 == CIL_TYPEATTRIBUTE) {
648
27.5k
    struct cil_type *t1 = (struct cil_type *)d1;
649
27.5k
    struct cil_typeattribute *a2 = (struct cil_typeattribute *)d2;
650
27.5k
    ebitmap_init(result);
651
27.5k
    if (ebitmap_get_bit(a2->types, t1->value)) {
652
26.9k
      rc = ebitmap_set_bit(result, t1->value, 1);
653
26.9k
      if (rc != SEPOL_OK) {
654
0
        ebitmap_destroy(result);
655
0
        goto exit;
656
0
      }
657
26.9k
    }
658
62.2k
  } else {
659
    /* Both are attributes */
660
62.2k
    struct cil_typeattribute *a1 = (struct cil_typeattribute *)d1;
661
62.2k
    struct cil_typeattribute *a2 = (struct cil_typeattribute *)d2;
662
62.2k
    rc = ebitmap_and(result, a1->types, a2->types);
663
62.2k
    if (rc != SEPOL_OK) {
664
0
      ebitmap_destroy(result);
665
0
      goto exit;
666
0
    }
667
62.2k
  }
668
109k
exit:
669
109k
  return rc;
670
109k
}
671
672
/* result = d1 and not d2 */
673
static int cil_datums_andnot(ebitmap_t *result, const struct cil_symtab_datum *d1, const struct cil_symtab_datum *d2)
674
188k
{
675
188k
  int rc = SEPOL_OK;
676
188k
  enum cil_flavor f1 = FLAVOR(d1);
677
188k
  enum cil_flavor f2 = FLAVOR(d2);
678
679
188k
  if (f1 != CIL_TYPEATTRIBUTE && f2 != CIL_TYPEATTRIBUTE) {
680
6.27k
    struct cil_type *t1 = (struct cil_type *)d1;
681
6.27k
    struct cil_type *t2 = (struct cil_type *)d2;
682
6.27k
    ebitmap_init(result);
683
6.27k
    if (t1->value != t2->value) {
684
6.27k
      rc = ebitmap_set_bit(result, t1->value, 1);
685
6.27k
      if (rc != SEPOL_OK) {
686
0
        ebitmap_destroy(result);
687
0
        goto exit;
688
0
      }
689
6.27k
    }
690
181k
  } else if (f1 == CIL_TYPEATTRIBUTE && f2 != CIL_TYPEATTRIBUTE) {
691
61.3k
    struct cil_typeattribute *a1 = (struct cil_typeattribute *)d1;
692
61.3k
    struct cil_type *t2 = (struct cil_type *)d2;
693
61.3k
    rc = ebitmap_cpy(result, a1->types);
694
61.3k
    if (rc != SEPOL_OK) {
695
0
      goto exit;
696
0
    }
697
61.3k
    rc = ebitmap_set_bit(result, t2->value, 0);
698
61.3k
    if (rc != SEPOL_OK) {
699
0
      ebitmap_destroy(result);
700
0
      goto exit;
701
0
    }
702
120k
  } else if (f1 != CIL_TYPEATTRIBUTE && f2 == CIL_TYPEATTRIBUTE) {
703
28.6k
    struct cil_type *t1 = (struct cil_type *)d1;
704
28.6k
    struct cil_typeattribute *a2 = (struct cil_typeattribute *)d2;
705
28.6k
    ebitmap_init(result);
706
28.6k
    if (!ebitmap_get_bit(a2->types, t1->value)) {
707
568
      rc = ebitmap_set_bit(result, t1->value, 1);
708
568
      if (rc != SEPOL_OK) {
709
0
        ebitmap_destroy(result);
710
0
        goto exit;
711
0
      }
712
568
    }
713
91.9k
  } else {
714
    /* Both are attributes */
715
91.9k
    struct cil_typeattribute *a1 = (struct cil_typeattribute *)d1;
716
91.9k
    struct cil_typeattribute *a2 = (struct cil_typeattribute *)d2;
717
91.9k
    rc = ebitmap_andnot(result, a1->types, a2->types, a1->types->highbit);
718
91.9k
    if (rc != SEPOL_OK) {
719
0
      ebitmap_destroy(result);
720
0
      goto exit;
721
0
    }
722
91.9k
  }
723
188k
exit:
724
188k
  return rc;
725
188k
}
726
727
static size_t num_digits(unsigned n)
728
15.9k
{
729
15.9k
  size_t num = 1;
730
51.7k
  while (n >= 10) {
731
35.7k
    n /= 10;
732
35.7k
    num++;
733
35.7k
  }
734
15.9k
  return num;
735
15.9k
}
736
737
static char *cil_create_new_attribute_name(unsigned num)
738
15.9k
{
739
15.9k
  char *s1 = NULL;
740
15.9k
  char *s2 = NULL;
741
15.9k
  size_t len_num = num_digits(num);
742
15.9k
  size_t len = strlen(CIL_DENY_ATTR_PREFIX) + 1 + len_num + 1;
743
15.9k
  int rc;
744
745
15.9k
  if (len >= CIL_MAX_NAME_LENGTH) {
746
0
    cil_log(CIL_ERR, "Name length greater than max name length of %d",
747
0
        CIL_MAX_NAME_LENGTH);
748
0
    goto exit;
749
0
  }
750
751
15.9k
  s1 = cil_malloc(len);
752
15.9k
  rc = snprintf(s1, len, "%s_%u", CIL_DENY_ATTR_PREFIX, num);
753
15.9k
  if (rc < 0 || (size_t)rc >= len) {
754
0
    cil_log(CIL_ERR, "Error creating new attribute name");
755
0
    free(s1);
756
0
    goto exit;
757
0
  }
758
759
15.9k
  s2 = cil_strpool_add(s1);
760
15.9k
  free(s1);
761
762
15.9k
exit:
763
15.9k
  return s2;
764
15.9k
}
765
766
static struct cil_list *cil_create_and_expr_list(enum cil_flavor f1, void *v1, enum cil_flavor f2, void *v2)
767
218k
{
768
218k
  struct cil_list *expr;
769
770
218k
  cil_list_init(&expr, CIL_TYPE);
771
218k
  cil_list_append(expr, CIL_OP, (void *)CIL_AND);
772
218k
  cil_list_append(expr, f1, v1);
773
218k
  cil_list_append(expr, f2, v2);
774
775
218k
  return expr;
776
218k
}
777
778
static struct cil_list *cil_create_andnot_expr_list(enum cil_flavor f1, void *v1, enum cil_flavor f2, void *v2)
779
418k
{
780
418k
  struct cil_list *expr, *sub_expr;
781
782
418k
  cil_list_init(&expr, CIL_TYPE);
783
418k
  cil_list_append(expr, CIL_OP, (void *)CIL_AND);
784
418k
  cil_list_append(expr, f1, v1);
785
418k
  cil_list_init(&sub_expr, CIL_TYPE);
786
418k
  cil_list_append(sub_expr, CIL_OP, (void *)CIL_NOT);
787
418k
  cil_list_append(sub_expr, f2, v2);
788
418k
  cil_list_append(expr, CIL_LIST, sub_expr);
789
790
418k
  return expr;
791
418k
}
792
793
static struct cil_tree_node *cil_create_and_insert_node(struct cil_tree_node *prev, enum cil_flavor flavor, void *data)
794
169k
{
795
169k
  struct cil_tree_node *new;
796
797
169k
  cil_tree_node_init(&new);
798
169k
  new->parent = prev->parent;
799
169k
  new->line = prev->line;
800
169k
  new->hll_offset = prev->hll_offset;
801
169k
  new->flavor = flavor;
802
169k
  new->data = data;
803
169k
  new->next = prev->next;
804
169k
  prev->next = new;
805
806
169k
  return new;
807
169k
}
808
809
static int cil_create_and_insert_attribute_and_set(struct cil_db *db, struct cil_tree_node *prev, struct cil_list *str_expr, struct cil_list *datum_expr, ebitmap_t *types, struct cil_symtab_datum **d)
810
15.9k
{
811
15.9k
  struct cil_tree_node *attr_node = NULL;
812
15.9k
  char *name;
813
15.9k
  struct cil_typeattribute *attr = NULL;
814
15.9k
  struct cil_tree_node *attrset_node = NULL;
815
15.9k
  struct cil_typeattributeset *attrset = NULL;
816
15.9k
  symtab_t *symtab = NULL;
817
15.9k
  int rc = SEPOL_ERR;
818
819
15.9k
  name = cil_create_new_attribute_name(db->num_types_and_attrs);
820
15.9k
  if (!name) {
821
0
    goto exit;
822
0
  }
823
824
15.9k
  cil_typeattributeset_init(&attrset);
825
15.9k
  attrset->attr_str = name;
826
15.9k
  attrset->str_expr = str_expr;
827
15.9k
  attrset->datum_expr = datum_expr;
828
829
15.9k
  cil_typeattribute_init(&attr);
830
15.9k
  cil_list_init(&attr->expr_list, CIL_TYPE);
831
15.9k
  cil_list_append(attr->expr_list, CIL_LIST, datum_expr);
832
15.9k
  attr->types = types;
833
15.9k
  attr->used = CIL_ATTR_AVRULE;
834
15.9k
  attr->keep = (ebitmap_cardinality(types) < db->attrs_expand_size) ? CIL_FALSE : CIL_TRUE;
835
836
15.9k
  attr_node = cil_create_and_insert_node(prev, CIL_TYPEATTRIBUTE, attr);
837
15.9k
  attrset_node = cil_create_and_insert_node(attr_node, CIL_TYPEATTRIBUTESET, attrset);
838
839
15.9k
  rc = cil_get_symtab(prev->parent, &symtab, CIL_SYM_TYPES);
840
15.9k
  if (rc != SEPOL_OK) {
841
0
    goto exit;
842
0
  }
843
844
15.9k
  rc = cil_symtab_insert(symtab, name, &attr->datum, attr_node);
845
15.9k
  if (rc != SEPOL_OK) {
846
0
    goto exit;
847
0
  }
848
849
15.9k
  db->num_types_and_attrs++;
850
851
15.9k
  *d = &attr->datum;
852
853
15.9k
  return SEPOL_OK;
854
855
0
exit:
856
0
  if (attr_node) {
857
0
    cil_destroy_typeattribute(attr_node->data); // This will not destroy datum_expr
858
0
    free(attr_node);
859
0
  }
860
0
  if (attrset_node) {
861
0
    prev->next = attrset_node->next;
862
0
    free(attrset_node);
863
0
  }
864
0
  return rc;
865
15.9k
}
866
867
struct attr_symtab_map_data {
868
  struct cil_symtab_datum *d;
869
  ebitmap_t *types;
870
};
871
872
static int cil_check_attribute_in_symtab(__attribute__((unused))hashtab_key_t k, hashtab_datum_t d, void *args)
873
16.8M
{
874
16.8M
  struct attr_symtab_map_data *data = args;
875
876
16.8M
  if (FLAVOR(d) == CIL_TYPEATTRIBUTE) {
877
13.1M
    struct cil_typeattribute *attr = (struct cil_typeattribute *)d;
878
13.1M
    if (ebitmap_cmp(data->types, attr->types)) {
879
170k
      data->d = d;
880
170k
    }
881
13.1M
  }
882
16.8M
  return SEPOL_OK;
883
16.8M
}
884
885
static struct cil_symtab_datum *cil_check_for_previously_defined_attribute(struct cil_db *db, ebitmap_t *types, struct cil_symtab_datum *d)
886
184k
{
887
184k
  symtab_t *local_symtab, *root_symtab;
888
184k
  struct attr_symtab_map_data data;
889
184k
  int rc;
890
891
184k
  data.d = NULL;
892
184k
  data.types = types;
893
894
184k
  local_symtab = d->symtab;
895
184k
  root_symtab = &((struct cil_root *)db->ast->root->data)->symtab[CIL_SYM_TYPES];
896
897
184k
  if (local_symtab != root_symtab) {
898
66.5k
    rc = cil_symtab_map(local_symtab, cil_check_attribute_in_symtab, &data);
899
66.5k
    if (rc != SEPOL_OK) {
900
0
      return NULL;
901
0
    }
902
66.5k
  }
903
904
184k
  if (!data.d) {
905
130k
    rc = cil_symtab_map(root_symtab, cil_check_attribute_in_symtab, &data);
906
130k
    if (rc != SEPOL_OK) {
907
0
      return NULL;
908
0
    }
909
130k
  }
910
911
184k
  return data.d;
912
184k
}
913
914
static int cil_create_attribute_all_and_not_d(struct cil_db *db, struct cil_symtab_datum *d, struct cil_symtab_datum **d3)
915
20.9k
{
916
20.9k
  struct cil_list *str_expr;
917
20.9k
  struct cil_list *datum_expr;
918
20.9k
  ebitmap_t *types;
919
20.9k
  int rc;
920
921
20.9k
  *d3 = NULL;
922
923
20.9k
  if (!d) {
924
0
    return SEPOL_ERR;
925
0
  }
926
927
20.9k
  str_expr = cil_create_andnot_expr_list(CIL_OP, (void *)CIL_ALL, CIL_STRING, d->fqn);
928
20.9k
  datum_expr = cil_create_andnot_expr_list(CIL_OP, (void *)CIL_ALL, CIL_DATUM, d);
929
930
20.9k
  types = cil_malloc(sizeof(*types));
931
20.9k
  rc = cil_datum_not(types, d, db->num_types);
932
20.9k
  if (rc != SEPOL_OK) {
933
0
    goto exit;
934
0
  }
935
936
20.9k
  if (ebitmap_is_empty(types)) {
937
513
    rc = SEPOL_OK;
938
513
    goto exit;
939
513
  }
940
941
20.4k
  if (ebitmap_cardinality(types) == 1) {
942
195
    unsigned i = ebitmap_highest_set_bit(types);
943
195
    *d3 = DATUM(db->val_to_type[i]);
944
195
    ebitmap_destroy(types);
945
195
    rc = SEPOL_OK;
946
195
    goto exit;
947
195
  }
948
949
20.2k
  *d3 = cil_check_for_previously_defined_attribute(db, types, d);
950
20.2k
  if (*d3) {
951
18.7k
    ebitmap_destroy(types);
952
18.7k
    rc = SEPOL_OK;
953
18.7k
    goto exit;
954
18.7k
  }
955
956
1.54k
  rc = cil_create_and_insert_attribute_and_set(db, NODE(d), str_expr, datum_expr, types, d3);
957
1.54k
  if (rc != SEPOL_OK) {
958
0
    goto exit;
959
0
  }
960
961
1.54k
  return SEPOL_OK;
962
963
19.4k
exit:
964
19.4k
  cil_list_destroy(&str_expr, CIL_FALSE);
965
19.4k
  cil_list_destroy(&datum_expr, CIL_FALSE);
966
19.4k
  free(types);
967
19.4k
  return rc;
968
1.54k
}
969
970
static int cil_create_attribute_d1_and_not_d2(struct cil_db *db, struct cil_symtab_datum *d1, struct cil_symtab_datum *d2, struct cil_symtab_datum **d3)
971
215k
{
972
215k
  struct cil_list *str_expr;
973
215k
  struct cil_list *datum_expr;
974
215k
  ebitmap_t *types;
975
215k
  int rc;
976
977
215k
  if (!d2) {
978
0
    *d3 = d1;
979
0
    return SEPOL_OK;
980
0
  }
981
982
215k
  *d3 = NULL;
983
984
215k
  if (!d1 || d1 == d2) {
985
27.4k
    return SEPOL_OK;
986
27.4k
  }
987
988
188k
  str_expr = cil_create_andnot_expr_list(CIL_STRING, d1->fqn, CIL_STRING, d2->fqn);
989
188k
  datum_expr = cil_create_andnot_expr_list(CIL_DATUM, d1, CIL_DATUM, d2);
990
991
188k
  types = cil_malloc(sizeof(*types));
992
188k
  rc = cil_datums_andnot(types, d1, d2);
993
188k
  if (rc != SEPOL_OK) {
994
0
    goto exit;
995
0
  }
996
188k
  if (ebitmap_is_empty(types)) {
997
62.9k
    rc = SEPOL_OK;
998
62.9k
    goto exit;
999
62.9k
  }
1000
1001
125k
  if (ebitmap_cardinality(types) == 1) {
1002
14.4k
    unsigned i = ebitmap_highest_set_bit(types);
1003
14.4k
    *d3 = DATUM(db->val_to_type[i]);
1004
14.4k
    ebitmap_destroy(types);
1005
14.4k
    rc = SEPOL_OK;
1006
14.4k
    goto exit;
1007
14.4k
  }
1008
1009
110k
  *d3 = cil_check_for_previously_defined_attribute(db, types, d1);
1010
110k
  if (*d3) {
1011
98.4k
    ebitmap_destroy(types);
1012
98.4k
    rc = SEPOL_OK;
1013
98.4k
    goto exit;
1014
98.4k
  }
1015
1016
12.3k
  rc = cil_create_and_insert_attribute_and_set(db, NODE(d1), str_expr, datum_expr, types, d3);
1017
12.3k
  if (rc != SEPOL_OK) {
1018
0
    goto exit;
1019
0
  }
1020
1021
12.3k
  return SEPOL_OK;
1022
1023
175k
exit:
1024
175k
  cil_list_destroy(&str_expr, CIL_FALSE);
1025
175k
  cil_list_destroy(&datum_expr, CIL_FALSE);
1026
175k
  free(types);
1027
175k
  return rc;
1028
12.3k
}
1029
1030
static int cil_create_attribute_d1_and_d2(struct cil_db *db, struct cil_symtab_datum *d1, struct cil_symtab_datum *d2, struct cil_symtab_datum **d3)
1031
122k
{
1032
122k
  struct cil_list *str_expr;
1033
122k
  struct cil_list *datum_expr;
1034
122k
  ebitmap_t *types;
1035
122k
  int rc;
1036
1037
122k
  if (d1 == d2) {
1038
13.5k
    *d3 = d1;
1039
13.5k
    return SEPOL_OK;
1040
13.5k
  }
1041
1042
109k
  *d3 = NULL;
1043
1044
109k
  if (!d1 || !d2) {
1045
0
    return SEPOL_OK;
1046
0
  }
1047
1048
109k
  str_expr = cil_create_and_expr_list(CIL_STRING, d1->fqn, CIL_STRING, d2->fqn);
1049
109k
  datum_expr = cil_create_and_expr_list(CIL_DATUM, d1, CIL_DATUM, d2);
1050
1051
109k
  types = cil_malloc(sizeof(*types));
1052
109k
  rc = cil_datums_and(types, d1, d2);
1053
109k
  if (rc != SEPOL_OK) {
1054
0
    goto exit;
1055
0
  }
1056
109k
  if (ebitmap_is_empty(types)) {
1057
13.0k
    rc = SEPOL_OK;
1058
13.0k
    goto exit;
1059
13.0k
  }
1060
1061
95.9k
  if (ebitmap_cardinality(types) == 1) {
1062
42.5k
    unsigned i = ebitmap_highest_set_bit(types);
1063
42.5k
    *d3 = DATUM(db->val_to_type[i]);
1064
42.5k
    ebitmap_destroy(types);
1065
42.5k
    rc = SEPOL_OK;
1066
42.5k
    goto exit;
1067
42.5k
  }
1068
1069
53.3k
  *d3 = cil_check_for_previously_defined_attribute(db, types, d1);
1070
53.3k
  if (*d3) {
1071
51.2k
    ebitmap_destroy(types);
1072
51.2k
    rc = SEPOL_OK;
1073
51.2k
    goto exit;
1074
51.2k
  }
1075
1076
2.07k
  rc = cil_create_and_insert_attribute_and_set(db, NODE(d1), str_expr, datum_expr, types, d3);
1077
2.07k
  if (rc != SEPOL_OK) {
1078
0
    goto exit;
1079
0
  }
1080
1081
2.07k
  return SEPOL_OK;
1082
1083
106k
exit:
1084
106k
  cil_list_destroy(&str_expr, CIL_FALSE);
1085
106k
  cil_list_destroy(&datum_expr, CIL_FALSE);
1086
106k
  free(types);
1087
106k
  return rc;
1088
2.07k
}
1089
1090
static struct cil_avrule *cil_create_avrule(struct cil_symtab_datum *src, struct cil_symtab_datum *tgt, struct cil_list *classperms)
1091
137k
{
1092
137k
  struct cil_avrule *new;
1093
1094
137k
  cil_avrule_init(&new);
1095
137k
  new->is_extended = CIL_FALSE;
1096
137k
  new->rule_kind = CIL_AVRULE_ALLOWED;
1097
137k
  new->src_str = src->name;
1098
137k
  new->src = src;
1099
137k
  new->tgt_str = tgt->name;
1100
137k
  new->tgt = tgt;
1101
137k
  new->perms.classperms = classperms;
1102
1103
137k
  return new;
1104
137k
}
1105
1106
static struct cil_tree_node *cil_create_and_add_avrule(struct cil_tree_node *curr, struct cil_symtab_datum *src, struct cil_symtab_datum *tgt, struct cil_list *classperms)
1107
246k
{
1108
246k
  struct cil_avrule *new_avrule;
1109
246k
  struct cil_list *new_cp_list;
1110
1111
246k
  if (!src || !tgt) {
1112
109k
    return curr;
1113
109k
  }
1114
1115
137k
  cil_classperms_list_copy(&new_cp_list, classperms);
1116
137k
  new_avrule = cil_create_avrule(src, tgt, new_cp_list);
1117
137k
  return cil_create_and_insert_node(curr, CIL_AVRULE, new_avrule);
1118
246k
}
1119
1120
static int cil_remove_permissions_from_special_rule(struct cil_db *db, struct cil_tree_node *curr, struct cil_symtab_datum *s1, struct cil_symtab_datum *t1, struct cil_symtab_datum *s2, struct cil_symtab_datum *t2, struct cil_list *p4, struct cil_symtab_datum *s3, struct cil_symtab_datum *s4)
1121
33.6k
{
1122
33.6k
  int rc;
1123
1124
33.6k
  if (t1 == DATUM(db->notselftype)) {
1125
20.9k
    if (t2 == DATUM(db->othertype)) {
1126
7.91k
      struct cil_symtab_datum *t;
1127
7.91k
      rc = cil_create_attribute_all_and_not_d(db, s2, &t);
1128
7.91k
      if (rc != SEPOL_OK) {
1129
0
        goto exit;
1130
0
      }
1131
7.91k
      curr = cil_create_and_add_avrule(curr, s4, t, p4);
1132
13.0k
    } else {
1133
13.0k
      struct cil_symtab_datum *s5, *s6, *ta, *tb;
1134
13.0k
      rc = cil_create_attribute_d1_and_not_d2(db, s4, t2, &s5);
1135
13.0k
      if (rc != SEPOL_OK) {
1136
0
        goto exit;
1137
0
      }
1138
13.0k
      rc = cil_create_attribute_d1_and_d2(db, s4, t2, &s6);
1139
13.0k
      if (rc != SEPOL_OK) {
1140
0
        goto exit;
1141
0
      }
1142
13.0k
      rc = cil_create_attribute_all_and_not_d(db, t2, &ta);
1143
13.0k
      if (rc != SEPOL_OK) {
1144
0
        goto exit;
1145
0
      }
1146
13.0k
      rc = cil_create_attribute_d1_and_not_d2(db, ta, s4, &tb);
1147
13.0k
      if (rc != SEPOL_OK) {
1148
0
        goto exit;
1149
0
      }
1150
13.0k
      curr = cil_create_and_add_avrule(curr, s6, ta, p4);
1151
13.0k
      curr = cil_create_and_add_avrule(curr, s5, tb, p4);
1152
13.0k
      if (cil_datum_cardinality(s5) > 1) {
1153
4.75k
        curr = cil_create_and_add_avrule(curr, s5, DATUM(db->othertype), p4);
1154
4.75k
      }
1155
13.0k
    }
1156
20.9k
  } else if (t1 == DATUM(db->othertype)) {
1157
10.2k
    curr = cil_create_and_add_avrule(curr, s3, s4, p4);
1158
10.2k
    if (t2 == DATUM(db->notselftype)) {
1159
      /* Nothing else is needed */
1160
9.62k
    } else if (t2 == DATUM(db->othertype)) {
1161
3.66k
      curr = cil_create_and_add_avrule(curr, s4, s3, p4);
1162
5.95k
    } else {
1163
5.95k
      struct cil_symtab_datum *s5, *s6, *tc, *td;
1164
5.95k
      rc = cil_create_attribute_d1_and_not_d2(db, s4, t2, &s5);
1165
5.95k
      if (rc != SEPOL_OK) {
1166
0
        goto exit;
1167
0
      }
1168
5.95k
      rc = cil_create_attribute_d1_and_d2(db, s4, t2, &s6);
1169
5.95k
      if (rc != SEPOL_OK) {
1170
0
        goto exit;
1171
0
      }
1172
5.95k
      rc = cil_create_attribute_d1_and_not_d2(db, s1, t2, &tc);
1173
5.95k
      if (rc != SEPOL_OK) {
1174
0
        goto exit;
1175
0
      }
1176
5.95k
      rc = cil_create_attribute_d1_and_not_d2(db, s3, t2, &td);
1177
5.95k
      if (rc != SEPOL_OK) {
1178
0
        goto exit;
1179
0
      }
1180
5.95k
      curr = cil_create_and_add_avrule(curr, s6, tc, p4);
1181
5.95k
      curr = cil_create_and_add_avrule(curr, s5, td, p4);
1182
5.95k
      if (cil_datum_cardinality(s5) > 1) {
1183
3.78k
        curr = cil_create_and_add_avrule(curr, s5, DATUM(db->othertype), p4);
1184
3.78k
      }
1185
5.95k
    }
1186
10.2k
  } else {
1187
2.43k
    struct cil_symtab_datum *s8;
1188
2.43k
    rc = cil_create_attribute_d1_and_d2(db, s4, t1, &s8);
1189
2.43k
    if (rc != SEPOL_OK) {
1190
0
      goto exit;
1191
0
    }
1192
2.43k
    curr = cil_create_and_add_avrule(curr, s8, DATUM(db->selftype), p4);
1193
2.43k
    if (t2 == DATUM(db->notselftype)) {
1194
      /* Nothing else is needed */
1195
1.34k
    } else { /* t2 == DATUM(db->othertype) */
1196
1.34k
      struct cil_symtab_datum *t;
1197
1.34k
      rc = cil_create_attribute_d1_and_not_d2(db, t1, s2, &t);
1198
1.34k
      if (rc != SEPOL_OK) {
1199
0
        goto exit;
1200
0
      }
1201
1.34k
      curr = cil_create_and_add_avrule(curr, s4, t, p4);
1202
1.34k
    }
1203
2.43k
  }
1204
33.6k
  return SEPOL_OK;
1205
1206
0
exit:
1207
0
  return rc;
1208
33.6k
}
1209
1210
static int cil_remove_permissions_from_rule(struct cil_db *db, struct cil_tree_node *allow_node, const struct cil_tree_node *deny_node)
1211
102k
{
1212
102k
  struct cil_avrule *allow_rule = allow_node->data;
1213
102k
  struct cil_deny_rule *deny_rule = deny_node->data;
1214
102k
  struct cil_symtab_datum *s1 = allow_rule->src;
1215
102k
  struct cil_symtab_datum *t1 = allow_rule->tgt;
1216
102k
  struct cil_list *p1 = allow_rule->perms.classperms;
1217
102k
  struct cil_symtab_datum *s2 = deny_rule->src;
1218
102k
  struct cil_symtab_datum *t2 = deny_rule->tgt;
1219
102k
  struct cil_list *p2 = deny_rule->classperms;
1220
102k
  struct cil_list *p3 = NULL;
1221
102k
  struct cil_list *p4 = NULL;
1222
102k
  struct cil_symtab_datum *s3, *s4;
1223
102k
  struct cil_tree_node *curr = allow_node;
1224
102k
  int rc;
1225
1226
102k
  cil_classperms_list_andnot(&p3, p1, p2);
1227
102k
  if (!cil_list_is_empty(p3)) {;
1228
4.21k
    curr = cil_create_and_add_avrule(curr, s1, t1, p3);
1229
4.21k
  }
1230
102k
  cil_destroy_classperms_list(&p3);
1231
102k
  p3 = NULL;
1232
1233
102k
  cil_classperms_list_and(&p4, p1, p2);
1234
102k
  if (cil_list_is_empty(p4)) {
1235
0
    cil_tree_log(allow_node, CIL_ERR, "Allow rule did not match deny rule: No matching class and permissions");
1236
0
    cil_tree_log((struct cil_tree_node *)deny_node, CIL_ERR, "Deny rule");
1237
0
    rc = SEPOL_ERR;
1238
0
    goto exit;
1239
0
  }
1240
1241
102k
  rc = cil_create_attribute_d1_and_not_d2(db, s1, s2, &s3);
1242
102k
  if (rc != SEPOL_OK) {
1243
0
    goto exit;
1244
0
  }
1245
102k
  curr = cil_create_and_add_avrule(curr, s3, t1, p4);
1246
1247
102k
  if ((t1 == DATUM(db->selftype) && t2 == DATUM(db->selftype)) ||
1248
101k
    (t1 == DATUM(db->notselftype) && t2 == DATUM(db->notselftype))) {
1249
    /* Nothing more needs to be done */
1250
2.26k
    rc = SEPOL_OK;
1251
2.26k
    goto exit;
1252
2.26k
  }
1253
1254
100k
  rc = cil_create_attribute_d1_and_d2(db, s1, s2, &s4);
1255
100k
  if (rc != SEPOL_OK) {
1256
0
    goto exit;
1257
0
  }
1258
1259
100k
  if (t1 == DATUM(db->notselftype) || t1 == DATUM(db->othertype) ||
1260
69.3k
    t2 == DATUM(db->notselftype) || t2 == DATUM(db->othertype)) {
1261
33.6k
    rc = cil_remove_permissions_from_special_rule(db, curr, s1, t1, s2, t2, p4, s3, s4);
1262
33.6k
    goto exit;
1263
33.6k
  }
1264
1265
66.9k
  if (t1 == DATUM(db->selftype) && t2 != DATUM(db->selftype)) {
1266
581
    struct cil_symtab_datum *s5;
1267
581
    rc = cil_create_attribute_d1_and_not_d2(db, s4, t2, &s5);
1268
581
    if (rc != SEPOL_OK) {
1269
0
      goto exit;
1270
0
    }
1271
581
    curr = cil_create_and_add_avrule(curr, s5, DATUM(db->selftype), p4);
1272
66.3k
  } else if (t1 != DATUM(db->selftype) && t2 == DATUM(db->selftype)) {
1273
505
    struct cil_symtab_datum *s7, *s8, *t8;
1274
505
    rc = cil_create_attribute_d1_and_not_d2(db, s4, t1, &s7);
1275
505
    if (rc != SEPOL_OK) {
1276
0
      goto exit;
1277
0
    }
1278
505
    rc = cil_create_attribute_d1_and_d2(db, s4, t1, &s8);
1279
505
    if (rc != SEPOL_OK) {
1280
0
      goto exit;
1281
0
    }
1282
505
    rc = cil_create_attribute_d1_and_not_d2(db, t1, s4, &t8);
1283
505
    if (rc != SEPOL_OK) {
1284
0
      goto exit;
1285
0
    }
1286
505
    curr = cil_create_and_add_avrule(curr, s7, t1, p4);
1287
505
    curr = cil_create_and_add_avrule(curr, s8, t8, p4);
1288
505
    if (cil_datum_cardinality(s8) > 1) {
1289
231
      curr = cil_create_and_add_avrule(curr, s8, DATUM(db->othertype), p4);
1290
231
    }
1291
65.8k
  } else {
1292
65.8k
    struct cil_symtab_datum *t3;
1293
65.8k
    rc = cil_create_attribute_d1_and_not_d2(db, t1, t2, &t3);
1294
65.8k
    if (rc != SEPOL_OK) {
1295
0
      goto exit;
1296
0
    }
1297
65.8k
    curr = cil_create_and_add_avrule(curr, s4, t3, p4);
1298
65.8k
  }
1299
1300
102k
exit:
1301
102k
  if (p4) {
1302
102k
    cil_destroy_classperms_list(&p4);
1303
102k
  }
1304
102k
  return rc;
1305
66.9k
}
1306
1307
static int cil_find_matching_allow_rules(struct cil_list *matching, struct cil_tree_node *start, struct cil_tree_node *deny_node)
1308
28.0k
{
1309
28.0k
  struct cil_deny_rule *deny_rule = deny_node->data;
1310
28.0k
  struct cil_avrule target;
1311
1312
28.0k
  target.rule_kind = CIL_AVRULE_ALLOWED;
1313
28.0k
  target.is_extended = CIL_FALSE;
1314
28.0k
  target.src = deny_rule->src;
1315
28.0k
  target.tgt = deny_rule->tgt;
1316
28.0k
  target.perms.classperms = deny_rule->classperms;
1317
1318
28.0k
  return cil_find_matching_avrule_in_ast(start, CIL_AVRULE, &target, matching, CIL_FALSE);
1319
28.0k
}
1320
1321
static int cil_process_deny_rule(struct cil_db *db, struct cil_tree_node *start, struct cil_tree_node *deny_node)
1322
28.0k
{
1323
28.0k
  struct cil_list *matching;
1324
28.0k
  struct cil_list_item *item;
1325
28.0k
  int rc;
1326
1327
28.0k
  cil_list_init(&matching, CIL_NODE);
1328
1329
28.0k
  rc = cil_find_matching_allow_rules(matching, start, deny_node);
1330
28.0k
  if (rc != SEPOL_OK) {
1331
0
    goto exit;
1332
0
  }
1333
1334
102k
  cil_list_for_each(item, matching) {
1335
102k
    struct cil_tree_node *allow_node = item->data;
1336
102k
    rc = cil_remove_permissions_from_rule(db, allow_node, deny_node);
1337
102k
    cil_tree_node_remove(allow_node);
1338
102k
    if (rc != SEPOL_OK) {
1339
0
      goto exit;
1340
0
    }
1341
1342
102k
  }
1343
1344
28.0k
exit:
1345
28.0k
  cil_list_destroy(&matching, CIL_FALSE);
1346
28.0k
  return rc;
1347
28.0k
}
1348
1349
static int cil_process_deny_rules(struct cil_db *db, struct cil_tree_node *start, struct cil_list *deny_rules)
1350
5.41k
{
1351
5.41k
  struct cil_list_item *item;
1352
5.41k
  int rc = SEPOL_OK;
1353
1354
28.0k
  cil_list_for_each(item, deny_rules) {
1355
28.0k
    struct cil_tree_node *deny_node = item->data;
1356
28.0k
    rc = cil_process_deny_rule(db, start, deny_node);
1357
28.0k
    if (rc != SEPOL_OK) {
1358
0
      goto exit;
1359
0
    }
1360
28.0k
    cil_tree_node_remove(deny_node);
1361
28.0k
  }
1362
1363
5.41k
exit:
1364
5.41k
  return rc;
1365
5.41k
}
1366
1367
static int __cil_find_deny_rules(struct cil_tree_node *node,  uint32_t *finished, void *extra_args)
1368
3.46M
{
1369
3.46M
  struct cil_list *deny_rules = extra_args;
1370
1371
3.46M
  if (node->flavor == CIL_BLOCK) {
1372
365k
    struct cil_block *block = node->data;
1373
365k
    if (block->is_abstract == CIL_TRUE) {
1374
520
      *finished = CIL_TREE_SKIP_HEAD;
1375
520
    }
1376
3.09M
  } else if (node->flavor == CIL_MACRO) {
1377
10.7k
    *finished = CIL_TREE_SKIP_HEAD;
1378
3.08M
  } else if (node->flavor == CIL_DENY_RULE) {
1379
28.0k
    cil_list_append(deny_rules, CIL_DENY_RULE, node);
1380
28.0k
  }
1381
3.46M
  return SEPOL_OK;
1382
3.46M
}
1383
1384
int cil_process_deny_rules_in_ast(struct cil_db *db)
1385
5.41k
{
1386
5.41k
  struct cil_tree_node *start;
1387
5.41k
  struct cil_list *deny_rules;
1388
5.41k
  int rc = SEPOL_ERR;
1389
1390
5.41k
  cil_list_init(&deny_rules, CIL_DENY_RULE);
1391
1392
5.41k
  if (!db) {
1393
0
    cil_log(CIL_ERR, "No CIL db provided to process deny rules\n");
1394
0
    goto exit;
1395
0
  }
1396
1397
5.41k
  start = db->ast->root;
1398
5.41k
  rc = cil_tree_walk(start, __cil_find_deny_rules, NULL, NULL, deny_rules);
1399
5.41k
  if (rc != SEPOL_OK) {
1400
0
    cil_log(CIL_ERR, "An error occurred while getting deny rules\n");
1401
0
    goto exit;
1402
0
  }
1403
1404
5.41k
  rc = cil_process_deny_rules(db, start, deny_rules);
1405
5.41k
  if (rc != SEPOL_OK) {
1406
0
    cil_log(CIL_ERR, "An error occurred while processing deny rules\n");
1407
0
    goto exit;
1408
0
  }
1409
1410
5.41k
exit:
1411
5.41k
  cil_list_destroy(&deny_rules, CIL_FALSE);
1412
5.41k
  return rc;
1413
5.41k
}