Coverage Report

Created: 2026-07-15 06:40

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/selinux/libsepol/src/assertion.c
Line
Count
Source
1
/* Authors: Joshua Brindle <jbrindle@tresys.com>
2
 *
3
 * Assertion checker for avtab entries, taken from
4
 * checkpolicy.c by Stephen Smalley <stephen.smalley.work@gmail.com>
5
 *
6
 * Copyright (C) 2005 Tresys Technology, LLC
7
 *
8
 *  This library is free software; you can redistribute it and/or
9
 *  modify it under the terms of the GNU Lesser General Public
10
 *  License as published by the Free Software Foundation; either
11
 *  version 2.1 of the License, or (at your option) any later version.
12
 *
13
 *  This library is distributed in the hope that it will be useful,
14
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16
 *  Lesser General Public License for more details.
17
 *
18
 *  You should have received a copy of the GNU Lesser General Public
19
 *  License along with this library; if not, write to the Free Software
20
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
21
 */
22
23
#include <stdbool.h>
24
#include <sepol/policydb/avtab.h>
25
#include <sepol/policydb/policydb.h>
26
#include <sepol/policydb/expand.h>
27
#include <sepol/policydb/util.h>
28
29
#include "private.h"
30
#include "debug.h"
31
32
struct avtab_match_args {
33
  sepol_handle_t *handle;
34
  policydb_t *p;
35
  const avrule_t *narule;
36
  unsigned long errors;
37
  bool conditional;
38
};
39
40
static const char *policy_name(const policydb_t *p)
41
0
{
42
0
  return p->name ?: "policy.conf";
43
0
}
44
45
static void report_failure(sepol_handle_t *handle, const policydb_t *p,
46
         const avrule_t *narule, unsigned int stype,
47
         unsigned int ttype, const class_perm_node_t *curperm,
48
         uint32_t perms)
49
0
{
50
0
  char *permstr = sepol_av_to_string(p, curperm->tclass, perms);
51
52
0
  if (narule->source_filename) {
53
0
    ERR(handle,
54
0
        "neverallow on line %lu of %s (or line %lu of %s) violated by allow %s %s:%s {%s };",
55
0
        narule->source_line, narule->source_filename, narule->line,
56
0
        policy_name(p), p->p_type_val_to_name[stype],
57
0
        p->p_type_val_to_name[ttype],
58
0
        p->p_class_val_to_name[curperm->tclass - 1],
59
0
        permstr ?: "<format-failure>");
60
0
  } else if (narule->line) {
61
0
    ERR(handle,
62
0
        "neverallow on line %lu violated by allow %s %s:%s {%s };",
63
0
        narule->line, p->p_type_val_to_name[stype],
64
0
        p->p_type_val_to_name[ttype],
65
0
        p->p_class_val_to_name[curperm->tclass - 1],
66
0
        permstr ?: "<format-failure>");
67
0
  } else {
68
0
    ERR(handle, "neverallow violated by allow %s %s:%s {%s };",
69
0
        p->p_type_val_to_name[stype], p->p_type_val_to_name[ttype],
70
0
        p->p_class_val_to_name[curperm->tclass - 1],
71
0
        permstr ?: "<format-failure>");
72
0
  }
73
74
0
  free(permstr);
75
0
}
76
77
static bool match_any_class_permissions(const class_perm_node_t *cp,
78
          uint32_t class, uint32_t data)
79
0
{
80
0
  for (; cp; cp = cp->next) {
81
0
    if ((cp->tclass == class) && (cp->data & data))
82
0
      return true;
83
0
  }
84
85
0
  return false;
86
0
}
87
88
static bool extended_permissions_and(const uint32_t *perms1,
89
             const uint32_t *perms2)
90
0
{
91
0
  size_t i;
92
0
  for (i = 0; i < EXTENDED_PERMS_LEN; i++) {
93
0
    if (perms1[i] & perms2[i])
94
0
      return true;
95
0
  }
96
97
0
  return false;
98
0
}
99
100
static bool check_extended_permissions(const av_extended_perms_t *neverallow,
101
               const avtab_extended_perms_t *allow)
