Coverage Report

Created: 2025-12-18 06:56

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
0
#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
0
{
131
0
  struct cil_list_item *curr;
132
133
0
  cil_list_for_each(curr, pl2) {
134
0
    struct cil_perm *p = curr->data;
135
0
    if (p == p1) {
136
0
      return CIL_TRUE;
137
0
    }
138
0
  }
139
0
  return CIL_FALSE;
140
0
}
141
142
static int cil_class_perm_match(const struct cil_class *c1, const struct cil_perm *p1, const struct cil_list *cpl2)
143
0
{
144
0
  struct cil_list_item *curr;
145
146
0
  cil_list_for_each(curr, cpl2) {
147
0
    if (curr->flavor == CIL_CLASSPERMS) {
148
0
      struct cil_classperms *cp = curr->data;
149
0
      if (FLAVOR(cp->class) == CIL_CLASS) {
150
0
        if (cp->class == c1) {
151
0
          if (cil_perm_match(p1, cp->perms)) {
152
0
            return CIL_TRUE;
153
0
          }
154
0
        }
155
0
      } else { /* MAP */
156
0
        struct cil_list_item *p;
157
0
        cil_list_for_each(p, cp->perms) {
158
0
          struct cil_perm *cmp = p->data;
159
0
          if (cil_class_perm_match(c1, p1, cmp->classperms)) {
160
0
            return CIL_TRUE;
161
0
          }
162
0
        }
163
0
      }
164
0
    } else { /* SET */
165
0
      struct cil_classperms_set *cp_set = curr->data;
166
0
      struct cil_classpermission *cp = cp_set->set;
167
0
      if (cil_class_perm_match(c1, p1, cp->classperms)) {
168
0
        return CIL_TRUE;
169
0
      }
170
0
    }
171
0
  }
172
0
  return CIL_FALSE;
173
0
}
174
175
static int cil_classperms_match_any(const struct cil_classperms *cp1, const struct cil_list *cpl2)
176
0
{
177
0
  struct cil_list_item *curr;
178
179
0
  cil_list_for_each(curr, cp1->perms) {
180
0
    struct cil_perm *perm = curr->data;
181
0
    if (cil_class_perm_match(cp1->class, perm, cpl2)) {
182
0
      return CIL_TRUE;
183
0
    }
184
0
  }
185
0
  return CIL_FALSE;
186
0
}
187
188
int cil_classperms_list_match_any(const struct cil_list *cpl1, const struct cil_list *cpl2)
189
0
{
190
0
  struct cil_list_item *curr;
191
192
0
  if (!cpl1 || !cpl2) {
193
0
    return (!cpl1 && !cpl2) ? CIL_TRUE : CIL_FALSE;
194
0
  }
195
196
0
  cil_list_for_each(curr, cpl1) {
197
0
    if (curr->flavor == CIL_CLASSPERMS) {
198
0
      struct cil_classperms *cp = curr->data;
199
0
      if (FLAVOR(cp->class) == CIL_CLASS) {
200
0
        if (cil_classperms_match_any(cp, cpl2)) {
201
0
          return CIL_TRUE;
202
0
        }
203
0
      } else { /* MAP */
204
0
        struct cil_list_item *p;
205
0
        cil_list_for_each(p, cp->perms) {
206
0
          struct cil_perm *cmp = p->data;
207
0
          if (cil_classperms_list_match_any(cmp->classperms, cpl2)) {
208
0
            return CIL_TRUE;
209
0
          }
210
0
        }
211
0
      }
212
0
    } else { /* SET */
213
0
      struct cil_classperms_set *cp_set = curr->data;
214
0
      struct cil_classpermission *cp = cp_set->set;
215
0
      if (cil_classperms_list_match_any(cp->classperms, cpl2)) {
216
0
        return CIL_TRUE;
217
0
      }
218
0
    }
219
0
  }
220
0
  return CIL_FALSE;
221
0
}
222
223
static int cil_classperms_match_all(const struct cil_classperms *cp1, const struct cil_list *cpl2)
224
0
{
225
0
  struct cil_list_item *curr;
226
227
0
  cil_list_for_each(curr, cp1->perms) {
228
0
    struct cil_perm *perm = curr->data;
229
0
    if (!cil_class_perm_match(cp1->class, perm, cpl2)) {
230
0
      return CIL_FALSE;
231
0
    }
232
0
  }
233
0
  return CIL_TRUE;
234
0
}
235
236
int cil_classperms_list_match_all(const struct cil_list *cpl1, const struct cil_list *cpl2)
237
0
{
238
0
  struct cil_list_item *curr;
239
240
0
  if (!cpl1 || !cpl2) {
241
0
    return (!cpl1 && !cpl2) ? CIL_TRUE : CIL_FALSE;
242
0
  }
243
244
0
  cil_list_for_each(curr, cpl1) {
245
0
    if (curr->flavor == CIL_CLASSPERMS) {
246
0
      struct cil_classperms *cp = curr->data;
247
0
      if (FLAVOR(cp->class) == CIL_CLASS) {
248
0
        if (!cil_classperms_match_all(cp, cpl2)) {
249
0
          return CIL_FALSE;
250
0
        }
251
0
      } else { /* MAP */
252
0
        struct cil_list_item *p;
253
0
        cil_list_for_each(p, cp->perms) {
254
0
          struct cil_perm *cmp = p->data;
255
0
          if (!cil_classperms_list_match_all(cmp->classperms, cpl2)) {
256
0
            return CIL_FALSE;
257
0
          }
258
0
        }
259
0
      }
260
0
    } else { /* SET */
261
0
      struct cil_classperms_set *cp_set = curr->data;
262
0
      struct cil_classpermission *cp = cp_set->set;
263
0
      if (!cil_classperms_list_match_all(cp->classperms, cpl2)) {
264
0
        return CIL_FALSE;
265
0
      }
266
0
    }
267
0
  }
268
0
  return CIL_TRUE;
269
0
}
270
271
static void cil_classperms_copy(struct cil_classperms **new, const struct cil_classperms *old)
272
0
{
273
0
  cil_classperms_init(new);
274
0
  (*new)->class_str = old->class_str;
275
0
  (*new)->class = old->class;
276
0
  cil_copy_list(old->perm_strs, &(*new)->perm_strs);
277
0
  cil_copy_list(old->perms, &(*new)->perms);
278
0
}
279
280
static void cil_classperms_set_copy(struct cil_classperms_set **new, const struct cil_classperms_set *old)
281
0
{
282
0
  cil_classperms_set_init(new);
283
0
  (*new)->set_str = old->set_str;
284
0
  (*new)->set = old->set;
285
0
}
286
287
void cil_classperms_list_copy(struct cil_list **new, const struct cil_list *old)
288
0
{
289
0
  struct cil_list_item *curr;
290
291
0
  if (!new) {
292
0
    return;
293
0
  }
294
295
0
  if (!old) {
296
0
    *new = NULL;
297
0
    return;
298
0
  }
299
300
0
  cil_list_init(new, CIL_LIST);
301
302
0
  cil_list_for_each(curr, old) {
303
0
    if (curr->flavor == CIL_CLASSPERMS) {
304
0
      struct cil_classperms *new_cp;
305
0
      cil_classperms_copy(&new_cp, curr->data);
306
0
      cil_list_append(*new, CIL_CLASSPERMS, new_cp);
307
0
    } else { /* SET */
308
0
      struct cil_classperms_set *new_cps;
309
0
      cil_classperms_set_copy(&new_cps, curr->data);
310
0
      cil_list_append(*new, CIL_CLASSPERMS_SET, new_cps);
311
0
    }
312
0
  }
313
314
0
  if (cil_list_is_empty(*new)) {
315
0
    cil_list_destroy(new, CIL_FALSE);
316
0
  }
317
0
}
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
0
{
322
0
  struct cil_classperms *new_cp = NULL;
323
0
  struct cil_list_item *curr;
324
325
0
  if (cil_classperms_match_all(cp1, cpl2)) {
326
0
    cil_classperms_copy(&new_cp, cp1);
327
0
    cil_list_append(*result, CIL_CLASSPERMS, new_cp);
328
0
    return;
329
0
  }
330
331
0
  cil_list_for_each(curr, cp1->perms) {
332
0
    struct cil_perm *perm = curr->data;
333
0
    if (cil_class_perm_match(cp1->class, perm, cpl2)) {
334
0
      if (new_cp == NULL) {
335
0
        cil_classperms_init(&new_cp);
336
0
        new_cp->class_str = cp1->class_str;
337
0
        new_cp->class = cp1->class;
338
0
        cil_list_init(&new_cp->perm_strs, CIL_PERM);
339
0
        cil_list_init(&new_cp->perms, CIL_PERM);
340
0
        cil_list_append(*result, CIL_CLASSPERMS, new_cp);
341
0
      }
342
0
      cil_list_append(new_cp->perm_strs, CIL_STRING, perm->datum.fqn);
343
0
      cil_list_append(new_cp->perms, CIL_DATUM, perm);
344
0
    }
345
0
  }
346
0
}
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
0
{
351
0
  struct cil_classperms *new_cp = NULL;
352
0
  struct cil_list_item *p;
353
354
0
  cil_list_for_each(p, cp1->perms) {
355
0
    struct cil_perm *map_perm = p->data;
356
0
    if (cil_classperms_list_match_all(map_perm->classperms, cpl2)) {
357
0
      if (new_cp == NULL) {
358
0
        cil_classperms_init(&new_cp);
359
0
        new_cp->class_str = cp1->class_str;
360
0
        new_cp->class = cp1->class;
361
0
        cil_list_init(&new_cp->perm_strs, CIL_PERM);
362
0
        cil_list_init(&new_cp->perms, CIL_PERM);
363
0
        cil_list_append(*result, CIL_CLASSPERMS, new_cp);
364
0
      }
365
0
      cil_list_append(new_cp->perm_strs, CIL_STRING, map_perm->datum.fqn);
366
0
      cil_list_append(new_cp->perms, CIL_DATUM, map_perm);
367
0
    } else {
368
0
      struct cil_list *new_cpl = NULL;
369
0
      cil_classperms_list_and(&new_cpl, map_perm->classperms, cpl2);
370
0
      if (new_cpl) {
371
0
        struct cil_list_item *i;
372
0
        cil_list_for_each(i, new_cpl) {
373
0
          cil_list_append(*result, i->flavor, i->data);
374
0
        }
375
0
        cil_list_destroy(&new_cpl, CIL_FALSE);
376
0
      }
377
0
    }
378
0
  }
379
0
}
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
0
{
384
0
  struct cil_classpermission *cp = cps1->set;
385
386
0
  if (cil_classperms_list_match_all(cp->classperms, cpl2)) {
387
0
    struct cil_classperms_set *new_cps;
388
0
    cil_classperms_set_copy(&new_cps, cps1);
389
0
    cil_list_append(*result, CIL_CLASSPERMS_SET, new_cps);
390
0
  } else {
391
0
    struct cil_list *new_cpl;
392
0
    cil_classperms_list_and(&new_cpl, cp->classperms, cpl2);
393
0
    if (new_cpl) {
394
0
      struct cil_list_item *i;
395
0
      cil_list_for_each(i, new_cpl) {
396
0
        cil_list_append(*result, i->flavor, i->data);
397
0
      }
398
0
      cil_list_destroy(&new_cpl, CIL_FALSE);
399
0
    }
400
0
  }
401
0
}
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
0
{
406
0
  struct cil_list_item *curr;
407
408
0
  if (!result) {
409
0
    return;
410
0
  }
411
412
0
  if (!cpl1 || !cpl2) {
413
0
    *result = NULL;
414
0
    return;
415
0
  }
416
417
0
  if (cil_classperms_list_match_all(cpl1, cpl2)) {
418
0
    cil_classperms_list_copy(result, cpl1);
419
0
    return;
420
0
  }
421
422
0
  cil_list_init(result, CIL_LIST);
423
424
0
  cil_list_for_each(curr, cpl1) {
425
0
    if (curr->flavor == CIL_CLASSPERMS) {
426
0
      struct cil_classperms *cp = curr->data;
427
0
      if (FLAVOR(cp->class) == CIL_CLASS) {
428
0
        cil_classperms_and(result, cp, cpl2);
429
0
      } else { /* MAP */
430
0
        cil_classperms_map_and(result, cp, cpl2);
431
0
      }
432
0
    } else { /* SET */
433
0
      struct cil_classperms_set *cps = curr->data;
434
0
      cil_classperms_set_and(result, cps, cpl2);
435
0
    }
436
0
  }
437
438
0
  if (cil_list_is_empty(*result)) {
439
0
    cil_list_destroy(result, CIL_FALSE);
440
0
  }
441
0
}
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
0
{
446
0
  struct cil_classperms *new_cp = NULL;
447
0
  struct cil_list_item *curr;
448
449
0
  if (!cil_classperms_match_any(cp1, cpl2)) {
450
0
    cil_classperms_copy(&new_cp, cp1);
451
0
    cil_list_append(*result, CIL_CLASSPERMS, new_cp);
452
0
    return;
453
0
  }
454
455
0
  cil_list_for_each(curr, cp1->perms) {
456
0
    struct cil_perm *perm = curr->data;
457
0
    if (!cil_class_perm_match(cp1->class, perm, cpl2)) {
458
0
      if (new_cp == NULL) {
459
0
        cil_classperms_init(&new_cp);
460
0
        new_cp->class_str = cp1->class_str;
461
0
        new_cp->class = cp1->class;
462
0
        cil_list_init(&new_cp->perm_strs, CIL_PERM);
463
0
        cil_list_init(&new_cp->perms, CIL_PERM);
464
0
        cil_list_append(*result, CIL_CLASSPERMS, new_cp);
465
0
      }
466
0
      cil_list_append(new_cp->perm_strs, CIL_STRING, perm->datum.fqn);
467
0
      cil_list_append(new_cp->perms, CIL_DATUM, perm);
468
0
    }
469
0
  }
470
0
}
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
0
{
475
0
  struct cil_classperms *new_cp = NULL;
476
0
  struct cil_list_item *p;
477
478
0
  cil_list_for_each(p, cp1->perms) {
479
0
    struct cil_perm *map_perm = p->data;
480
0
    if (!cil_classperms_list_match_any(map_perm->classperms, cpl2)) {
481
0
      if (new_cp == NULL) {
482
0
        cil_classperms_init(&new_cp);
483
0
        new_cp->class_str = cp1->class_str;
484
0
        new_cp->class = cp1->class;
485
0
        cil_list_init(&new_cp->perm_strs, CIL_PERM);
486
0
        cil_list_init(&new_cp->perms, CIL_PERM);
487
0
        cil_list_append(*result, CIL_CLASSPERMS, new_cp);
488
0
      }
489
0
      cil_list_append(new_cp->perm_strs, CIL_STRING, map_perm->datum.fqn);
490
0
      cil_list_append(new_cp->perms, CIL_DATUM, map_perm);
491
0
    } else {
492
0
      struct cil_list *new_cpl = NULL;
493
0
      cil_classperms_list_andnot(&new_cpl, map_perm->classperms, cpl2);
494
0
      if (new_cpl) {
495
0
        struct cil_list_item *i;
496
0
        cil_list_for_each(i, new_cpl) {
497
0
          cil_list_append(*result, i->flavor, i->data);
498
0
        }
499
0
        cil_list_destroy(&new_cpl, CIL_FALSE);
500
0
      }
501
0
    }
502
0
  }
503
0
}
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
0
{
508
0
  struct cil_classpermission *cp = cps1->set;
509
510
0
  if (!cil_classperms_list_match_any(cp->classperms, cpl2)) {
511
0
    struct cil_classperms_set *new_cps;
512
0
    cil_classperms_set_copy(&new_cps, cps1);
513
0
    cil_list_append(*result, CIL_CLASSPERMS_SET, new_cps);
514
0
  } else {
515
0
    struct cil_list *new_cpl;
516
0
    cil_classperms_list_andnot(&new_cpl, cp->classperms, cpl2);
517
0
    if (new_cpl) {
518
0
      struct cil_list_item *i;
519
0
      cil_list_for_each(i, new_cpl) {
520
0
        cil_list_append(*result, i->flavor, i->data);
521
0
      }
522
0
      cil_list_destroy(&new_cpl, CIL_FALSE);
523
0
    }
524
0
  }
525
0
}
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
0
{
530
0
  struct cil_list_item *curr;
531
532
0
  if (!result) {
533
0
    return;
534
0
  }
535
536
0
  if (!cpl1) {
537
0
    *result = NULL;
538
0
    return;
539
0
  }
540
541
0
  if (!cpl2 || !cil_classperms_list_match_any(cpl1, cpl2)) {
542
0
    cil_classperms_list_copy(result, cpl1);
543
0
    return;
544
0
  }
545
546
0
  cil_list_init(result, CIL_LIST);
547
548
0
  cil_list_for_each(curr, cpl1) {
549
0
    if (curr->flavor == CIL_CLASSPERMS) {
550
0
      struct cil_classperms *cp = curr->data;
551
0
      if (FLAVOR(cp->class) == CIL_CLASS) {
552
0
        cil_classperms_andnot(result, cp, cpl2);
553
0
      } else { /* MAP */
554
0
        cil_classperms_map_andnot(result, cp, cpl2);
555
0
      }
556
0
    } else { /* SET */
557
0
      struct cil_classperms_set *cps = curr->data;
558
0
      cil_classperms_set_andnot(result, cps, cpl2);
559
0
    }
560
0
  }
561
562
0
  if (cil_list_is_empty(*result)) {
563
0
    cil_list_destroy(result, CIL_FALSE);
564
0
  }
565
0
}
566
567
static int cil_datum_cardinality(const struct cil_symtab_datum *d)
568
0
{
569
0
  if (!d) {
570
0
    return 0;
571
0
  }
572
0
  if (FLAVOR(d) != CIL_TYPEATTRIBUTE) {
573
0
    return 1;
574
0
  } else {
575
0
    struct cil_typeattribute *a = (struct cil_typeattribute *)d;
576
0
    return ebitmap_cardinality(a->types);
577
0
  }
578
0
}
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
0
{
583
0
  int rc = SEPOL_OK;
584
585
0
  if (FLAVOR(d) != CIL_TYPEATTRIBUTE) {
586
0
    struct cil_type *t = (struct cil_type *)d;
587
0
    ebitmap_t e;
588
589
0
    ebitmap_init(&e);
590
0
    rc = ebitmap_set_bit(&e, t->value, 1);
591
0
    if (rc != SEPOL_OK) {
592
0
      ebitmap_destroy(&e);
593
0
      goto exit;
594
0
    }
595
596
0
    ebitmap_init(result);
597
0
    rc = ebitmap_not(result, &e, max);
598
0
    if (rc != SEPOL_OK) {
599
0
      ebitmap_destroy(&e);
600
0
      ebitmap_destroy(result);
601
0
      goto exit;
602
0
    }
603
0
    ebitmap_destroy(&e);
604
0
  } else {
605
0
    struct cil_typeattribute *a = (struct cil_typeattribute *)d;
606
607
0
    ebitmap_init(result);
608
0
    rc = ebitmap_not(result, a->types, max);
609
0
    if (rc != SEPOL_OK) {
610
0
      ebitmap_destroy(result);
611
0
      goto exit;
612
0
    }
613
0
  }
614
0
exit:
615
0
  return rc;
616
0
}
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
0
{
621
0
  int rc = SEPOL_OK;
622
0
  enum cil_flavor f1 = FLAVOR(d1);
623
0
  enum cil_flavor f2 = FLAVOR(d2);
624
625
0
  if (f1 != CIL_TYPEATTRIBUTE && f2 != CIL_TYPEATTRIBUTE) {
626
0
    struct cil_type *t1 = (struct cil_type *)d1;
627
0
    struct cil_type *t2 = (struct cil_type *)d2;
628
0
    ebitmap_init(result);
629
0
    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
0
  } else if (f1 == CIL_TYPEATTRIBUTE && f2 != CIL_TYPEATTRIBUTE) {
637
0
    struct cil_typeattribute *a1 = (struct cil_typeattribute *)d1;
638
0
    struct cil_type *t2 = (struct cil_type *)d2;
639
0
    ebitmap_init(result);
640
0
    if (ebitmap_get_bit(a1->types, t2->value)) {
641
0
      rc = ebitmap_set_bit(result, t2->value, 1);
642
0
      if (rc != SEPOL_OK) {
643
0
        ebitmap_destroy(result);
644
0
        goto exit;
645
0
      }
646
0
    }
647
0
  } else if (f1 != CIL_TYPEATTRIBUTE && f2 == CIL_TYPEATTRIBUTE) {
648
0
    struct cil_type *t1 = (struct cil_type *)d1;
649
0
    struct cil_typeattribute *a2 = (struct cil_typeattribute *)d2;
650
0
    ebitmap_init(result);
651
0
    if (ebitmap_get_bit(a2->types, t1->value)) {
652
0
      rc = ebitmap_set_bit(result, t1->value, 1);
653
0
      if (rc != SEPOL_OK) {
654
0
        ebitmap_destroy(result);
655
0
        goto exit;
656
0
      }
657
0
    }
658
0
  } else {
659
    /* Both are attributes */
660
0
    struct cil_typeattribute *a1 = (struct cil_typeattribute *)d1;
661
0
    struct cil_typeattribute *a2 = (struct cil_typeattribute *)d2;
662
0
    rc = ebitmap_and(result, a1->types, a2->types);
663
0
    if (rc != SEPOL_OK) {
664
0
      ebitmap_destroy(result);
665
0
      goto exit;
666
0
    }
667
0
  }
668
0
exit:
669
0
  return rc;
670
0
}
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
0
{
675
0
  int rc = SEPOL_OK;
676
0
  enum cil_flavor f1 = FLAVOR(d1);
677
0
  enum cil_flavor f2 = FLAVOR(d2);
678
679
0
  if (f1 != CIL_TYPEATTRIBUTE && f2 != CIL_TYPEATTRIBUTE) {
680
0
    struct cil_type *t1 = (struct cil_type *)d1;
681
0
    struct cil_type *t2 = (struct cil_type *)d2;
682
0
    ebitmap_init(result);
683
0
    if (t1->value != t2->value) {
684
0
      rc = ebitmap_set_bit(result, t1->value, 1);
685
0
      if (rc != SEPOL_OK) {
686
0
        ebitmap_destroy(result);
687
0
        goto exit;
688
0
      }
689
0
    }
690
0
  } else if (f1 == CIL_TYPEATTRIBUTE && f2 != CIL_TYPEATTRIBUTE) {
691
0
    struct cil_typeattribute *a1 = (struct cil_typeattribute *)d1;
692
0
    struct cil_type *t2 = (struct cil_type *)d2;
693
0
    rc = ebitmap_cpy(result, a1->types);
694
0
    if (rc != SEPOL_OK) {
695
0
      goto exit;
696
0
    }
697
0
    rc = ebitmap_set_bit(result, t2->value, 0);
698
0
    if (rc != SEPOL_OK) {
699
0
      ebitmap_destroy(result);
700
0
      goto exit;
701
0
    }
702
0
  } else if (f1 != CIL_TYPEATTRIBUTE && f2 == CIL_TYPEATTRIBUTE) {
703
0
    struct cil_type *t1 = (struct cil_type *)d1;
704
0
    struct cil_typeattribute *a2 = (struct cil_typeattribute *)d2;
705
0
    ebitmap_init(result);
706
0
    if (!ebitmap_get_bit(a2->types, t1->value)) {
707
0
      rc = ebitmap_set_bit(result, t1->value, 1);
708
0
      if (rc != SEPOL_OK) {
709
0
        ebitmap_destroy(result);
710
0
        goto exit;
711
0
      }
712
0
    }
713
0
  } else {
714
    /* Both are attributes */
715
0
    struct cil_typeattribute *a1 = (struct cil_typeattribute *)d1;
716
0
    struct cil_typeattribute *a2 = (struct cil_typeattribute *)d2;
717
0
    rc = ebitmap_andnot(result, a1->types, a2->types, a1->types->highbit);
718
0
    if (rc != SEPOL_OK) {
719
0
      ebitmap_destroy(result);
720
0
      goto exit;
721
0
    }
722
0
  }
723
0
exit:
724
0
  return rc;
725
0
}
726
727
static size_t num_digits(unsigned n)
728
0
{
729
0
  size_t num = 1;
730
0
  while (n >= 10) {
731
0
    n /= 10;
732
0
    num++;
733
0
  }
734
0
  return num;
735
0
}
736
737
static char *cil_create_new_attribute_name(unsigned num)
738
0
{
739
0
  char *s1 = NULL;
740
0
  char *s2 = NULL;
741
0
  size_t len_num = num_digits(num);
742
0
  size_t len = strlen(CIL_DENY_ATTR_PREFIX) + 1 + len_num + 1;
743
0
  int rc;
744
745
0
  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
0
  s1 = cil_malloc(len);
752
0
  rc = snprintf(s1, len, "%s_%u", CIL_DENY_ATTR_PREFIX, num);
753
0
  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
0
  s2 = cil_strpool_add(s1);
760
0
  free(s1);
761
762
0
exit:
763
0
  return s2;
764
0
}
765
766
static struct cil_list *cil_create_and_expr_list(enum cil_flavor f1, void *v1, enum cil_flavor f2, void *v2)
767
0
{
768
0
  struct cil_list *expr;
769
770
0
  cil_list_init(&expr, CIL_TYPE);
771
0
  cil_list_append(expr, CIL_OP, (void *)CIL_AND);
772
0
  cil_list_append(expr, f1, v1);
773
0
  cil_list_append(expr, f2, v2);
774
775
0
  return expr;
776
0
}
777
778
static struct cil_list *cil_create_andnot_expr_list(enum cil_flavor f1, void *v1, enum cil_flavor f2, void *v2)
779
0
{
780
0
  struct cil_list *expr, *sub_expr;
781
782
0
  cil_list_init(&expr, CIL_TYPE);
783
0
  cil_list_append(expr, CIL_OP, (void *)CIL_AND);
784
0
  cil_list_append(expr, f1, v1);
785
0
  cil_list_init(&sub_expr, CIL_TYPE);
786
0
  cil_list_append(sub_expr, CIL_OP, (void *)CIL_NOT);
787
0
  cil_list_append(sub_expr, f2, v2);
788
0
  cil_list_append(expr, CIL_LIST, sub_expr);
789
790
0
  return expr;
791
0
}
792
793
static struct cil_tree_node *cil_create_and_insert_node(struct cil_tree_node *prev, enum cil_flavor flavor, void *data)
794
0
{
795
0
  struct cil_tree_node *new;
796
797
0
  cil_tree_node_init(&new);
798
0
  new->parent = prev->parent;
799
0
  new->line = prev->line;
800
0
  new->hll_offset = prev->hll_offset;
801
0
  new->flavor = flavor;
802
0
  new->data = data;
803
0
  new->next = prev->next;
804
0
  prev->next = new;
805
806
0
  return new;
807
0
}
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
0
{
811
0
  struct cil_tree_node *attr_node = NULL;
812
0
  char *name;
813
0
  struct cil_typeattribute *attr = NULL;
814
0
  struct cil_tree_node *attrset_node = NULL;
815
0
  struct cil_typeattributeset *attrset = NULL;
816
0
  symtab_t *symtab = NULL;
817
0
  int rc = SEPOL_ERR;
818
819
0
  name = cil_create_new_attribute_name(db->num_types_and_attrs);
820
0
  if (!name) {
821
0
    goto exit;
822
0
  }
823
824
0
  cil_typeattributeset_init(&attrset);
825
0
  attrset->attr_str = name;
826
0
  attrset->str_expr = str_expr;
827
0
  attrset->datum_expr = datum_expr;
828
829
0
  cil_typeattribute_init(&attr);
830
0
  cil_list_init(&attr->expr_list, CIL_TYPE);
831
0
  cil_list_append(attr->expr_list, CIL_LIST, datum_expr);
832
0
  attr->types = types;
833
0
  attr->used = CIL_ATTR_AVRULE;
834
0
  attr->keep = (ebitmap_cardinality(types) < db->attrs_expand_size) ? CIL_FALSE : CIL_TRUE;
835
836
0
  attr_node = cil_create_and_insert_node(prev, CIL_TYPEATTRIBUTE, attr);
837
0
  attrset_node = cil_create_and_insert_node(attr_node, CIL_TYPEATTRIBUTESET, attrset);
838
839
0
  rc = cil_get_symtab(prev->parent, &symtab, CIL_SYM_TYPES);
840
0
  if (rc != SEPOL_OK) {
841
0
    goto exit;
842
0
  }
843
844
0
  rc = cil_symtab_insert(symtab, name, &attr->datum, attr_node);
845
0
  if (rc != SEPOL_OK) {
846
0
    goto exit;
847
0
  }
848
849
0
  db->num_types_and_attrs++;
850
851
0
  *d = &attr->datum;
852
853
0
  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
0
}
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
0
{
874
0
  struct attr_symtab_map_data *data = args;
875
876
0
  if (FLAVOR(d) == CIL_TYPEATTRIBUTE) {
877
0
    struct cil_typeattribute *attr = (struct cil_typeattribute *)d;
878
0
    if (ebitmap_cmp(data->types, attr->types)) {
879
0
      data->d = d;
880
0
    }
881
0
  }
882
0
  return SEPOL_OK;
883
0
}
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
0
{
887
0
  symtab_t *local_symtab, *root_symtab;
888
0
  struct attr_symtab_map_data data;
889
0
  int rc;
890
891
0
  data.d = NULL;
892
0
  data.types = types;
893
894
0
  local_symtab = d->symtab;
895
0
  root_symtab = &((struct cil_root *)db->ast->root->data)->symtab[CIL_SYM_TYPES];
896
897
0
  if (local_symtab != root_symtab) {
898
0
    rc = cil_symtab_map(local_symtab, cil_check_attribute_in_symtab, &data);
899
0
    if (rc != SEPOL_OK) {
900
0
      return NULL;
901
0
    }
902
0
  }
903
904
0
  if (!data.d) {
905
0
    rc = cil_symtab_map(root_symtab, cil_check_attribute_in_symtab, &data);
906
0
    if (rc != SEPOL_OK) {
907
0
      return NULL;
908
0
    }
909
0
  }
910
911
0
  return data.d;
912
0
}
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
0
{
916
0
  struct cil_list *str_expr;
917
0
  struct cil_list *datum_expr;
918
0
  ebitmap_t *types;
919
0
  int rc;
920
921
0
  *d3 = NULL;
922
923
0
  if (!d) {
924
0
    return SEPOL_ERR;
925
0
  }
926
927
0
  str_expr = cil_create_andnot_expr_list(CIL_OP, (void *)CIL_ALL, CIL_STRING, d->fqn);
928
0
  datum_expr = cil_create_andnot_expr_list(CIL_OP, (void *)CIL_ALL, CIL_DATUM, d);
929
930
0
  types = cil_malloc(sizeof(*types));
931
0
  rc = cil_datum_not(types, d, db->num_types);
932
0
  if (rc != SEPOL_OK) {
933
0
    goto exit;
934
0
  }
935
936
0
  if (ebitmap_is_empty(types)) {
937
0
    rc = SEPOL_OK;
938
0
    goto exit;
939
0
  }
940
941
0
  if (ebitmap_cardinality(types) == 1) {
942
0
    unsigned i = ebitmap_highest_set_bit(types);
943
0
    *d3 = DATUM(db->val_to_type[i]);
944
0
    ebitmap_destroy(types);
945
0
    rc = SEPOL_OK;
946
0
    goto exit;
947
0
  }
948
949
0
  *d3 = cil_check_for_previously_defined_attribute(db, types, d);
950
0
  if (*d3) {
951
0
    ebitmap_destroy(types);
952
0
    rc = SEPOL_OK;
953
0
    goto exit;
954
0
  }
955
956
0
  rc = cil_create_and_insert_attribute_and_set(db, NODE(d), str_expr, datum_expr, types, d3);
957
0
  if (rc != SEPOL_OK) {
958
0
    goto exit;
959
0
  }
960
961
0
  return SEPOL_OK;
962
963
0
exit:
964
0
  cil_list_destroy(&str_expr, CIL_FALSE);
965
0
  cil_list_destroy(&datum_expr, CIL_FALSE);
966
0
  free(types);
967
0
  return rc;
968
0
}
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
0
{
972
0
  struct cil_list *str_expr;
973
0
  struct cil_list *datum_expr;
974
0
  ebitmap_t *types;
975
0
  int rc;
976
977
0
  if (!d2) {
978
0
    *d3 = d1;
979
0
    return SEPOL_OK;
980
0
  }
981
982
0
  *d3 = NULL;
983
984
0
  if (!d1 || d1 == d2) {
985
0
    return SEPOL_OK;
986
0
  }
987
988
0
  str_expr = cil_create_andnot_expr_list(CIL_STRING, d1->fqn, CIL_STRING, d2->fqn);
989
0
  datum_expr = cil_create_andnot_expr_list(CIL_DATUM, d1, CIL_DATUM, d2);
990
991
0
  types = cil_malloc(sizeof(*types));
992
0
  rc = cil_datums_andnot(types, d1, d2);
993
0
  if (rc != SEPOL_OK) {
994
0
    goto exit;
995
0
  }
996
0
  if (ebitmap_is_empty(types)) {
997
0
    rc = SEPOL_OK;
998
0
    goto exit;
999
0
  }
1000
1001
0
  if (ebitmap_cardinality(types) == 1) {
1002
0
    unsigned i = ebitmap_highest_set_bit(types);
1003
0
    *d3 = DATUM(db->val_to_type[i]);
1004
0
    ebitmap_destroy(types);
1005
0
    rc = SEPOL_OK;
1006
0
    goto exit;
1007
0
  }
1008
1009
0
  *d3 = cil_check_for_previously_defined_attribute(db, types, d1);
1010
0
  if (*d3) {
1011
0
    ebitmap_destroy(types);
1012
0
    rc = SEPOL_OK;
1013
0
    goto exit;
1014
0
  }
1015
1016
0
  rc = cil_create_and_insert_attribute_and_set(db, NODE(d1), str_expr, datum_expr, types, d3);
1017
0
  if (rc != SEPOL_OK) {
1018
0
    goto exit;
1019
0
  }
1020
1021
0
  return SEPOL_OK;
1022
1023
0
exit:
1024
0
  cil_list_destroy(&str_expr, CIL_FALSE);
1025
0
  cil_list_destroy(&datum_expr, CIL_FALSE);
1026
0
  free(types);
1027
0
  return rc;
1028
0
}
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
0
{
1032
0
  struct cil_list *str_expr;
1033
0
  struct cil_list *datum_expr;
1034
0
  ebitmap_t *types;
1035
0
  int rc;
1036
1037
0
  if (d1 == d2) {
1038
0
    *d3 = d1;
1039
0
    return SEPOL_OK;
1040
0
  }
1041
1042
0
  *d3 = NULL;
1043
1044
0
  if (!d1 || !d2) {
1045
0
    return SEPOL_OK;
1046
0
  }
1047
1048
0
  str_expr = cil_create_and_expr_list(CIL_STRING, d1->fqn, CIL_STRING, d2->fqn);
1049
0
  datum_expr = cil_create_and_expr_list(CIL_DATUM, d1, CIL_DATUM, d2);
1050
1051
0
  types = cil_malloc(sizeof(*types));
1052
0
  rc = cil_datums_and(types, d1, d2);
1053
0
  if (rc != SEPOL_OK) {
1054
0
    goto exit;
1055
0
  }
1056
0
  if (ebitmap_is_empty(types)) {
1057
0
    rc = SEPOL_OK;
1058
0
    goto exit;
1059
0
  }
1060
1061
0
  if (ebitmap_cardinality(types) == 1) {
1062
0
    unsigned i = ebitmap_highest_set_bit(types);
1063
0
    *d3 = DATUM(db->val_to_type[i]);
1064
0
    ebitmap_destroy(types);
1065
0
    rc = SEPOL_OK;
1066
0
    goto exit;
1067
0
  }
1068
1069
0
  *d3 = cil_check_for_previously_defined_attribute(db, types, d1);
1070
0
  if (*d3) {
1071
0
    ebitmap_destroy(types);
1072
0
    rc = SEPOL_OK;
1073
0
    goto exit;
1074
0
  }
1075
1076
0
  rc = cil_create_and_insert_attribute_and_set(db, NODE(d1), str_expr, datum_expr, types, d3);
1077
0
  if (rc != SEPOL_OK) {
1078
0
    goto exit;
1079
0
  }
1080
1081
0
  return SEPOL_OK;
1082
1083
0
exit:
1084
0
  cil_list_destroy(&str_expr, CIL_FALSE);
1085
0
  cil_list_destroy(&datum_expr, CIL_FALSE);
1086
0
  free(types);
1087
0
  return rc;
1088
0
}
1089
1090
static struct cil_avrule *cil_create_avrule(struct cil_symtab_datum *src, struct cil_symtab_datum *tgt, struct cil_list *classperms)
1091
0
{
1092
0
  struct cil_avrule *new;
1093
1094
0
  cil_avrule_init(&new);
1095
0
  new->is_extended = CIL_FALSE;
1096
0
  new->rule_kind = CIL_AVRULE_ALLOWED;
1097
0
  new->src_str = src->name;
1098
0
  new->src = src;
1099
0
  new->tgt_str = tgt->name;
1100
0
  new->tgt = tgt;
1101
0
  new->perms.classperms = classperms;
1102
1103
0
  return new;
1104
0
}
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
0
{
1108
0
  struct cil_avrule *new_avrule;
1109
0
  struct cil_list *new_cp_list;
1110
1111
0
  if (!src || !tgt) {
1112
0
    return curr;
1113
0
  }
1114
1115
0
  cil_classperms_list_copy(&new_cp_list, classperms);
1116
0
  new_avrule = cil_create_avrule(src, tgt, new_cp_list);
1117
0
  return cil_create_and_insert_node(curr, CIL_AVRULE, new_avrule);
1118
0
}
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
0
{
1122
0
  int rc;
1123
1124
0
  if (t1 == DATUM(db->notselftype)) {
1125
0
    if (t2 == DATUM(db->othertype)) {
1126
0
      struct cil_symtab_datum *t;
1127
0
      rc = cil_create_attribute_all_and_not_d(db, s2, &t);
1128
0
      if (rc != SEPOL_OK) {
1129
0
        goto exit;
1130
0
      }
1131
0
      curr = cil_create_and_add_avrule(curr, s4, t, p4);
1132
0
    } else {
1133
0
      struct cil_symtab_datum *s5, *s6, *ta, *tb;
1134
0
      rc = cil_create_attribute_d1_and_not_d2(db, s4, t2, &s5);
1135
0
      if (rc != SEPOL_OK) {
1136
0
        goto exit;
1137
0
      }
1138
0
      rc = cil_create_attribute_d1_and_d2(db, s4, t2, &s6);
1139
0
      if (rc != SEPOL_OK) {
1140
0
        goto exit;
1141
0
      }
1142
0
      rc = cil_create_attribute_all_and_not_d(db, t2, &ta);
1143
0
      if (rc != SEPOL_OK) {
1144
0
        goto exit;
1145
0
      }
1146
0
      rc = cil_create_attribute_d1_and_not_d2(db, ta, s4, &tb);
1147
0
      if (rc != SEPOL_OK) {
1148
0
        goto exit;
1149
0
      }
1150
0
      curr = cil_create_and_add_avrule(curr, s6, ta, p4);
1151
0
      curr = cil_create_and_add_avrule(curr, s5, tb, p4);
1152
0
      if (cil_datum_cardinality(s5) > 1) {
1153
0
        curr = cil_create_and_add_avrule(curr, s5, DATUM(db->othertype), p4);
1154
0
      }
1155
0
    }
1156
0
  } else if (t1 == DATUM(db->othertype)) {
1157
0
    curr = cil_create_and_add_avrule(curr, s3, s4, p4);
1158
0
    if (t2 == DATUM(db->notselftype)) {
1159
      /* Nothing else is needed */
1160
0
    } else if (t2 == DATUM(db->othertype)) {
1161
0
      curr = cil_create_and_add_avrule(curr, s4, s3, p4);
1162
0
    } else {
1163
0
      struct cil_symtab_datum *s5, *s6, *tc, *td;
1164
0
      rc = cil_create_attribute_d1_and_not_d2(db, s4, t2, &s5);
1165
0
      if (rc != SEPOL_OK) {
1166
0
        goto exit;
1167
0
      }
1168
0
      rc = cil_create_attribute_d1_and_d2(db, s4, t2, &s6);
1169
0
      if (rc != SEPOL_OK) {
1170
0
        goto exit;
1171
0
      }
1172
0
      rc = cil_create_attribute_d1_and_not_d2(db, s1, t2, &tc);
1173
0
      if (rc != SEPOL_OK) {
1174
0
        goto exit;
1175
0
      }
1176
0
      rc = cil_create_attribute_d1_and_not_d2(db, s3, t2, &td);
1177
0
      if (rc != SEPOL_OK) {
1178
0
        goto exit;
1179
0
      }
1180
0
      curr = cil_create_and_add_avrule(curr, s6, tc, p4);
1181
0
      curr = cil_create_and_add_avrule(curr, s5, td, p4);
1182
0
      if (cil_datum_cardinality(s5) > 1) {
1183
0
        curr = cil_create_and_add_avrule(curr, s5, DATUM(db->othertype), p4);
1184
0
      }
1185
0
    }
1186
0
  } else {
1187
0
    struct cil_symtab_datum *s8;
1188
0
    rc = cil_create_attribute_d1_and_d2(db, s4, t1, &s8);
1189
0
    if (rc != SEPOL_OK) {
1190
0
      goto exit;
1191
0
    }
1192
0
    curr = cil_create_and_add_avrule(curr, s8, DATUM(db->selftype), p4);
1193
0
    if (t2 == DATUM(db->notselftype)) {
1194
      /* Nothing else is needed */
1195
0
    } else { /* t2 == DATUM(db->othertype) */
1196
0
      struct cil_symtab_datum *t;
1197
0
      rc = cil_create_attribute_d1_and_not_d2(db, t1, s2, &t);
1198
0
      if (rc != SEPOL_OK) {
1199
0
        goto exit;
1200
0
      }
1201
0
      curr = cil_create_and_add_avrule(curr, s4, t, p4);
1202
0
    }
1203
0
  }
1204
0
  return SEPOL_OK;
1205
1206
0
exit:
1207
0
  return rc;
1208
0
}
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
0
{
1212
0
  struct cil_avrule *allow_rule = allow_node->data;
1213
0
  struct cil_deny_rule *deny_rule = deny_node->data;
1214
0
  struct cil_symtab_datum *s1 = allow_rule->src;
1215
0
  struct cil_symtab_datum *t1 = allow_rule->tgt;
1216
0
  struct cil_list *p1 = allow_rule->perms.classperms;
1217
0
  struct cil_symtab_datum *s2 = deny_rule->src;
1218
0
  struct cil_symtab_datum *t2 = deny_rule->tgt;
1219
0
  struct cil_list *p2 = deny_rule->classperms;
1220
0
  struct cil_list *p3 = NULL;
1221
0
  struct cil_list *p4 = NULL;
1222
0
  struct cil_symtab_datum *s3, *s4;
1223
0
  struct cil_tree_node *curr = allow_node;
1224
0
  int rc;
1225
1226
0
  cil_classperms_list_andnot(&p3, p1, p2);
1227
0
  if (!cil_list_is_empty(p3)) {;
1228
0
    curr = cil_create_and_add_avrule(curr, s1, t1, p3);
1229
0
  }
1230
0
  cil_destroy_classperms_list(&p3);
1231
0
  p3 = NULL;
1232
1233
0
  cil_classperms_list_and(&p4, p1, p2);
1234
0
  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
0
  rc = cil_create_attribute_d1_and_not_d2(db, s1, s2, &s3);
1242
0
  if (rc != SEPOL_OK) {
1243
0
    goto exit;
1244
0
  }
1245
0
  curr = cil_create_and_add_avrule(curr, s3, t1, p4);
1246
1247
0
  if ((t1 == DATUM(db->selftype) && t2 == DATUM(db->selftype)) ||
1248
0
    (t1 == DATUM(db->notselftype) && t2 == DATUM(db->notselftype))) {
1249
    /* Nothing more needs to be done */
1250
0
    rc = SEPOL_OK;
1251
0
    goto exit;
1252
0
  }
1253
1254
0
  rc = cil_create_attribute_d1_and_d2(db, s1, s2, &s4);
1255
0
  if (rc != SEPOL_OK) {
1256
0
    goto exit;
1257
0
  }
1258
1259
0
  if (t1 == DATUM(db->notselftype) || t1 == DATUM(db->othertype) ||
1260
0
    t2 == DATUM(db->notselftype) || t2 == DATUM(db->othertype)) {
1261
0
    rc = cil_remove_permissions_from_special_rule(db, curr, s1, t1, s2, t2, p4, s3, s4);
1262
0
    goto exit;
1263
0
  }
1264
1265
0
  if (t1 == DATUM(db->selftype) && t2 != DATUM(db->selftype)) {
1266
0
    struct cil_symtab_datum *s5;
1267
0
    rc = cil_create_attribute_d1_and_not_d2(db, s4, t2, &s5);
1268
0
    if (rc != SEPOL_OK) {
1269
0
      goto exit;
1270
0
    }
1271
0
    curr = cil_create_and_add_avrule(curr, s5, DATUM(db->selftype), p4);
1272
0
  } else if (t1 != DATUM(db->selftype) && t2 == DATUM(db->selftype)) {
1273
0
    struct cil_symtab_datum *s7, *s8, *t8;
1274
0
    rc = cil_create_attribute_d1_and_not_d2(db, s4, t1, &s7);
1275
0
    if (rc != SEPOL_OK) {
1276
0
      goto exit;
1277
0
    }
1278
0
    rc = cil_create_attribute_d1_and_d2(db, s4, t1, &s8);
1279
0
    if (rc != SEPOL_OK) {
1280
0
      goto exit;
1281
0
    }
1282
0
    rc = cil_create_attribute_d1_and_not_d2(db, t1, s4, &t8);
1283
0
    if (rc != SEPOL_OK) {
1284
0
      goto exit;
1285
0
    }
1286
0
    curr = cil_create_and_add_avrule(curr, s7, t1, p4);
1287
0
    curr = cil_create_and_add_avrule(curr, s8, t8, p4);
1288
0
    if (cil_datum_cardinality(s8) > 1) {
1289
0
      curr = cil_create_and_add_avrule(curr, s8, DATUM(db->othertype), p4);
1290
0
    }
1291
0
  } else {
1292
0
    struct cil_symtab_datum *t3;
1293
0
    rc = cil_create_attribute_d1_and_not_d2(db, t1, t2, &t3);
1294
0
    if (rc != SEPOL_OK) {
1295
0
      goto exit;
1296
0
    }
1297
0
    curr = cil_create_and_add_avrule(curr, s4, t3, p4);
1298
0
  }
1299
1300
0
exit:
1301
0
  if (p4) {
1302
0
    cil_destroy_classperms_list(&p4);
1303
0
  }
1304
0
  return rc;
1305
0
}
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
0
{
1309
0
  struct cil_deny_rule *deny_rule = deny_node->data;
1310
0
  struct cil_avrule target;
1311
1312
0
  target.rule_kind = CIL_AVRULE_ALLOWED;
1313
0
  target.is_extended = CIL_FALSE;
1314
0
  target.src = deny_rule->src;
1315
0
  target.tgt = deny_rule->tgt;
1316
0
  target.perms.classperms = deny_rule->classperms;
1317
1318
0
  return cil_find_matching_avrule_in_ast(start, CIL_AVRULE, &target, matching, CIL_FALSE);
1319
0
}
1320
1321
static int cil_process_deny_rule(struct cil_db *db, struct cil_tree_node *start, struct cil_tree_node *deny_node)
1322
0
{
1323
0
  struct cil_list *matching;
1324
0
  struct cil_list_item *item;
1325
0
  int rc;
1326
1327
0
  cil_list_init(&matching, CIL_NODE);
1328
1329
0
  rc = cil_find_matching_allow_rules(matching, start, deny_node);
1330
0
  if (rc != SEPOL_OK) {
1331
0
    goto exit;
1332
0
  }
1333
1334
0
  cil_list_for_each(item, matching) {
1335
0
    struct cil_tree_node *allow_node = item->data;
1336
0
    rc = cil_remove_permissions_from_rule(db, allow_node, deny_node);
1337
0
    cil_tree_node_remove(allow_node);
1338
0
    if (rc != SEPOL_OK) {
1339
0
      goto exit;
1340
0
    }
1341
1342
0
  }
1343
1344
0
exit:
1345
0
  cil_list_destroy(&matching, CIL_FALSE);
1346
0
  return rc;
1347
0
}
1348
1349
static int cil_process_deny_rules(struct cil_db *db, struct cil_tree_node *start, struct cil_list *deny_rules)
1350
6
{
1351
6
  struct cil_list_item *item;
1352
6
  int rc = SEPOL_OK;
1353
1354
6
  cil_list_for_each(item, deny_rules) {
1355
0
    struct cil_tree_node *deny_node = item->data;
1356
0
    rc = cil_process_deny_rule(db, start, deny_node);
1357
0
    if (rc != SEPOL_OK) {
1358
0
      goto exit;
1359
0
    }
1360
0
    cil_tree_node_remove(deny_node);
1361
0
  }
1362
1363
6
exit:
1364
6
  return rc;
1365
6
}
1366
1367
static int __cil_find_deny_rules(struct cil_tree_node *node,  uint32_t *finished, void *extra_args)
1368
36
{
1369
36
  struct cil_list *deny_rules = extra_args;
1370
1371
36
  if (node->flavor == CIL_BLOCK) {
1372
0
    struct cil_block *block = node->data;
1373
0
    if (block->is_abstract == CIL_TRUE) {
1374
0
      *finished = CIL_TREE_SKIP_HEAD;
1375
0
    }
1376
36
  } else if (node->flavor == CIL_MACRO) {
1377
0
    *finished = CIL_TREE_SKIP_HEAD;
1378
36
  } else if (node->flavor == CIL_DENY_RULE) {
1379
0
    cil_list_append(deny_rules, CIL_DENY_RULE, node);
1380
0
  }
1381
36
  return SEPOL_OK;
1382
36
}
1383
1384
int cil_process_deny_rules_in_ast(struct cil_db *db)
1385
6
{
1386
6
  struct cil_tree_node *start;
1387
6
  struct cil_list *deny_rules;
1388
6
  int rc = SEPOL_ERR;
1389
1390
6
  cil_list_init(&deny_rules, CIL_DENY_RULE);
1391
1392
6
  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
6
  start = db->ast->root;
1398
6
  rc = cil_tree_walk(start, __cil_find_deny_rules, NULL, NULL, deny_rules);
1399
6
  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
6
  rc = cil_process_deny_rules(db, start, deny_rules);
1405
6
  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
6
exit:
1411
6
  cil_list_destroy(&deny_rules, CIL_FALSE);
1412
6
  return rc;
1413
6
}