102
0
{
103
0
  bool rc = false;
104
0
  if ((neverallow->specified == AVRULE_XPERMS_IOCTLFUNCTION) &&
105
0
      (allow->specified == AVTAB_XPERMS_IOCTLFUNCTION)) {
106
0
    if (neverallow->driver == allow->driver)
107
0
      rc = extended_permissions_and(neverallow->perms,
108
0
                  allow->perms);
109
0
  } else if ((neverallow->specified == AVRULE_XPERMS_IOCTLFUNCTION) &&
110
0
       (allow->specified == AVTAB_XPERMS_IOCTLDRIVER)) {
111
0
    rc = xperm_test(neverallow->driver, allow->perms);
112
0
  } else if ((neverallow->specified == AVRULE_XPERMS_IOCTLDRIVER) &&
113
0
       (allow->specified == AVTAB_XPERMS_IOCTLFUNCTION)) {
114
0
    rc = xperm_test(allow->driver, neverallow->perms);
115
0
  } else if ((neverallow->specified == AVRULE_XPERMS_IOCTLDRIVER) &&
116
0
       (allow->specified == AVTAB_XPERMS_IOCTLDRIVER)) {
117
0
    rc = extended_permissions_and(neverallow->perms, allow->perms);
118
0
  } else if ((neverallow->specified == AVRULE_XPERMS_NLMSG) &&
119
0
       (allow->specified == AVTAB_XPERMS_NLMSG)) {
120
0
    if (neverallow->driver == allow->driver)
121
0
      rc = extended_permissions_and(neverallow->perms,
122
0
                  allow->perms);
123
0
  }
124
125
0
  return rc;
126
0
}
127
128
/* Compute which allowed extended permissions violate the neverallow rule */
129
static void extended_permissions_violated(avtab_extended_perms_t *result,
130
            const av_extended_perms_t *neverallow,
131
            const avtab_extended_perms_t *allow)
132
0
{
133
0
  size_t i;
134
0
  if ((neverallow->specified == AVRULE_XPERMS_IOCTLFUNCTION) &&
135
0
      (allow->specified == AVTAB_XPERMS_IOCTLFUNCTION)) {
136
0
    result->specified = AVTAB_XPERMS_IOCTLFUNCTION;
137
0
    result->driver = allow->driver;
138
0
    for (i = 0; i < EXTENDED_PERMS_LEN; i++)
139
0
      result->perms[i] = neverallow->perms[i] &
140
0
             allow->perms[i];
141
0
  } else if ((neverallow->specified == AVRULE_XPERMS_IOCTLFUNCTION) &&
142
0
       (allow->specified == AVTAB_XPERMS_IOCTLDRIVER)) {
143
0
    result->specified = AVTAB_XPERMS_IOCTLFUNCTION;
144
0
    result->driver = neverallow->driver;
145
0
    memcpy(result->perms, neverallow->perms, sizeof(result->perms));
146
0
  } else if ((neverallow->specified == AVRULE_XPERMS_IOCTLDRIVER) &&
147
0
       (allow->specified == AVTAB_XPERMS_IOCTLFUNCTION)) {
148
0
    result->specified = AVTAB_XPERMS_IOCTLFUNCTION;
149
0
    result->driver = allow->driver;
150
0
    memcpy(result->perms, allow->perms, sizeof(result->perms));
151
0
  } else if ((neverallow->specified == AVRULE_XPERMS_IOCTLDRIVER) &&
152
0
       (allow->specified == AVTAB_XPERMS_IOCTLDRIVER)) {
153
0
    result->specified = AVTAB_XPERMS_IOCTLDRIVER;
154
0
    for (i = 0; i < EXTENDED_PERMS_LEN; i++)
155
0
      result->perms[i] = neverallow->perms[i] &
156
0
             allow->perms[i];
157
0
  } else if ((neverallow->specified == AVRULE_XPERMS_NLMSG) &&
158
0
       (allow->specified == AVTAB_XPERMS_NLMSG)) {
159
0
    result->specified = AVTAB_XPERMS_NLMSG;
160
0
    result->driver = allow->driver;
161
0
    for (i = 0; i < EXTENDED_PERMS_LEN; i++)
162
0
      result->perms[i] = neverallow->perms[i] &
163
0
             allow->perms[i];
164
0
  }
165
0
}
166
167
static bool match_node_key(const struct avtab_node *node,
168
         const avtab_key_t *key)
169
0
{
170
0
  return node->key.source_type == key->source_type &&
171
0
         node->key.target_type == key->target_type &&
172
0
         node->key.target_class == key->target_class;
173
0
}
174
175
/* Same scenarios of interest as check_assertion_extended_permissions */
176
static int report_assertion_extended_permissions(
177
  sepol_handle_t *handle, policydb_t *p, const avrule_t *narule,
178
  unsigned int stype, unsigned int ttype,
179
  const class_perm_node_t *curperm, uint32_t perms, const avtab_key_t *k,
180
  bool conditional)
181
0
{
182
0
  avtab_ptr_t node;
183
0
  avtab_key_t tmp_key;
184
0
  avtab_extended_perms_t *xperms;
185
0
  avtab_extended_perms_t error;
186
0
  const ebitmap_t *sattr = &p->type_attr_map[stype];
187
0
  const ebitmap_t *tattr = &p->type_attr_map[ttype];
188
0
  ebitmap_node_t *snode, *tnode;
189
0
  unsigned int i, j;
190
0
  bool found_xperm = false, found_cond_conflict = false;
191
0
  int errors = 0;
192
193
0
  memcpy(&tmp_key, k, sizeof(avtab_key_t));
194
0
  tmp_key.specified = AVTAB_XPERMS_ALLOWED;
195
196
0
  ebitmap_for_each_positive_bit(sattr, snode, i) {
197
0
    tmp_key.source_type = i + 1;
198
0
    ebitmap_for_each_positive_bit(tattr, tnode, j) {
199
0
      tmp_key.target_type = j + 1;
200
0
      for (node = avtab_search_node(&p->te_avtab, &tmp_key);
201
0
           node; node = avtab_search_node_next(
202
0
             node, tmp_key.specified)) {
203
0
        xperms = node->datum.xperms;
204
0
        if ((xperms->specified !=
205
0
             AVTAB_XPERMS_IOCTLFUNCTION) &&
206
0
            (xperms->specified !=
207
0
             AVTAB_XPERMS_IOCTLDRIVER) &&
208
0
            (xperms->specified != AVTAB_XPERMS_NLMSG))
209
0
          continue;
210
0
        found_xperm = true;
211
        /* failure on the extended permission check_extended_permissions */
212
0
        if (check_extended_permissions(narule->xperms,
213
0
                     xperms)) {
214
0
          char *permstring;
215
216
0
          extended_permissions_violated(
217
0
            &error, narule->xperms, xperms);
218
0
          permstring =
219
0
            sepol_extended_perms_to_string(
220
0
              &error);
221
222
0
          ERR(handle,
223
0
              "neverallowxperm on line %lu of %s (or line %lu of %s) violated by\n"
224
0
              "  allowxperm %s %s:%s %s;",
225
0
              narule->source_line,
226
0
              narule->source_filename,
227
0
              narule->line, policy_name(p),
228
0
              p->p_type_val_to_name[i],
229
0
              p->p_type_val_to_name[j],
230
0
              p->p_class_val_to_name
231
0
                [curperm->tclass - 1],
232
0
              permstring ?: "<format-failure>");
233
234
0
          free(permstring);
235
0
          errors++;
236
0
        }
237
0
      }
238
239
0
      for (const cond_list_t *cl = p->cond_list; cl;
240
0
           cl = cl->next) {
241
0
        bool found_true_base = false,
242
0
             found_true_xperm = false;
243
0
        bool found_false_base = false,
244
0
             found_false_xperm = false;
245
246
0
        for (const cond_av_list_t *cal = cl->true_list;
247
0
             cal; cal = cal->next) {
248
0
          node = cal->node; /* node->next is not from the same condition */
249
0
          if (!node)
250
0
            continue;
251
252
0
          if (!match_node_key(node, &tmp_key))
253
0
            continue;
254
255
0
          if (match_any_class_permissions(
256
0
                narule->perms,
257
0
                node->key.target_class,
258
0
                node->datum.data)) {
259
0
            found_true_base = true;
260
0
            continue;
261
0
          }
262
263
0
          if (!(node->key.specified &
264
0
                AVTAB_XPERMS_ALLOWED))
265
0
            continue;
266
267
0
          xperms = node->datum.xperms;
268
0
          if ((xperms->specified !=
269
0
               AVTAB_XPERMS_IOCTLFUNCTION) &&
270
0
              (xperms->specified !=
271
0
               AVTAB_XPERMS_IOCTLDRIVER) &&
272
0
              (xperms->specified !=
273
0
               AVTAB_XPERMS_NLMSG))
274
0
            continue;
275
0
          found_true_xperm = true;
276
          /* failure on the extended permission check_extended_permissions */
277
0
          if (check_extended_permissions(
278
0
                narule->xperms, xperms)) {
279
0
            char *permstring;
280
281
0
            extended_permissions_violated(
282
0
              &error, narule->xperms,
283
0
              xperms);
284
0
            permstring =
285
0
              sepol_extended_perms_to_string(
286
0
                &error);
287
288
0
            ERR(handle,
289
0
                "neverallowxperm on line %lu of %s (or line %lu of %s) violated by\n"
290
0
                "  allowxperm %s %s:%s %s;",
291
0
                narule->source_line,
292
0
                narule->source_filename,
293
0
                narule->line,
294
0
                policy_name(p),
295
0
                p->p_type_val_to_name[i],
296
0
                p->p_type_val_to_name[j],
297
0
                p->p_class_val_to_name
298
0
                  [curperm->tclass -
299
0
                   1],
300
0
                permstring ?:
301
0
                  "<format-failure>");
302
303
0
            free(permstring);
304
0
            errors++;
305
0
          }
306
0
        }
307
308
0
        for (const cond_av_list_t *cal = cl->false_list;
309
0
             cal; cal = cal->next) {
310
0
          node = cal->node; /* node->next is not from the same condition */
311
0
          if (!node)
312
0
            continue;
313
314
0
          if (!match_node_key(node, &tmp_key))
315
0
            continue;
316
317
0
          if (match_any_class_permissions(
318
0
                narule->perms,
319
0
                node->key.target_class,
320
0
                node->datum.data)) {
321
0
            found_false_base = true;
322
0
            continue;
323
0
          }
324
325
0
          if (!(node->key.specified &
326
0
                AVTAB_XPERMS_ALLOWED))
327
0
            continue;
328
329
0
          xperms = node->datum.xperms;
330
0
          if ((xperms->specified !=
331
0
               AVTAB_XPERMS_IOCTLFUNCTION) &&
332
0
              (xperms->specified !=
333
0
               AVTAB_XPERMS_IOCTLDRIVER) &&
334
0
              (xperms->specified !=
335
0
               AVTAB_XPERMS_NLMSG))
336
0
            continue;
337
0
          found_false_xperm = true;
338
          /* failure on the extended permission check_extended_permissions */
339
0
          if (check_extended_permissions(
340
0
                narule->xperms, xperms)) {
341
0
            char *permstring;
342
343
0
            extended_permissions_violated(
344
0
              &error, narule->xperms,
345
0
              xperms);
346
0
            permstring =
347
0
              sepol_extended_perms_to_string(
348
0
                &error);
349
350
0
            ERR(handle,
351
0
                "neverallowxperm on line %lu of %s (or line %lu of %s) violated by\n"
352
0
                "  allowxperm %s %s:%s %s;",
353
0
                narule->source_line,
354
0
                narule->source_filename,
355
0
                narule->line,
356
0
                policy_name(p),
357
0
                p->p_type_val_to_name[i],
358
0
                p->p_type_val_to_name[j],
359
0
                p->p_class_val_to_name
360
0
                  [curperm->tclass -
361
0
                   1],
362
0
                permstring ?:
363
0
                  "<format-failure>");
364
365
0
            free(permstring);
366
0
            errors++;
367
0
          }
368
0
        }
369
370
0
        if (found_true_xperm && found_false_xperm)
371
0
          found_xperm = true;
372
0
        else if (conditional && ((found_true_base &&
373
0
                !found_true_xperm) ||
374
0
               (found_false_base &&
375
0
                !found_false_xperm)))
376
0
          found_cond_conflict = true;
377
0
      }
378
0
    }
379
0
  }
380
381
0
  if ((!found_xperm && !conditional) || found_cond_conflict) {
382
    /* failure on the regular permissions */
383
0
    char *permstr = sepol_av_to_string(p, curperm->tclass, perms);
384
385
0
    ERR(handle,
386
0
        "neverallowxperm on line %lu of %s (or line %lu of %s) violated by\n"
387
0
        "  allow %s %s:%s {%s };",
388
0
        narule->source_line, narule->source_filename, narule->line,
389
0
        policy_name(p), p->p_type_val_to_name[stype],
390
0
        p->p_type_val_to_name[ttype],
391
0
        p->p_class_val_to_name[curperm->tclass - 1],
392
0
        permstr ?: "<format-failure>");
393
394
0
    free(permstr);
395
0
    errors++;
396
0
  }
397
398
0
  return errors;
399
0
}
400
401
static int report_assertion_avtab_matches(avtab_key_t *k, avtab_datum_t *d,
402
            void *args)
403
0
{
404
0
  int rc = 0;
405
0
  struct avtab_match_args *a = (struct avtab_match_args *)args;
406
0
  sepol_handle_t *handle = a->handle;
407
0
  policydb_t *p = a->p;
408
0
  const avrule_t *narule = a->narule;
409
0
  const class_perm_node_t *cp;
410
0
  uint32_t perms;
411
0
  ebitmap_t src_matches, tgt_matches, self_matches;
412
0
  ebitmap_node_t *snode, *tnode;
413
0
  unsigned int i, j;
414
0
  const bool is_narule_self = (narule->flags & RULE_SELF) != 0;
415
0
  const bool is_narule_notself = (narule->flags & RULE_NOTSELF) != 0;
416
417
0
  if ((k->specified & AVTAB_ALLOWED) == 0)
418
0
    return 0;
419
420
0
  if (!match_any_class_permissions(narule->perms, k->target_class,
421
0
           d->data))
422
0
    return 0;
423
424
0
  ebitmap_init(&src_matches);
425
0
  ebitmap_init(&tgt_matches);
426
0
  ebitmap_init(&self_matches);
427
428
0
  rc = ebitmap_and(&src_matches, &narule->stypes.types,
429
0
       &p->attr_type_map[k->source_type - 1]);
430
0
  if (rc < 0)
431
0
    goto oom;
432
433
0
  if (ebitmap_is_empty(&src_matches))
434
0
    goto exit;
435
436
0
  if (is_narule_notself) {
437
0
    if (ebitmap_is_empty(&narule->ttypes.types)) {
438
      /* avrule tgt is of the form ~self */
439
0
      rc = ebitmap_cpy(&tgt_matches,
440
0
           &p->attr_type_map[k->target_type - 1]);
441
0
    } else {
442
      /* avrule tgt is of the form {ATTR -self} */
443
0
      rc = ebitmap_and(&tgt_matches, &narule->ttypes.types,
444
0
           &p->attr_type_map[k->target_type - 1]);
445
0
    }
446
0
    if (rc)
447
0
      goto oom;
448
0
  } else {
449
0
    rc = ebitmap_and(&tgt_matches, &narule->ttypes.types,
450
0
         &p->attr_type_map[k->target_type - 1]);
451
0
    if (rc < 0)
452
0
      goto oom;
453
454
0
    if (is_narule_self) {
455
0
      rc = ebitmap_and(&self_matches, &src_matches,
456
0
           &p->attr_type_map[k->target_type - 1]);
457
0
      if (rc < 0)
458
0
        goto oom;
459
460
0
      if (!ebitmap_is_empty(&self_matches)) {
461
0
        rc = ebitmap_union(&tgt_matches, &self_matches);
462
0
        if (rc < 0)
463
0
          goto oom;
464
0
      }
465
0
    }
466
0
  }
467
468
0
  if (ebitmap_is_empty(&tgt_matches))
469
0
    goto exit;
470
471
0
  for (cp = narule->perms; cp; cp = cp->next) {
472
0
    perms = cp->data & d->data;
473
0
    if ((cp->tclass != k->target_class) || !perms) {
474
0
      continue;
475
0
    }
476
477
0
    ebitmap_for_each_positive_bit(&src_matches, snode, i) {
478
0
      ebitmap_for_each_positive_bit(&tgt_matches, tnode, j) {
479
0
        if (is_narule_self && i != j)
480
0
          continue;
481
0
        if (is_narule_notself && i == j)
482
0
          continue;
483
0
        if (narule->specified ==
484
0
            AVRULE_XPERMS_NEVERALLOW) {
485
0
          a->errors +=
486
0
            report_assertion_extended_permissions(
487
0
              handle, p, narule, i, j,
488
0
              cp, perms, k,
489
0
              a->conditional);
490
0
        } else {
491
0
          a->errors++;
492
0
          report_failure(handle, p, narule, i, j,
493
0
                   cp, perms);
494
0
        }
495
0
      }
496
0
    }
497
0
  }
498
499
0
oom:
500
0
exit:
501
0
  ebitmap_destroy(&src_matches);
502
0
  ebitmap_destroy(&tgt_matches);
503
0
  ebitmap_destroy(&self_matches);
504
0
  return rc;
505
0
}
506
507
static int report_assertion_failures(sepol_handle_t *handle, policydb_t *p,
508
             const avrule_t *narule)
509
0
{
510
0
  int rc;
511
0
  struct avtab_match_args args = {
512
0
    .handle = handle,
513
0
    .p = p,
514
0
    .narule = narule,
515
0
    .errors = 0,
516
0
  };
517
518
0
  args.conditional = false;
519
0
  rc = avtab_map(&p->te_avtab, report_assertion_avtab_matches, &args);
520
0
  if (rc < 0)
521
0
    goto oom;
522
523
0
  args.conditional = true;
524
0
  rc = avtab_map(&p->te_cond_avtab, report_assertion_avtab_matches,
525
0
           &args);
526
0
  if (rc < 0)
527
0
    goto oom;
528
529
0
  return args.errors;
530
531
0
oom:
532
0
  return rc;
533
0
}
534
535
/*
536
 * Look up the extended permissions in avtab and verify that neverallowed
537
 * permissions are not granted.
538
 */
539
static bool check_assertion_extended_permissions_avtab(
540
  const avrule_t *narule, unsigned int stype, unsigned int ttype,
541
  const avtab_key_t *k, policydb_t *p, bool conditional)
542
0
{
543
0
  avtab_ptr_t node;
544
0
  avtab_key_t tmp_key;
545
0
  const avtab_extended_perms_t *xperms;
546
0
  const av_extended_perms_t *neverallow_xperms = narule->xperms;
547
0
  const ebitmap_t *sattr = &p->type_attr_map[stype];
548
0
  const ebitmap_t *tattr = &p->type_attr_map[ttype];
549
0
  ebitmap_node_t *snode, *tnode;
550
0
  unsigned int i, j;
551
0
  bool found_xperm = false, found_cond_conflict = false;
552
553
0
  memcpy(&tmp_key, k, sizeof(avtab_key_t));
554
0
  tmp_key.specified = AVTAB_XPERMS_ALLOWED;
555
556
0
  ebitmap_for_each_positive_bit(sattr, snode, i) {
557
0
    tmp_key.source_type = i + 1;
558
0
    ebitmap_for_each_positive_bit(tattr, tnode, j) {
559
0
      tmp_key.target_type = j + 1;
560
0
      for (node = avtab_search_node(&p->te_avtab, &tmp_key);
561
0
           node; node = avtab_search_node_next(
562
0
             node, tmp_key.specified)) {
563
0
        xperms = node->datum.xperms;
564
565
0
        if ((xperms->specified !=
566
0
             AVTAB_XPERMS_IOCTLFUNCTION) &&
567
0
            (xperms->specified !=
568
0
             AVTAB_XPERMS_IOCTLDRIVER) &&
569
0
            (xperms->specified != AVTAB_XPERMS_NLMSG))
570
0
          continue;
571
0
        found_xperm = true;
572
0
        if (check_extended_permissions(
573
0
              neverallow_xperms, xperms))
574
0
          return true;
575
0
      }
576
577
0
      for (const cond_list_t *cl = p->cond_list; cl;
578
0
           cl = cl->next) {
579
0
        bool found_true_base = false,
580
0
             found_true_xperm = false;
581
0
        bool found_false_base = false,
582
0
             found_false_xperm = false;
583
584
0
        for (const cond_av_list_t *cal = cl->true_list;
585
0
             cal; cal = cal->next) {
586
0
          node = cal->node; /* node->next is not from the same condition */
587
0
          if (!node)
588
0
            continue;
589
590
0
          if (!match_node_key(node, &tmp_key))
591
0
            continue;
592
593
0
          if ((node->key.specified &
594
0
               AVTAB_ALLOWED) &&
595
0
              match_any_class_permissions(
596
0
                narule->perms,
597
0
                node->key.target_class,
598
0
                node->datum.data)) {
599
0
            found_true_base = true;
600
0
            continue;
601
0
          }
602
603
0
          if (!(node->key.specified &
604
0
                AVTAB_XPERMS_ALLOWED))
605
0
            continue;
606
607
0
          xperms = node->datum.xperms;
608
609
0
          if ((xperms->specified !=
610
0
               AVTAB_XPERMS_IOCTLFUNCTION) &&
611
0
              (xperms->specified !=
612
0
               AVTAB_XPERMS_IOCTLDRIVER) &&
613
0
              (xperms->specified !=
614
0
               AVTAB_XPERMS_NLMSG))
615
0
            continue;
616
0
          found_true_xperm = true;
617
0
          if (check_extended_permissions(
618
0
                neverallow_xperms, xperms))
619
0
            return true;
620
0
        }
621
622
0
        for (const cond_av_list_t *cal = cl->false_list;
623
0
             cal; cal = cal->next) {
624
0
          node = cal->node; /* node->next is not from the same condition */
625
0
          if (!node)
626
0
            continue;
627
628
0
          if (!match_node_key(node, &tmp_key))
629
0
            continue;
630
631
0
          if ((node->key.specified &
632
0
               AVTAB_ALLOWED) &&
633
0
              match_any_class_permissions(
634
0
                narule->perms,
635
0
                node->key.target_class,
636
0
                node->datum.data)) {
637
0
            found_false_base = true;
638
0
            continue;
639
0
          }
640
641
0
          if (!(node->key.specified &
642
0
                AVTAB_XPERMS_ALLOWED))
643
0
            continue;
644
645
0
          xperms = node->datum.xperms;
646
647
0
          if ((xperms->specified !=
648
0
               AVTAB_XPERMS_IOCTLFUNCTION) &&
649
0
              (xperms->specified !=
650
0
               AVTAB_XPERMS_IOCTLDRIVER) &&
651
0
              (xperms->specified !=
652
0
               AVTAB_XPERMS_NLMSG))
653
0
            continue;
654
0
          found_false_xperm = true;
655
0
          if (check_extended_permissions(
656
0
                neverallow_xperms, xperms))
657
0
            return true;
658
0
        }
659
660
0
        if (found_true_xperm && found_false_xperm)
661
0
          found_xperm = true;
662
0
        else if (conditional && ((found_true_base &&
663
0
                !found_true_xperm) ||
664
0
               (found_false_base &&
665
0
                !found_false_xperm)))
666
0
          found_cond_conflict = true;
667
0
      }
668
0
    }
669
0
  }
670
671
0
  return (!conditional && !found_xperm) || found_cond_conflict;
672
0
}
673
674
/*
675
 * When the ioctl permission is granted on an avtab entry that matches an
676
 * avrule neverallowxperm entry, enumerate over the matching
677
 * source/target/class sets to determine if the extended permissions exist
678
 * and if the neverallowed ioctls are granted.
679
 *
680
 * Four scenarios of interest:
681
 * 1. PASS - the ioctl permission is not granted for this source/target/class
682
 *    This case is handled in check_assertion_avtab_match
683
 * 2. PASS - The ioctl permission is granted AND the extended permission
684
 *    is NOT granted
685
 * 3. FAIL - The ioctl permission is granted AND no extended permissions
686
 *    exist
687
 * 4. FAIL - The ioctl permission is granted AND the extended permission is
688
 *    granted
689
 */
690
static int check_assertion_extended_permissions(const avrule_t *narule,
691
            const avtab_key_t *k,
692
            policydb_t *p, bool conditional)
693
0
{
694
0
  ebitmap_t src_matches, tgt_matches, self_matches;
695
0
  unsigned int i, j;
696
0
  ebitmap_node_t *snode, *tnode;
697
0
  const bool is_narule_self = (narule->flags & RULE_SELF) != 0;
698
0
  const bool is_narule_notself = (narule->flags & RULE_NOTSELF) != 0;
699
0
  int rc;
700
701
0
  ebitmap_init(&src_matches);
702
0
  ebitmap_init(&tgt_matches);
703
0
  ebitmap_init(&self_matches);
704
705
0
  rc = ebitmap_and(&src_matches, &narule->stypes.types,
706
0
       &p->attr_type_map[k->source_type - 1]);
707
0
  if (rc < 0)
708
0
    goto oom;
709
710
0
  if (ebitmap_is_empty(&src_matches)) {
711
0
    rc = 0;
712
0
    goto exit;
713
0
  }
714
715
0
  if (is_narule_notself) {
716
0
    if (ebitmap_is_empty(&narule->ttypes.types)) {
717
      /* avrule tgt is of the form ~self */
718
0
      rc = ebitmap_cpy(&tgt_matches,
719
0
           &p->attr_type_map[k->target_type - 1]);
720
0
    } else {
721
      /* avrule tgt is of the form {ATTR -self} */
722
0
      rc = ebitmap_and(&tgt_matches, &narule->ttypes.types,
723
0
           &p->attr_type_map[k->target_type - 1]);
724
0
    }
725
0
    if (rc < 0)
726
0
      goto oom;
727
0
  } else {
728
0
    rc = ebitmap_and(&tgt_matches, &narule->ttypes.types,
729
0
         &p->attr_type_map[k->target_type - 1]);
730
0
    if (rc < 0)
731
0
      goto oom;
732
733
0
    if (is_narule_self) {
734
0
      rc = ebitmap_and(&self_matches, &src_matches,
735
0
           &p->attr_type_map[k->target_type - 1]);
736
0
      if (rc < 0)
737
0
        goto oom;
738
739
0
      if (!ebitmap_is_empty(&self_matches)) {
740
0
        rc = ebitmap_union(&tgt_matches, &self_matches);
741
0
        if (rc < 0)
742
0
          goto oom;
743
0
      }
744
0
    }
745
0
  }
746
747
0
  if (ebitmap_is_empty(&tgt_matches)) {
748
0
    rc = 0;
749
0
    goto exit;
750
0
  }
751
752
0
  ebitmap_for_each_positive_bit(&src_matches, snode, i) {
753
0
    ebitmap_for_each_positive_bit(&tgt_matches, tnode, j) {
754
0
      if (is_narule_self && i != j)
755
0
        continue;
756
0
      if (is_narule_notself && i == j)
757
0
        continue;
758
0
      if (check_assertion_extended_permissions_avtab(
759
0
            narule, i, j, k, p, conditional)) {
760
0
        rc = 1;
761
0
        goto exit;
762
0
      }
763
0
    }
764
0
  }
765
766
0
  rc = 0;
767
768
0
oom:
769
0
exit:
770
0
  ebitmap_destroy(&src_matches);
771
0
  ebitmap_destroy(&tgt_matches);
772
0
  ebitmap_destroy(&self_matches);
773
0
  return rc;
774
0
}
775
776
static int check_assertion_notself_match(const avtab_key_t *k,
777
           const avrule_t *narule, policydb_t *p)
778
0
{
779
0
  ebitmap_t src_matches, tgt_matches;
780
0
  unsigned int num_src_matches, num_tgt_matches;
781
0
  int rc;
782
783
0
  ebitmap_init(&src_matches);
784
0
  ebitmap_init(&tgt_matches);
785
786
0
  rc = ebitmap_and(&src_matches, &narule->stypes.types,
787
0
       &p->attr_type_map[k->source_type - 1]);
788
0
  if (rc < 0)
789
0
    goto oom;
790
791
0
  if (ebitmap_is_empty(&narule->ttypes.types)) {
792
    /* avrule tgt is of the form ~self */
793
0
    rc = ebitmap_cpy(&tgt_matches,
794
0
         &p->attr_type_map[k->target_type - 1]);
795
0
  } else {
796
    /* avrule tgt is of the form {ATTR -self} */
797
0
    rc = ebitmap_and(&tgt_matches, &narule->ttypes.types,
798
0
         &p->attr_type_map[k->target_type - 1]);
799
0
  }
800
0
  if (rc < 0)
801
0
    goto oom;
802
803
0
  num_src_matches = ebitmap_cardinality(&src_matches);
804
0
  num_tgt_matches = ebitmap_cardinality(&tgt_matches);
805
0
  if (num_src_matches == 0 || num_tgt_matches == 0) {
806
0
    rc = 0;
807
0
    goto nomatch;
808
0
  }
809
0
  if (num_src_matches == 1 && num_tgt_matches == 1) {
810
0
    ebitmap_t matches;
811
0
    unsigned int num_matches;
812
0
    rc = ebitmap_and(&matches, &src_matches, &tgt_matches);
813
0
    if (rc < 0) {
814
0
      ebitmap_destroy(&matches);
815
0
      goto oom;
816
0
    }
817
0
    num_matches = ebitmap_cardinality(&matches);
818
0
    ebitmap_destroy(&matches);
819
0
    if (num_matches == 1) {
820
      /* The only non-match is of the form TYPE TYPE */
821
0
      rc = 0;
822
0
      goto nomatch;
823
0
    }
824
0
  }
825
826
0
  rc = 1;
827
828
0
oom:
829
0
nomatch:
830
0
  ebitmap_destroy(&src_matches);
831
0
  ebitmap_destroy(&tgt_matches);
832
0
  return rc;
833
0
}
834
835
static int check_assertion_self_match(const avtab_key_t *k,
836
              const avrule_t *narule, policydb_t *p)
837
0
{
838
0
  ebitmap_t src_matches;
839
0
  int rc;
840
841
  /* The key's target must match something in the matches of the avrule's source
842
   * and the key's source.
843
   */
844
845
0
  rc = ebitmap_and(&src_matches, &narule->stypes.types,
846
0
       &p->attr_type_map[k->source_type - 1]);
847
0
  if (rc < 0)
848
0
    goto oom;
849
850
0
  if (!ebitmap_match_any(&src_matches,
851
0
             &p->attr_type_map[k->target_type - 1])) {
852
0
    rc = 0;
853
0
    goto nomatch;
854
0
  }
855
856
0
  rc = 1;
857
858
0
oom:
859
0
nomatch:
860
0
  ebitmap_destroy(&src_matches);
861
0
  return rc;
862
0
}
863
864
static int check_assertion_avtab_match(avtab_key_t *k, avtab_datum_t *d,
865
               void *args)
866
0
{
867
0
  int rc;
868
0
  struct avtab_match_args *a = (struct avtab_match_args *)args;
869
0
  policydb_t *p = a->p;
870
0
  const avrule_t *narule = a->narule;
871
872
0
  if ((k->specified & AVTAB_ALLOWED) == 0)
873
0
    goto nomatch;
874
875
0
  if (!match_any_class_permissions(narule->perms, k->target_class,
876
0
           d->data))
877
0
    goto nomatch;
878
879
0
  if (!ebitmap_match_any(&narule->stypes.types,
880
0
             &p->attr_type_map[k->source_type - 1]))
881
0
    goto nomatch;
882
883
0
  if (narule->flags & RULE_NOTSELF) {
884
0
    rc = check_assertion_notself_match(k, narule, p);
885
0
    if (rc < 0)
886
0
      goto oom;
887
0
    if (rc == 0)
888
0
      goto nomatch;
889
0
  } else {
890
    /* neverallow may have tgts even if it uses SELF */
891
0
    if (!ebitmap_match_any(&narule->ttypes.types,
892
0
               &p->attr_type_map[k->target_type - 1])) {
893
0
      if (narule->flags == RULE_SELF) {
894
0
        rc = check_assertion_self_match(k, narule, p);
895
0
        if (rc < 0)
896
0
          goto oom;
897
0
        if (rc == 0)
898
0
          goto nomatch;
899
0
      } else {
900
0
        goto nomatch;
901
0
      }
902
0
    }
903
0
  }
904
905
0
  if (narule->specified == AVRULE_XPERMS_NEVERALLOW) {
906
0
    rc = check_assertion_extended_permissions(narule, k, p,
907
0
                a->conditional);
908
0
    if (rc < 0)
909
0
      goto oom;
910
0
    if (rc == 0)
911
0
      goto nomatch;
912
0
  }
913
0
  return 1;
914
915
0
nomatch:
916
0
  return 0;
917
918
0
oom:
919
0
  return rc;
920
0
}
921
922
int check_assertion(policydb_t *p, const avrule_t *narule)
923
0
{
924
0
  int rc;
925
0
  struct avtab_match_args args = {
926
0
    .handle = NULL,
927
0
    .p = p,
928
0
    .narule = narule,
929
0
    .errors = 0,
930
0
  };
931
932
0
  args.conditional = false;
933
0
  rc = avtab_map(&p->te_avtab, check_assertion_avtab_match, &args);
934
935
0
  if (rc == 0) {
936
0
    args.conditional = true;
937
0
    rc = avtab_map(&p->te_cond_avtab, check_assertion_avtab_match,
938
0
             &args);
939
0
  }
940
941
0
  return rc;
942
0
}
943
944
int check_assertions(sepol_handle_t *handle, policydb_t *p,
945
         const avrule_t *narules)
946
0
{
947
0
  int rc;
948
0
  const avrule_t *a;
949
0
  unsigned long errors = 0;
950
951
0
  for (a = narules; a != NULL; a = a->next) {
952
0
    if (!(a->specified &
953
0
          (AVRULE_NEVERALLOW | AVRULE_XPERMS_NEVERALLOW)))
954
0
      continue;
955
0
    rc = check_assertion(p, a);
956
0
    if (rc < 0) {
957
0
      ERR(handle,
958
0
          "Error occurred while checking neverallows");
959
0
      return -1;
960
0
    }
961
0
    if (rc) {
962
0
      rc = report_assertion_failures(handle, p, a);
963
0
      if (rc < 0) {
964
0
        ERR(handle,
965
0
            "Error occurred while checking neverallows");
966
0
        return -1;
967
0
      }
968
0
      errors += rc;
969
0
    }
970
0
  }
971
972
0
  if (errors)
973
0
    ERR(handle, "%lu neverallow failures occurred", errors);
974
975
0
  return errors ? -1 : 0;
976
0
}