Coverage Report

Created: 2026-01-10 06:30

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/selinux/libsepol/cil/src/cil_policy.c
Line
Count
Source
1
/*
2
 * Copyright 2011 Tresys Technology, LLC. All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions are met:
6
 *
7
 *    1. Redistributions of source code must retain the above copyright notice,
8
 *       this list of conditions and the following disclaimer.
9
 *
10
 *    2. Redistributions in binary form must reproduce the above copyright notice,
11
 *       this list of conditions and the following disclaimer in the documentation
12
 *       and/or other materials provided with the distribution.
13
 *
14
 * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS
15
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
16
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
17
 * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
18
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
19
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
21
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
22
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
23
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24
 *
25
 * The views and conclusions contained in the software and documentation are those
26
 * of the authors and should not be interpreted as representing official policies,
27
 * either expressed or implied, of Tresys Technology, LLC.
28
 */
29
30
#include <stdlib.h>
31
#include <stdio.h>
32
#include <string.h>
33
#include <stdint.h>
34
#include <unistd.h>
35
#include <inttypes.h>
36
37
#include <sepol/policydb/conditional.h>
38
#include <sepol/errcodes.h>
39
40
#include "cil_internal.h"
41
#include "cil_flavor.h"
42
#include "cil_find.h"
43
#include "cil_mem.h"
44
#include "cil_policy.h"
45
#include "cil_tree.h"
46
#include "cil_list.h"
47
#include "cil_symtab.h"
48
49
50
enum cil_statement_list {
51
  CIL_LIST_COMMON = 1,
52
  CIL_LIST_DEFAULT_USER,
53
  CIL_LIST_DEFAULT_ROLE,
54
  CIL_LIST_DEFAULT_TYPE,
55
  CIL_LIST_DEFAULT_RANGE,
56
  CIL_LIST_SENSALIAS,
57
  CIL_LIST_CATALIAS,
58
  CIL_LIST_MLSCONSTRAIN,
59
  CIL_LIST_MLSVALIDATETRANS,
60
  CIL_LIST_POLICYCAP,
61
  CIL_LIST_TYPEATTRIBUTE,
62
  CIL_LIST_ROLEATTRIBUTE,
63
  CIL_LIST_BOOL,
64
  CIL_LIST_TYPE,
65
  CIL_LIST_TYPEALIAS,
66
  CIL_LIST_ROLE,
67
  CIL_LIST_ROLEALLOW,
68
  CIL_LIST_ROLETRANSITION,
69
  CIL_LIST_USER,
70
  CIL_LIST_CONSTRAINT,
71
  CIL_LIST_VALIDATETRANS,
72
  CIL_LIST_NUM_LISTS
73
};
74
75
static int __cil_gather_statements_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args)
76
0
{
77
0
  struct cil_list **lists;
78
0
  int kind = 0;
79
80
0
  lists = (struct cil_list **)extra_args;
81
82
0
  switch (node->flavor) {
83
0
  case CIL_BLOCK: {
84
0
    struct cil_block *blk = node->data;
85
0
    if (blk->is_abstract == CIL_TRUE) {
86
0
      *finished = CIL_TREE_SKIP_HEAD;
87
0
    }
88
0
    break;
89
0
  }
90
0
  case CIL_MACRO:
91
0
    *finished = CIL_TREE_SKIP_HEAD;
92
0
    break;
93
0
  case CIL_BOOLEANIF:
94
0
    *finished = CIL_TREE_SKIP_HEAD;
95
0
    break;
96
0
  case CIL_COMMON:
97
0
    kind = CIL_LIST_COMMON;
98
0
    break;
99
0
  case CIL_DEFAULTUSER:
100
0
    kind = CIL_LIST_DEFAULT_USER;
101
0
    break;
102
0
  case CIL_DEFAULTROLE:
103
0
    kind = CIL_LIST_DEFAULT_ROLE;
104
0
    break;
105
0
  case CIL_DEFAULTTYPE:
106
0
    kind = CIL_LIST_DEFAULT_TYPE;
107
0
    break;
108
0
  case CIL_DEFAULTRANGE:
109
0
    kind = CIL_LIST_DEFAULT_RANGE;
110
0
    break;
111
0
  case CIL_SENSALIAS:
112
0
    kind = CIL_LIST_SENSALIAS;
113
0
    break;
114
0
  case CIL_CATALIAS:
115
0
    kind = CIL_LIST_CATALIAS;
116
0
    break;
117
0
  case CIL_MLSCONSTRAIN:
118
0
    kind = CIL_LIST_MLSCONSTRAIN;
119
0
    break;
120
0
  case CIL_MLSVALIDATETRANS:
121
0
    kind = CIL_LIST_MLSVALIDATETRANS;
122
0
    break;
123
0
  case CIL_POLICYCAP:
124
0
    kind = CIL_LIST_POLICYCAP;
125
0
    break;
126
0
  case CIL_TYPEATTRIBUTE: {
127
0
    struct cil_typeattribute *attr = node->data;
128
0
    if (strcmp(attr->datum.fqn, "cil_gen_require") != 0) {
129
0
      kind = CIL_LIST_TYPEATTRIBUTE;
130
0
    }
131
0
    break;
132
0
  }
133
0
  case CIL_ROLEATTRIBUTE: {
134
0
    struct cil_roleattribute *attr = node->data;
135
0
    if (strcmp(attr->datum.fqn, "cil_gen_require") != 0) {
136
0
      kind = CIL_LIST_ROLEATTRIBUTE;
137
0
    }
138
0
    break;
139
0
  }
140
0
  case CIL_BOOL:
141
0
    kind = CIL_LIST_BOOL;
142
0
    break;
143
0
  case CIL_TYPE:
144
0
    kind = CIL_LIST_TYPE;
145
0
    break;
146
0
  case CIL_TYPEALIAS:
147
0
    kind = CIL_LIST_TYPEALIAS;
148
0
    break;
149
0
  case CIL_ROLE: {
150
0
    struct cil_role *role = node->data;
151
0
    if (strcmp(role->datum.fqn, "object_r") != 0) {
152
0
      kind = CIL_LIST_ROLE;
153
0
    }
154
0
    break;
155
0
  }
156
0
  case CIL_ROLEALLOW:
157
0
    kind = CIL_LIST_ROLEALLOW;
158
0
    break;
159
0
  case CIL_ROLETRANSITION:
160
0
    kind = CIL_LIST_ROLETRANSITION;
161
0
    break;
162
0
  case CIL_USER:
163
0
    kind = CIL_LIST_USER;
164
0
    break;
165
0
  case CIL_CONSTRAIN:
166
0
    kind = CIL_LIST_CONSTRAINT;
167
0
    break;
168
0
  case CIL_VALIDATETRANS:
169
0
    kind = CIL_LIST_VALIDATETRANS;
170
0
    break;
171
0
  default:
172
0
    break;
173
0
  }
174
175
0
  if (kind > 0) {
176
0
    cil_list_append(lists[kind], node->flavor, node->data);
177
0
  }
178
179
0
  return SEPOL_OK;
180
0
}
181
182
static void cil_gather_statements(struct cil_tree_node *start, struct cil_list *lists[])
183
0
{
184
0
  cil_tree_walk(start, __cil_gather_statements_helper, NULL, NULL, lists);
185
0
}
186
187
static void cil_simple_rules_to_policy(FILE *out, struct cil_list *rules, const char *kind)
188
0
{
189
0
  struct cil_list_item *i1;
190
191
0
  cil_list_for_each(i1, rules) {
192
0
    fprintf(out, "%s %s;\n", kind, DATUM(i1->data)->fqn);
193
0
  }
194
0
}
195
196
static void cil_cats_to_policy(FILE *out, struct cil_cats *cats)
197
0
{
198
0
  const char *lead = "";
199
0
  struct cil_cat *first = NULL, *last = NULL, *cat;
200
0
  struct cil_list_item *i1;
201
202
0
  cil_list_for_each(i1, cats->datum_expr) {
203
0
    cat = i1->data;
204
0
    if (first == NULL) {
205
0
      first = cat;
206
0
    } else if (last == NULL) {
207
0
      if (cat->value == first->value + 1) {
208
0
        last = cat;
209
0
      } else {
210
0
        fprintf(out, "%s%s", lead, DATUM(first)->fqn);
211
0
        lead = ",";
212
0
        first = cat;
213
0
      }
214
0
    } else if (cat->value == last->value + 1) {
215
0
      last = cat;
216
0
    } else {
217
0
      fprintf(out, "%s%s", lead, DATUM(first)->fqn);
218
0
      lead = ",";
219
0
      if (last->value >= first->value + 1) {
220
0
        fprintf(out, ".");
221
0
      } else {
222
0
        fprintf(out, ",");
223
0
      }
224
0
      fprintf(out, "%s", DATUM(last)->fqn);
225
0
      first = cat;
226
0
      last = NULL;
227
0
    }
228
0
  }
229
0
  if (first) {
230
0
    fprintf(out, "%s%s", lead, DATUM(first)->fqn);
231
0
    if (last != NULL) {
232
0
      if (last->value >= first->value + 1) {
233
0
        fprintf(out, ".");
234
0
      } else {
235
0
        fprintf(out, ",");
236
0
      }
237
0
      fprintf(out, "%s", DATUM(last)->fqn);
238
0
    }
239
0
  }
240
0
}
241
242
static void cil_level_to_policy(FILE *out, struct cil_level *level)
243
0
{
244
0
  fprintf(out, "%s", DATUM(level->sens)->fqn);
245
0
  if (level->cats != NULL) {
246
0
    fprintf(out, ":");
247
0
    cil_cats_to_policy(out, level->cats);
248
0
  }
249
0
}
250
251
static int cil_levels_simple_and_equal(struct cil_level *l1, struct cil_level *l2)
252
0
{
253
  /* Mostly just want to detect s0 - s0 ranges */
254
0
  if (l1 == l2)
255
0
    return CIL_TRUE;
256
257
0
  if (l1->sens == l2->sens && (l1->cats == NULL && l2->cats == NULL))
258
0
    return CIL_TRUE;
259
260
0
  return CIL_FALSE;
261
0
}
262
263
static void cil_levelrange_to_policy(FILE *out, struct cil_levelrange *lvlrange)
264
0
{
265
0
  cil_level_to_policy(out, lvlrange->low);
266
0
  if (cil_levels_simple_and_equal(lvlrange->low, lvlrange->high) == CIL_FALSE) {
267
0
    fprintf(out, " - ");
268
0
    cil_level_to_policy(out, lvlrange->high);
269
0
  }
270
0
}
271
272
static void cil_context_to_policy(FILE *out, struct cil_context *context, int mls)
273
0
{
274
0
  fprintf(out, "%s:", DATUM(context->user)->fqn);
275
0
  fprintf(out, "%s:", DATUM(context->role)->fqn);
276
0
  fprintf(out, "%s", DATUM(context->type)->fqn);
277
0
  if (mls) {
278
0
    fprintf(out, ":");
279
0
    cil_levelrange_to_policy(out, context->range);
280
0
  }
281
0
}
282
283
static void cil_cond_expr_to_policy(FILE *out, struct cil_list *expr, int first)
284
0
{
285
0
  struct cil_list_item *i1 = expr->head;
286
287
0
  if (i1->flavor == CIL_OP) {
288
0
    enum cil_flavor op = (enum cil_flavor)(uintptr_t)i1->data;
289
0
    fprintf(out, "(");
290
0
    switch (op) {
291
0
    case CIL_NOT:
292
0
      fprintf(out, "! ");
293
0
      cil_cond_expr_to_policy(out, i1->next->data, CIL_FALSE);
294
0
      break;
295
0
    case CIL_OR:
296
0
      cil_cond_expr_to_policy(out, i1->next->data, CIL_FALSE);
297
0
      fprintf(out, " || ");
298
0
      cil_cond_expr_to_policy(out, i1->next->next->data, CIL_FALSE);
299
0
      break;
300
0
    case CIL_AND:
301
0
      cil_cond_expr_to_policy(out, i1->next->data, CIL_FALSE);
302
0
      fprintf(out, " && ");
303
0
      cil_cond_expr_to_policy(out, i1->next->next->data, CIL_FALSE);
304
0
      break;
305
0
    case CIL_XOR:
306
0
      cil_cond_expr_to_policy(out, i1->next->data, CIL_FALSE);
307
0
      fprintf(out, " ^ ");
308
0
      cil_cond_expr_to_policy(out, i1->next->next->data, CIL_FALSE);
309
0
      break;
310
0
    case CIL_EQ:
311
0
      cil_cond_expr_to_policy(out, i1->next->data, CIL_FALSE);
312
0
      fprintf(out, " == ");
313
0
      cil_cond_expr_to_policy(out, i1->next->next->data, CIL_FALSE);
314
0
      break;
315
0
    case CIL_NEQ:
316
0
      cil_cond_expr_to_policy(out, i1->next->data, CIL_FALSE);
317
0
      fprintf(out, " != ");
318
0
      cil_cond_expr_to_policy(out, i1->next->next->data, CIL_FALSE);
319
0
      break;
320
0
    default:
321
0
      fprintf(out, "???");
322
0
      break;
323
0
    }
324
0
    fprintf(out, ")");
325
0
  } else if (i1->flavor == CIL_DATUM) {
326
0
    if (first == CIL_TRUE) {
327
0
      fprintf(out, "(");
328
0
    }
329
0
    fprintf(out, "%s", DATUM(i1->data)->fqn);
330
0
    if (first == CIL_TRUE) {
331
0
      fprintf(out, ")");
332
0
    }
333
0
  } else if (i1->flavor == CIL_LIST) {
334
0
    cil_cond_expr_to_policy(out, i1->data, CIL_FALSE);
335
0
  } else {
336
0
    fprintf(out, "???");
337
0
  }
338
0
}
339
340
static size_t __cil_userattribute_len(struct cil_db *db, struct cil_userattribute *attr)
341
0
{
342
0
  ebitmap_node_t *unode;
343
0
  unsigned int i;
344
0
  size_t len = 0;
345
346
0
  ebitmap_for_each_positive_bit(attr->users, unode, i) {
347
0
    len += strlen(DATUM(db->val_to_user[i])->fqn);
348
0
    len++;
349
0
  }
350
351
0
  return len;
352
0
}
353
354
static size_t __cil_cons_leaf_operand_len(struct cil_db *db, struct cil_list_item *operand)
355
0
{
356
0
  struct cil_list_item *i1;
357
0
  enum cil_flavor flavor = operand->flavor;
358
0
  size_t len = 0;
359
360
0
  if (flavor == CIL_CONS_OPERAND) {
361
0
    len = 2;
362
0
  } else if (flavor == CIL_DATUM) {
363
0
    struct cil_tree_node *node = NODE(operand->data);
364
0
    if (node->flavor == CIL_USERATTRIBUTE) {
365
0
      len = __cil_userattribute_len(db, operand->data);
366
0
      len++; /* "{" */
367
0
    } else {
368
0
      len = strlen(DATUM(operand->data)->fqn);
369
0
    }
370
0
  } else if (flavor == CIL_LIST) {
371
0
    len = 1; /* "{" */
372
0
    cil_list_for_each(i1, (struct cil_list *)operand->data) {
373
0
      struct cil_tree_node *node = NODE(operand->data);
374
0
      if (node->flavor == CIL_USERATTRIBUTE) {
375
0
        len = __cil_userattribute_len(db, operand->data);
376
0
      } else {
377
0
        len += strlen(DATUM(operand->data)->fqn);
378
0
        len++; /* " " or "}" */
379
0
      }
380
0
    }
381
0
  }
382
383
0
  return len;
384
0
}
385
386
static size_t __cil_cons_leaf_op_len(struct cil_list_item *op)
387
0
{
388
0
  enum cil_flavor flavor = (enum cil_flavor)(uintptr_t)op->data;
389
0
  size_t len;
390
391
0
  switch (flavor) {
392
0
  case CIL_EQ:
393
0
    len = 4; /* " == " */
394
0
    break;
395
0
  case CIL_NEQ:
396
0
    len = 4; /* " != " */
397
0
    break;
398
0
  case CIL_CONS_DOM:
399
0
    len = 5; /* " dom " */
400
0
    break;
401
0
  case CIL_CONS_DOMBY:
402
0
    len = 7; /* " domby " */
403
0
    break;
404
0
  case CIL_CONS_INCOMP:
405
0
    len = 8; /* " incomp " */
406
0
    break;
407
0
  default:
408
    /* Should be impossible to be here */
409
0
    len = 5; /* " ??? " */
410
0
  }
411
412
0
  return len;
413
0
}
414
415
static size_t cil_cons_expr_len(struct cil_db *db, struct cil_list *cons_expr)
416
0
{
417
0
  struct cil_list_item *i1;
418
0
  enum cil_flavor op;
419
0
  size_t len;
420
421
0
  i1 = cons_expr->head;
422
423
0
  op = (enum cil_flavor)(uintptr_t)i1->data;
424
0
  switch (op) {
425
0
  case CIL_NOT:
426
0
    len = 6; /* "(not )" */
427
0
    len += cil_cons_expr_len(db, i1->next->data);
428
0
    break;
429
0
  case CIL_AND:
430
0
    len = 7; /* "( and )" */
431
0
    len += cil_cons_expr_len(db, i1->next->data);
432
0
    len += cil_cons_expr_len(db, i1->next->next->data);
433
0
    break;
434
0
  case CIL_OR:
435
0
    len = 6; /* "( or )" */
436
0
    len += cil_cons_expr_len(db, i1->next->data);
437
0
    len += cil_cons_expr_len(db, i1->next->next->data);
438
0
    break;
439
0
  default:
440
0
    len = 2; /* "()" */
441
0
    len += __cil_cons_leaf_operand_len(db, i1->next);
442
0
    len += __cil_cons_leaf_op_len(i1);
443
0
    len += __cil_cons_leaf_operand_len(db, i1->next->next);
444
0
  }
445
446
0
  return len;
447
0
}
448
449
static char *__cil_userattribute_to_string(struct cil_db *db, struct cil_userattribute *attr, char *new)
450
0
{
451
0
  ebitmap_node_t *unode;
452
0
  unsigned int i;
453
0
  char *str;
454
0
  size_t len;
455
456
0
  ebitmap_for_each_positive_bit(attr->users, unode, i) {
457
0
    str = DATUM(db->val_to_user[i])->fqn;
458
0
    len = strlen(str);
459
0
    memcpy(new, str, len);
460
0
    new += len;
461
0
    *new++ = ' ';
462
0
  }
463
464
0
  return new;
465
0
}
466
467
static char *__cil_cons_leaf_operand_to_string(struct cil_db *db, struct cil_list_item *operand, char *new)
468
0
{
469
0
  struct cil_list_item *i1;
470
0
  enum cil_flavor flavor = operand->flavor;
471
0
  const char *o_str;
472
0
  size_t o_len;
473
474
0
  if (flavor == CIL_CONS_OPERAND) {
475
0
    enum cil_flavor o_flavor = (enum cil_flavor)(uintptr_t)operand->data;
476
0
    switch (o_flavor) {
477
0
    case CIL_CONS_U1:
478
0
      o_str = "u1";
479
0
      break;
480
0
    case CIL_CONS_U2:
481
0
      o_str = "u2";
482
0
      break;
483
0
    case CIL_CONS_U3:
484
0
      o_str = "u3";
485
0
      break;
486
0
    case CIL_CONS_R1:
487
0
      o_str = "r1";
488
0
      break;
489
0
    case CIL_CONS_R2:
490
0
      o_str = "r2";
491
0
      break;
492
0
    case CIL_CONS_R3:
493
0
      o_str = "r3";
494
0
      break;
495
0
    case CIL_CONS_T1:
496
0
      o_str = "t1";
497
0
      break;
498
0
    case CIL_CONS_T2:
499
0
      o_str = "t2";
500
0
      break;
501
0
    case CIL_CONS_T3:
502
0
      o_str = "t3";
503
0
      break;
504
0
    case CIL_CONS_L1:
505
0
      o_str = "l1";
506
0
      break;
507
0
    case CIL_CONS_L2:
508
0
      o_str = "l2";
509
0
      break;
510
0
    case CIL_CONS_H1:
511
0
      o_str = "h1";
512
0
      break;
513
0
    case CIL_CONS_H2:
514
0
      o_str = "h2";
515
0
      break;
516
0
    default:
517
      /* Impossible */
518
0
      o_str = "??";
519
0
    }
520
0
    strcpy(new, o_str);
521
0
    new += 2;
522
0
  } else if (flavor == CIL_DATUM) {
523
0
    struct cil_tree_node *node = NODE(operand->data);
524
0
    if (node->flavor == CIL_USERATTRIBUTE) {
525
0
      *new++ = '{';
526
0
      new = __cil_userattribute_to_string(db, operand->data, new);
527
0
      new--;
528
0
      *new++ = '}';
529
0
    } else {
530
0
      o_str = DATUM(operand->data)->fqn;
531
0
      o_len = strlen(o_str);
532
0
      memcpy(new, o_str, o_len);
533
0
      new += o_len;
534
0
    }
535
0
  } else if (flavor == CIL_LIST) {
536
0
    *new++ = '{';
537
0
    cil_list_for_each(i1, (struct cil_list *)operand->data) {
538
0
      struct cil_tree_node *node = NODE(operand->data);
539
0
      if (node->flavor == CIL_USERATTRIBUTE) {
540
0
        new = __cil_userattribute_to_string(db, operand->data, new);
541
0
      } else {
542
0
        o_str = DATUM(operand->data)->fqn;
543
0
        o_len = strlen(o_str);
544
0
        memcpy(new, o_str, o_len);
545
0
        new += o_len;
546
0
        *new++ = ' ';
547
0
      }
548
0
    }
549
0
    new--;
550
0
    *new++ = '}';
551
0
  }
552
553
0
  return new;
554
0
}
555
556
static char *__cil_cons_leaf_op_to_string(struct cil_list_item *op, char *new)
557
0
{
558
0
  enum cil_flavor flavor = (enum cil_flavor)(uintptr_t)op->data;
559
0
  const char *op_str;
560
0
  size_t len;
561
562
0
  switch (flavor) {
563
0
  case CIL_EQ:
564
0
    op_str = " == ";
565
0
    len = 4;
566
0
    break;
567
0
  case CIL_NEQ:
568
0
    op_str = " != ";
569
0
    len = 4;
570
0
    break;
571
0
  case CIL_CONS_DOM:
572
0
    op_str = " dom ";
573
0
    len = 5;
574
0
    break;
575
0
  case CIL_CONS_DOMBY:
576
0
    op_str = " domby ";
577
0
    len = 7;
578
0
    break;
579
0
  case CIL_CONS_INCOMP:
580
0
    op_str = " incomp ";
581
0
    len = 8;
582
0
    break;
583
0
  default:
584
    /* Should be impossible to be here */
585
0
    op_str = " ??? ";
586
0
    len = 5;
587
0
  }
588
589
0
  strcpy(new, op_str);
590
0
  new += len;
591
592
0
  return new;
593
0
}
594
595
static char *__cil_cons_expr_to_string(struct cil_db *db, struct cil_list *cons_expr, char *new)
596
0
{
597
0
  struct cil_list_item *i1;
598
0
  enum cil_flavor op;
599
600
0
  i1 = cons_expr->head;
601
602
0
  op = (enum cil_flavor)(uintptr_t)i1->data;
603
0
  switch (op) {
604
0
  case CIL_NOT:
605
0
    *new++ = '(';
606
0
    strcpy(new, "not ");
607
0
    new += 4;
608
0
    new = __cil_cons_expr_to_string(db, i1->next->data, new);
609
0
    *new++ = ')';
610
0
    break;
611
0
  case CIL_AND:
612
0
    *new++ = '(';
613
0
    new = __cil_cons_expr_to_string(db, i1->next->data, new);
614
0
    strcpy(new, " and ");
615
0
    new += 5;
616
0
    new = __cil_cons_expr_to_string(db, i1->next->next->data, new);
617
0
    *new++ = ')';
618
0
    break;
619
0
  case CIL_OR:
620
0
    *new++ = '(';
621
0
    new = __cil_cons_expr_to_string(db, i1->next->data, new);
622
0
    strcpy(new, " or ");
623
0
    new += 4;
624
0
    new = __cil_cons_expr_to_string(db, i1->next->next->data, new);
625
0
    *new++ = ')';
626
0
    break;
627
0
  default:
628
0
    *new++ = '(';
629
0
    new = __cil_cons_leaf_operand_to_string(db, i1->next, new);
630
0
    new = __cil_cons_leaf_op_to_string(i1, new);
631
0
    new = __cil_cons_leaf_operand_to_string(db, i1->next->next, new);
632
0
    *new++ = ')';
633
0
  }
634
635
0
  return new;
636
0
}
637
638
static char *cil_cons_expr_to_string(struct cil_db *db, struct cil_list *cons_expr)
639
0
{
640
0
  char *new, *tail;
641
0
  size_t len = cil_cons_expr_len(db, cons_expr);
642
643
0
  new = cil_malloc(len+1);
644
0
  tail = __cil_cons_expr_to_string(db, cons_expr, new);
645
0
  *tail = '\0';
646
647
0
  return new;
648
0
}
649
650
static void cil_classperms_to_string(struct cil_classperms *classperms, struct cil_list *classperms_strs)
651
0
{
652
0
  struct cil_list_item *i1;
653
0
  size_t len = 0;
654
0
  char *new, *curr;
655
656
0
  len += strlen(DATUM(classperms->class)->fqn) + 1;
657
0
  cil_list_for_each(i1, classperms->perms) {
658
0
    len += strlen(DATUM(i1->data)->fqn) + 1;
659
0
  }
660
0
  len += 4; /* for "{ " and " }" */
661
662
0
  new = cil_malloc(len);
663
0
  curr = new;
664
665
0
  curr[len-1] = '\0';
666
667
0
  len = strlen(DATUM(classperms->class)->fqn);
668
0
  memcpy(curr, DATUM(classperms->class)->fqn, len);
669
0
  curr += len;
670
0
  *curr++ = ' ';
671
672
0
  *curr++ = '{';
673
0
  *curr++ = ' ';
674
0
  cil_list_for_each(i1, classperms->perms) {
675
0
    len = strlen(DATUM(i1->data)->fqn);
676
0
    memcpy(curr, DATUM(i1->data)->fqn, len);
677
0
    curr += len;
678
0
    *curr++ = ' ';
679
0
  }
680
0
  *curr++ = '}';
681
682
0
  cil_list_append(classperms_strs, CIL_STRING, new);
683
0
}
684
685
static void cil_classperms_to_strings(struct cil_list *classperms, struct cil_list *classperms_strs)
686
0
{
687
0
  struct cil_list_item *i1;
688
689
0
  cil_list_for_each(i1, classperms) {
690
0
    if (i1->flavor == CIL_CLASSPERMS) {
691
0
      struct cil_classperms *cp = i1->data;
692
0
      if (FLAVOR(cp->class) == CIL_CLASS) {
693
0
        cil_classperms_to_string(cp, classperms_strs);
694
0
      } else { /* MAP */
695
0
        struct cil_list_item *i2 = NULL;
696
0
        cil_list_for_each(i2, cp->perms) {
697
0
          struct cil_perm *cmp = i2->data;
698
0
          cil_classperms_to_strings(cmp->classperms, classperms_strs);
699
0
        }
700
0
      }
701
0
    } else { /* SET */
702
0
      struct cil_classperms_set *cp_set = i1->data;
703
0
      struct cil_classpermission *cp = cp_set->set;
704
0
      cil_classperms_to_strings(cp->classperms, classperms_strs);
705
0
    }
706
0
  }
707
0
}
708
709
static void cil_class_decls_to_policy(FILE *out, struct cil_list *classorder)
710
0
{
711
0
  struct cil_list_item *i1;
712
713
0
  cil_list_for_each(i1, classorder) {
714
0
    fprintf(out, "class %s\n", DATUM(i1->data)->fqn);
715
0
  }
716
0
}
717
718
static void cil_sid_decls_to_policy(FILE *out, struct cil_list *sidorder)
719
0
{
720
0
  struct cil_list_item *i1;
721
722
0
  cil_list_for_each(i1, sidorder) {
723
0
    fprintf(out, "sid %s\n", DATUM(i1->data)->fqn);
724
0
  }
725
0
}
726
727
static void cil_commons_to_policy(FILE *out, struct cil_list *commons)
728
0
{
729
0
  struct cil_list_item *i1;
730
0
  struct cil_class* common;
731
0
  struct cil_tree_node *node;
732
0
  struct cil_tree_node *perm;
733
734
0
  cil_list_for_each(i1, commons) {
735
0
    common = i1->data;
736
0
    node = NODE(&common->datum);
737
0
    perm = node->cl_head;
738
739
0
    fprintf(out, "common %s {", common->datum.fqn);
740
0
    while (perm != NULL) {
741
0
      fprintf(out, "%s ", DATUM(perm->data)->fqn);
742
0
      perm = perm->next;
743
0
    }
744
0
    fprintf(out, "}\n");
745
0
  }
746
0
}
747
748
static void cil_classes_to_policy(FILE *out, struct cil_list *classorder)
749
0
{
750
0
  struct cil_list_item *i1;
751
0
  struct cil_class *class;
752
0
  struct cil_tree_node *node;
753
754
0
  cil_list_for_each(i1, classorder) {
755
0
    class = i1->data;
756
0
    node = NODE(&class->datum);
757
758
0
    fprintf(out, "class %s", class->datum.fqn);
759
0
    if (class->common != NULL) {
760
0
      fprintf(out, " inherits %s", class->common->datum.fqn);
761
0
    }
762
0
    if (node->cl_head != NULL) {
763
0
      struct cil_tree_node *perm = node->cl_head;
764
0
      fprintf(out, " {");
765
0
      while (perm != NULL) {
766
0
        fprintf(out, " %s", DATUM(perm->data)->fqn);
767
0
        perm = perm->next;
768
0
      }
769
0
      fprintf(out, " }");
770
0
    }
771
0
    fprintf(out, "\n");
772
0
  }
773
0
}
774
775
static void cil_defaults_to_policy(FILE *out, struct cil_list *defaults, const char *kind)
776
0
{
777
0
  struct cil_list_item *i1, *i2, *i3;
778
0
  struct cil_default *def;
779
0
  struct cil_list *class_list;
780
781
0
  cil_list_for_each(i1, defaults) {
782
0
    def = i1->data;
783
0
    fprintf(out, "%s {",kind);
784
0
    cil_list_for_each(i2, def->class_datums) {
785
0
      class_list = cil_expand_class(i2->data);
786
0
      cil_list_for_each(i3, class_list) {
787
0
        fprintf(out, " %s", DATUM(i3->data)->fqn);
788
0
      }
789
0
      cil_list_destroy(&class_list, CIL_FALSE);
790
0
    }
791
0
    fprintf(out, " }");
792
0
    if (def->object == CIL_DEFAULT_SOURCE) {
793
0
      fprintf(out," %s",CIL_KEY_SOURCE);
794
0
    } else if (def->object == CIL_DEFAULT_TARGET) {
795
0
      fprintf(out," %s",CIL_KEY_TARGET);
796
0
    }
797
0
    fprintf(out,";\n");
798
0
  }
799
0
}
800
801
static void cil_default_ranges_to_policy(FILE *out, struct cil_list *defaults)
802
0
{
803
0
  struct cil_list_item *i1, *i2, *i3;
804
0
  struct cil_defaultrange *def;
805
0
  struct cil_list *class_list;
806
807
0
  cil_list_for_each(i1, defaults) {
808
0
    def = i1->data;
809
0
    fprintf(out, "default_range {");
810
0
    cil_list_for_each(i2, def->class_datums) {
811
0
      class_list = cil_expand_class(i2->data);
812
0
      cil_list_for_each(i3, class_list) {
813
0
        fprintf(out, " %s", DATUM(i3->data)->fqn);
814
0
      }
815
0
      cil_list_destroy(&class_list, CIL_FALSE);
816
0
    }
817
0
    fprintf(out, " }");
818
819
0
    switch (def->object_range) {
820
0
    case CIL_DEFAULT_SOURCE_LOW:
821
0
      fprintf(out," %s %s", CIL_KEY_SOURCE, CIL_KEY_LOW);
822
0
      break;
823
0
    case CIL_DEFAULT_SOURCE_HIGH:
824
0
      fprintf(out," %s %s", CIL_KEY_SOURCE, CIL_KEY_HIGH);
825
0
      break;
826
0
    case CIL_DEFAULT_SOURCE_LOW_HIGH:
827
0
      fprintf(out," %s %s", CIL_KEY_SOURCE, CIL_KEY_LOW_HIGH);
828
0
      break;
829
0
    case CIL_DEFAULT_TARGET_LOW:
830
0
      fprintf(out," %s %s", CIL_KEY_TARGET, CIL_KEY_LOW);
831
0
      break;
832
0
    case CIL_DEFAULT_TARGET_HIGH:
833
0
      fprintf(out," %s %s", CIL_KEY_TARGET, CIL_KEY_HIGH);
834
0
      break;
835
0
    case CIL_DEFAULT_TARGET_LOW_HIGH:
836
0
      fprintf(out," %s %s", CIL_KEY_TARGET, CIL_KEY_LOW_HIGH);
837
0
      break;
838
0
    case CIL_DEFAULT_GLBLUB:
839
0
      fprintf(out," %s", CIL_KEY_GLBLUB);
840
0
      break;
841
0
    default:
842
0
      break;
843
0
    }
844
0
    fprintf(out,";\n");
845
0
  }
846
0
}
847
848
static void cil_sensitivities_to_policy(FILE *out, struct cil_list *sensorder, struct cil_list *all_aliases)
849
0
{
850
0
  struct cil_list_item *i1, *i2;
851
0
  struct cil_sens *sens;
852
0
  struct cil_list *aliases = NULL;
853
0
  struct cil_alias *alias;
854
0
  struct cil_sens *actual;
855
0
  int num_aliases;
856
857
0
  cil_list_for_each(i1, sensorder) {
858
0
    sens = i1->data;
859
0
    num_aliases = 0;
860
0
    cil_list_for_each(i2, all_aliases) {
861
0
      alias = i2->data;
862
0
      actual = alias->actual;
863
0
      if (sens == actual) {
864
0
        if (num_aliases == 0) {
865
0
          cil_list_init(&aliases, CIL_LIST);
866
0
        }
867
0
        cil_list_append(aliases, CIL_SENSALIAS, alias);
868
0
        num_aliases++;
869
0
      }
870
0
    }
871
0
    fprintf(out, "sensitivity %s", sens->datum.fqn);
872
0
    if (num_aliases > 0) {
873
0
      fprintf(out, " alias");
874
0
      if (num_aliases > 1) {
875
0
        fprintf(out, " {");
876
0
      }
877
0
      cil_list_for_each(i2, aliases) {
878
0
        alias = i2->data;
879
0
        fprintf(out, " %s", alias->datum.fqn);
880
0
      }
881
0
      if (num_aliases > 1) {
882
0
        fprintf(out, " }");
883
0
      }
884
0
      cil_list_destroy(&aliases, CIL_FALSE);
885
0
    }
886
0
    fprintf(out, ";\n");
887
0
  }
888
0
}
889
890
static void cil_dominance_to_policy(FILE *out, struct cil_list *sensorder)
891
0
{
892
0
  struct cil_list_item *item;
893
0
  struct cil_sens *sens;
894
895
0
  fprintf(out, "dominance {");
896
0
  cil_list_for_each(item, sensorder) {
897
0
    sens = item->data;
898
0
    fprintf(out, " %s", sens->datum.fqn);
899
0
  }
900
0
  fprintf(out, " }\n");
901
0
}
902
903
static void cil_categories_to_policy(FILE *out, struct cil_list *catorder, struct cil_list *all_aliases)
904
0
{
905
0
  struct cil_list_item *i1, *i2;
906
0
  struct cil_sens *cat;
907
0
  struct cil_list *aliases = NULL;
908
0
  struct cil_alias *alias;
909
0
  struct cil_sens *actual;
910
0
  int num_aliases;
911
912
0
  cil_list_for_each(i1, catorder) {
913
0
    cat = i1->data;
914
0
    num_aliases = 0;
915
0
    cil_list_for_each(i2, all_aliases) {
916
0
      alias = i2->data;
917
0
      actual = alias->actual;
918
0
      if (cat == actual) {
919
0
        if (num_aliases == 0) {
920
0
          cil_list_init(&aliases, CIL_LIST);
921
0
        }
922
0
        cil_list_append(aliases, CIL_CATALIAS, alias);
923
0
        num_aliases++;
924
0
      }
925
0
    }
926
0
    fprintf(out, "category %s",cat->datum.fqn);
927
0
    if (num_aliases > 0) {
928
0
      fprintf(out, " alias");
929
0
      if (num_aliases > 1) {
930
0
        fprintf(out, " { ");
931
0
      }
932
0
      cil_list_for_each(i2, aliases) {
933
0
        alias = i2->data;
934
0
        fprintf(out, " %s", alias->datum.fqn);
935
0
      }
936
0
      if (num_aliases > 1) {
937
0
        fprintf(out, " }");
938
0
      }
939
0
      cil_list_destroy(&aliases, CIL_FALSE);
940
0
    }
941
0
    fprintf(out, ";\n");
942
0
  }
943
0
}
944
945
static void cil_levels_to_policy(FILE *out, struct cil_list *sensorder)
946
0
{
947
0
  struct cil_list_item *i1, *i2;
948
0
  struct cil_sens *sens;
949
950
0
  cil_list_for_each(i1, sensorder) {
951
0
    sens = i1->data;
952
0
    if (sens->cats_list) {
953
0
      cil_list_for_each(i2, sens->cats_list) {
954
0
        fprintf(out, "level %s:",sens->datum.fqn);
955
0
        cil_cats_to_policy(out, i2->data);
956
0
        fprintf(out,";\n");
957
0
      }
958
0
    } else {
959
0
      fprintf(out, "level %s;\n",sens->datum.fqn);
960
0
    }
961
0
  }
962
0
}
963
964
static void cil_mlsconstrains_to_policy(FILE *out, struct cil_db *db, struct cil_list *mlsconstrains)
965
0
{
966
0
  struct cil_list_item *i1, *i2;
967
0
  struct cil_constrain *cons;
968
0
  struct cil_list *classperms_strs;
969
0
  char *cp_str;
970
0
  char *expr_str;
971
972
0
  cil_list_for_each(i1, mlsconstrains) {
973
0
    cons = i1->data;
974
0
    cil_list_init(&classperms_strs, CIL_LIST);
975
0
    cil_classperms_to_strings(cons->classperms, classperms_strs);
976
0
    expr_str = cil_cons_expr_to_string(db, cons->datum_expr);
977
0
    cil_list_for_each(i2, classperms_strs) {
978
0
      cp_str = i2->data;
979
0
      fprintf(out, "mlsconstrain %s %s;\n", cp_str, expr_str);
980
0
      free(cp_str);
981
0
    }
982
0
    free(expr_str);
983
0
    cil_list_destroy(&classperms_strs, CIL_FALSE);
984
0
  }
985
0
}
986
987
static void cil_validatetrans_to_policy(FILE *out, struct cil_db *db, struct cil_list *validatetrans, char *kind)
988
0
{
989
0
  struct cil_list_item *i1, *i2;
990
0
  struct cil_validatetrans *trans;
991
0
  struct cil_list *class_list;
992
0
  struct cil_class *class;
993
0
  char *expr_str;
994
995
0
  cil_list_for_each(i1, validatetrans) {
996
0
    trans = i1->data;
997
0
    class_list = cil_expand_class(trans->class);
998
0
    expr_str = cil_cons_expr_to_string(db, trans->datum_expr);
999
0
    cil_list_for_each(i2, class_list) {
1000
0
      class = i2->data;
1001
0
      fprintf(out, "%s %s %s;\n", kind, class->datum.fqn, expr_str);
1002
0
    }
1003
0
    free(expr_str);
1004
0
    cil_list_destroy(&class_list, CIL_FALSE);
1005
0
  }
1006
0
}
1007
1008
static void cil_bools_to_policy(FILE *out, struct cil_list *bools)
1009
0
{
1010
0
  struct cil_list_item *i1;
1011
0
  struct cil_bool *boolean;
1012
0
  const char *value;
1013
1014
0
  cil_list_for_each(i1, bools) {
1015
0
    boolean = i1->data;
1016
0
    value = boolean->value ? "true" : "false";
1017
0
    fprintf(out, "bool %s %s;\n", boolean->datum.fqn, value);
1018
0
  }
1019
0
}
1020
1021
static void cil_typealiases_to_policy(FILE *out, struct cil_list *types, struct cil_list *all_aliases)
1022
0
{
1023
0
  struct cil_list_item *i1, *i2;
1024
0
  struct cil_type *type;
1025
0
  struct cil_list *aliases = NULL;
1026
0
  struct cil_alias *alias;
1027
0
  struct cil_type *actual;
1028
0
  int num_aliases;
1029
1030
0
  cil_list_for_each(i1, types) {
1031
0
    type = i1->data;
1032
0
    num_aliases = 0;
1033
0
    cil_list_for_each(i2, all_aliases) {
1034
0
      alias = i2->data;
1035
0
      actual = alias->actual;
1036
0
      if (type == actual) {
1037
0
        if (num_aliases == 0) {
1038
0
          cil_list_init(&aliases, CIL_LIST);
1039
0
        }
1040
0
        cil_list_append(aliases, CIL_TYPEALIAS, alias);
1041
0
        num_aliases++;
1042
0
      }
1043
0
    }
1044
0
    if (num_aliases > 0) {
1045
0
      fprintf(out, "typealias %s alias", type->datum.fqn);
1046
0
      if (num_aliases > 1) {
1047
0
        fprintf(out, " {");
1048
0
      }
1049
0
      cil_list_for_each(i2, aliases) {
1050
0
        alias = i2->data;
1051
0
        fprintf(out, " %s", alias->datum.fqn);
1052
0
      }
1053
0
      if (num_aliases > 1) {
1054
0
        fprintf(out, " }");
1055
0
      }
1056
0
      fprintf(out, ";\n");
1057
0
      cil_list_destroy(&aliases, CIL_FALSE);
1058
0
    }
1059
0
  }
1060
0
}
1061
1062
static void cil_typebounds_to_policy(FILE *out, struct cil_list *types)
1063
0
{
1064
0
  struct cil_list_item *i1;
1065
0
  struct cil_type *child;
1066
0
  struct cil_type *parent;
1067
1068
0
  cil_list_for_each(i1, types) {
1069
0
    child = i1->data;
1070
0
    if (child->bounds != NULL) {
1071
0
      parent = child->bounds;
1072
0
      fprintf(out, "typebounds %s %s;\n", parent->datum.fqn, child->datum.fqn);
1073
0
    }
1074
0
  }
1075
0
}
1076
1077
static void cil_typeattributes_to_policy(FILE *out, struct cil_list *types, struct cil_list *attributes)
1078
0
{
1079
0
  struct cil_list_item *i1, *i2;
1080
0
  struct cil_type *type;
1081
0
  struct cil_typeattribute *attribute;
1082
0
  int first = CIL_TRUE;
1083
1084
0
  cil_list_for_each(i1, types) {
1085
0
    type = i1->data;
1086
0
    cil_list_for_each(i2, attributes) {
1087
0
      attribute = i2->data;
1088
0
      if (!attribute->keep)
1089
0
        continue;
1090
0
      if (ebitmap_get_bit(attribute->types, type->value)) {
1091
0
        if (first) {
1092
0
          fprintf(out, "typeattribute %s %s", type->datum.fqn, attribute->datum.fqn);
1093
0
          first = CIL_FALSE;
1094
0
        } else {
1095
0
          fprintf(out, ", %s", attribute->datum.fqn);
1096
0
        }
1097
0
      }
1098
0
    }
1099
0
    if (!first) {
1100
0
      fprintf(out, ";\n");
1101
0
      first = CIL_TRUE;
1102
0
    }
1103
0
  }
1104
0
}
1105
1106
static void cil_xperms_to_policy(FILE *out, struct cil_permissionx *permx)
1107
0
{
1108
0
  ebitmap_node_t *node;
1109
0
  unsigned int i, first = 0, last = 0;
1110
0
  int need_first = CIL_TRUE, need_last = CIL_TRUE;
1111
0
  const char *kind;
1112
1113
0
  if (permx->kind == CIL_PERMX_KIND_IOCTL) {
1114
0
    kind = "ioctl";
1115
0
  } else if (permx->kind == CIL_PERMX_KIND_NLMSG) {
1116
0
    kind = "nlmsg";
1117
0
  } else {
1118
0
    kind = "???";
1119
0
  }
1120
1121
0
  fprintf(out, "%s %s {", DATUM(permx->obj)->fqn, kind);
1122
1123
0
  ebitmap_for_each_positive_bit(permx->perms, node, i) {
1124
0
    if (need_first == CIL_TRUE) {
1125
0
      first = i;
1126
0
      need_first = CIL_FALSE;
1127
0
    } else if (need_last == CIL_TRUE) {
1128
0
      if (i == first+1) {
1129
0
        last = i;
1130
0
        need_last = CIL_FALSE;
1131
0
      } else {
1132
0
        fprintf(out, " 0x%x", first);
1133
0
        first = i;
1134
0
      }
1135
0
    } else if (i == last+1) {
1136
0
      last = i;
1137
0
    } else {
1138
0
      if (last > first+1) {
1139
0
        fprintf(out, " 0x%x-0x%x", first, last);
1140
0
      } else {
1141
0
        fprintf(out, " 0x%x 0x%x", first, last);
1142
0
      }
1143
0
      first = i;
1144
0
      need_last = CIL_TRUE;
1145
0
    }
1146
0
  }
1147
0
  if (need_first == CIL_FALSE) {
1148
0
    if (need_last == CIL_FALSE) {
1149
0
      fprintf(out, " 0x%x-0x%x", first, last);
1150
0
    } else {
1151
0
      fprintf(out, " 0x%x", first);
1152
0
    }
1153
0
  }
1154
0
  fprintf(out," }");
1155
0
}
1156
1157
static void cil_av_rulex_to_policy(FILE *out, struct cil_avrule *rule)
1158
0
{
1159
0
  const char *kind;
1160
0
  struct cil_symtab_datum *src, *tgt;
1161
1162
0
  src = rule->src;
1163
0
  tgt = rule->tgt;
1164
1165
0
  switch (rule->rule_kind) {
1166
0
  case CIL_AVRULE_ALLOWED:
1167
0
    kind = "allowxperm";
1168
0
    break;
1169
0
  case CIL_AVRULE_AUDITALLOW:
1170
0
    kind = "auditallowxperm";
1171
0
    break;
1172
0
  case CIL_AVRULE_DONTAUDIT:
1173
0
    kind = "dontauditxperm";
1174
0
    break;
1175
0
  case CIL_AVRULE_NEVERALLOW:
1176
0
    kind = "neverallowxperm";
1177
0
    break;
1178
0
  default:
1179
0
    kind = "???";
1180
0
    break;
1181
0
  }
1182
1183
0
  fprintf(out, "%s %s %s : ", kind, src->fqn, tgt->fqn);
1184
0
  cil_xperms_to_policy(out, rule->perms.x.permx);
1185
0
  fprintf(out, ";\n");
1186
0
}
1187
1188
static void cil_av_rule_to_policy(FILE *out, struct cil_avrule *rule)
1189
0
{
1190
0
  const char *kind;
1191
0
  struct cil_symtab_datum *src, *tgt;
1192
0
  struct cil_list *classperms_strs;
1193
0
  struct cil_list_item *i1;
1194
1195
0
  src = rule->src;
1196
0
  tgt = rule->tgt;
1197
1198
0
  switch (rule->rule_kind) {
1199
0
  case CIL_AVRULE_ALLOWED:
1200
0
    kind = "allow";
1201
0
    break;
1202
0
  case CIL_AVRULE_AUDITALLOW:
1203
0
    kind = "auditallow";
1204
0
    break;
1205
0
  case CIL_AVRULE_DONTAUDIT:
1206
0
    kind = "dontaudit";
1207
0
    break;
1208
0
  case CIL_AVRULE_NEVERALLOW:
1209
0
    kind = "neverallow";
1210
0
    break;
1211
0
  default:
1212
0
    kind = "???";
1213
0
    break;
1214
0
  }
1215
1216
0
  cil_list_init(&classperms_strs, CIL_LIST);
1217
0
  cil_classperms_to_strings(rule->perms.classperms, classperms_strs);
1218
0
  cil_list_for_each(i1, classperms_strs) {
1219
0
    char *cp_str = i1->data;
1220
0
    fprintf(out, "%s %s %s : %s;\n", kind, src->fqn, tgt->fqn, cp_str);
1221
0
    free(cp_str);
1222
0
  }
1223
0
  cil_list_destroy(&classperms_strs, CIL_FALSE);
1224
0
}
1225
1226
static void cil_type_rule_to_policy(FILE *out, struct cil_type_rule *rule)
1227
0
{
1228
0
  const char *kind;
1229
0
  struct cil_symtab_datum *src, *tgt, *res;
1230
0
  struct cil_list *class_list;
1231
0
  struct cil_list_item *i1;
1232
1233
0
  src = rule->src;
1234
0
  tgt = rule->tgt;
1235
0
  res = rule->result;
1236
1237
0
  switch (rule->rule_kind) {
1238
0
  case CIL_TYPE_TRANSITION:
1239
0
    kind = "type_transition";
1240
0
    break;
1241
0
  case CIL_TYPE_MEMBER:
1242
0
    kind = "type_member";
1243
0
    break;
1244
0
  case CIL_TYPE_CHANGE:
1245
0
    kind = "type_change";
1246
0
    break;
1247
0
  default:
1248
0
    kind = "???";
1249
0
    break;
1250
0
  }
1251
1252
0
  class_list = cil_expand_class(rule->obj);
1253
0
  cil_list_for_each(i1, class_list) {
1254
0
    fprintf(out, "%s %s %s : %s %s;\n", kind, src->fqn, tgt->fqn, DATUM(i1->data)->fqn, res->fqn);
1255
0
  }
1256
0
  cil_list_destroy(&class_list, CIL_FALSE);
1257
0
}
1258
1259
static void cil_nametypetransition_to_policy(FILE *out, struct cil_nametypetransition *trans)
1260
0
{
1261
0
  struct cil_symtab_datum *src, *tgt, *name, *res;
1262
0
  struct cil_list *class_list;
1263
0
  struct cil_list_item *i1;
1264
1265
0
  src = trans->src;
1266
0
  tgt = trans->tgt;
1267
0
  name = trans->name;
1268
0
  res = trans->result;
1269
1270
0
  class_list = cil_expand_class(trans->obj);
1271
0
  cil_list_for_each(i1, class_list) {
1272
0
    fprintf(out, "type_transition %s %s : %s %s \"%s\";\n", src->fqn, tgt->fqn, DATUM(i1->data)->fqn, res->fqn, name->fqn);
1273
0
  }
1274
0
  cil_list_destroy(&class_list, CIL_FALSE);
1275
0
}
1276
1277
static void cil_rangetransition_to_policy(FILE *out, struct cil_rangetransition *trans)
1278
0
{
1279
0
  struct cil_symtab_datum *src, *exec;
1280
0
  struct cil_list *class_list;
1281
0
  struct cil_list_item *i1;
1282
1283
0
  src = trans->src;
1284
0
  exec = trans->exec;
1285
1286
0
  class_list = cil_expand_class(trans->obj);
1287
0
  cil_list_for_each(i1, class_list) {
1288
0
    fprintf(out, "range_transition %s %s : %s ", src->fqn, exec->fqn, DATUM(i1->data)->fqn);
1289
0
    cil_levelrange_to_policy(out, trans->range);
1290
0
    fprintf(out, ";\n");
1291
0
  }
1292
0
  cil_list_destroy(&class_list, CIL_FALSE);
1293
0
}
1294
1295
static void cil_typepermissive_to_policy(FILE *out, struct cil_typepermissive *rule)
1296
0
{
1297
0
  fprintf(out, "permissive %s;\n", DATUM(rule->type)->fqn);
1298
0
}
1299
1300
static void cil_typeneveraudit_to_policy(FILE *out, struct cil_typeneveraudit *rule)
1301
0
{
1302
0
  fprintf(out, "neveraudit %s;\n", DATUM(rule->type)->fqn);
1303
0
}
1304
1305
struct block_te_rules_extra {
1306
  FILE *out;
1307
  enum cil_flavor flavor;
1308
  uint32_t rule_kind;
1309
};
1310
1311
static int __cil_block_te_rules_to_policy_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args)
1312
0
{
1313
0
  struct block_te_rules_extra *args = extra_args;
1314
1315
0
  switch (node->flavor) {
1316
0
  case CIL_BLOCK: {
1317
0
    struct cil_block *blk = node->data;
1318
0
    if (blk->is_abstract == CIL_TRUE) {
1319
0
      *finished = CIL_TREE_SKIP_HEAD;
1320
0
    }
1321
0
    break;
1322
0
  }
1323
0
  case CIL_MACRO:
1324
0
    *finished = CIL_TREE_SKIP_HEAD;
1325
0
    break;
1326
0
  case CIL_BOOLEANIF:
1327
0
    *finished = CIL_TREE_SKIP_HEAD;
1328
0
    break;
1329
0
  case CIL_AVRULE:
1330
0
  case CIL_AVRULEX:
1331
0
    if (args->flavor == node->flavor) {
1332
0
      struct cil_avrule *rule = node->data;
1333
0
      if (args->rule_kind == rule->rule_kind) {
1334
0
        if (rule->is_extended) {
1335
0
          cil_av_rulex_to_policy(args->out, rule);
1336
0
        } else {
1337
0
          cil_av_rule_to_policy(args->out, rule);
1338
0
        }
1339
0
      }
1340
0
    }
1341
0
    break;
1342
0
  case CIL_TYPE_RULE:
1343
0
    if (args->flavor == node->flavor) {
1344
0
      struct cil_type_rule *rule = node->data;
1345
0
      if (args->rule_kind == rule->rule_kind) {
1346
0
        cil_type_rule_to_policy(args->out, rule);
1347
0
      }
1348
0
    }
1349
1350
0
    break;
1351
0
  case CIL_NAMETYPETRANSITION:
1352
0
    if (args->flavor == node->flavor) {
1353
0
      cil_nametypetransition_to_policy(args->out, node->data);
1354
0
    }
1355
0
    break;
1356
0
  case CIL_RANGETRANSITION:
1357
0
    if (args->flavor == node->flavor) {
1358
0
      cil_rangetransition_to_policy(args->out, node->data);
1359
0
    }
1360
1361
0
    break;
1362
0
  case CIL_TYPEPERMISSIVE:
1363
0
    if (args->flavor == node->flavor) {
1364
0
      cil_typepermissive_to_policy(args->out, node->data);
1365
0
    }
1366
0
    break;
1367
0
  case CIL_TYPENEVERAUDIT:
1368
0
    if (args->flavor == node->flavor) {
1369
0
      cil_typeneveraudit_to_policy(args->out, node->data);
1370
0
    }
1371
0
    break;
1372
0
  default:
1373
0
    break;
1374
0
  }
1375
1376
0
  return SEPOL_OK;
1377
0
}
1378
1379
static void cil_block_te_rules_to_policy(FILE *out, struct cil_tree_node *start, int mls)
1380
0
{
1381
0
  struct block_te_rules_extra args;
1382
1383
0
  args.out = out;
1384
1385
0
  args.flavor = CIL_TYPEPERMISSIVE;
1386
0
  args.rule_kind = 0;
1387
0
  cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1388
1389
0
  args.flavor = CIL_TYPENEVERAUDIT;
1390
0
  args.rule_kind = 0;
1391
0
  cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1392
1393
0
  args.flavor = CIL_AVRULE;
1394
0
  args.rule_kind = CIL_AVRULE_ALLOWED;
1395
0
  cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1396
0
  args.rule_kind = CIL_AVRULE_AUDITALLOW;
1397
0
  cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1398
0
  args.rule_kind = CIL_AVRULE_DONTAUDIT;
1399
0
  cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1400
0
  args.rule_kind = CIL_AVRULE_NEVERALLOW;
1401
0
  cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1402
1403
0
  args.flavor = CIL_AVRULEX;
1404
0
  args.rule_kind = CIL_AVRULE_ALLOWED;
1405
0
  cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1406
0
  args.rule_kind = CIL_AVRULE_AUDITALLOW;
1407
0
  cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1408
0
  args.rule_kind = CIL_AVRULE_DONTAUDIT;
1409
0
  cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1410
0
  args.rule_kind = CIL_AVRULE_NEVERALLOW;
1411
0
  cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1412
1413
0
  args.flavor = CIL_TYPE_RULE;
1414
0
  args.rule_kind = CIL_TYPE_TRANSITION;
1415
0
  cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1416
0
  args.rule_kind = CIL_TYPE_MEMBER;
1417
0
  cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1418
0
  args.rule_kind = CIL_TYPE_CHANGE;
1419
0
  cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1420
0
  args.rule_kind = CIL_AVRULE_TYPE;
1421
0
  cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1422
1423
0
  args.flavor = CIL_NAMETYPETRANSITION;
1424
0
  args.rule_kind = 0;
1425
0
  cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1426
1427
0
  if (mls == CIL_TRUE) {
1428
0
    args.flavor = CIL_RANGETRANSITION;
1429
0
    args.rule_kind = 0;
1430
0
    cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1431
0
  }
1432
0
}
1433
1434
struct te_rules_extra {
1435
  FILE *out;
1436
  int mls;
1437
};
1438
1439
static int __cil_te_rules_to_policy_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args)
1440
0
{
1441
0
  struct te_rules_extra *args = extra_args;
1442
1443
0
  switch (node->flavor) {
1444
0
  case CIL_BLOCK: {
1445
0
    struct cil_block *blk = node->data;
1446
0
    if (blk->is_abstract == CIL_TRUE) {
1447
0
      *finished = CIL_TREE_SKIP_HEAD;
1448
0
    }
1449
0
    break;
1450
0
  }
1451
0
  case CIL_MACRO:
1452
0
    *finished = CIL_TREE_SKIP_HEAD;
1453
0
    break;
1454
0
  case CIL_BOOLEANIF: {
1455
0
    struct cil_booleanif *boolean = node->data;
1456
0
    struct cil_tree_node *n;
1457
0
    struct cil_condblock *cb;
1458
1459
0
    fprintf(args->out, "if ");
1460
0
    cil_cond_expr_to_policy(args->out, boolean->datum_expr, CIL_TRUE);
1461
0
    fprintf(args->out," {\n");
1462
0
    n = node->cl_head;
1463
0
    cb = n != NULL ? n->data : NULL;
1464
0
    if (cb && cb->flavor == CIL_CONDTRUE) {
1465
0
      cil_block_te_rules_to_policy(args->out, n, args->mls);
1466
0
      n = n->next;
1467
0
      cb = n != NULL ? n->data : NULL;
1468
0
    }
1469
0
    if (cb && cb->flavor == CIL_CONDFALSE) {
1470
0
      fprintf(args->out,"} else {\n");
1471
0
      cil_block_te_rules_to_policy(args->out, n, args->mls);
1472
0
    }
1473
0
    fprintf(args->out,"}\n");
1474
0
    *finished = CIL_TREE_SKIP_HEAD;
1475
0
    break;
1476
0
  }
1477
0
  default:
1478
0
    break;
1479
0
  }
1480
1481
0
  return SEPOL_OK;
1482
0
}
1483
1484
static void cil_te_rules_to_policy(FILE *out, struct cil_tree_node *head, int mls)
1485
0
{
1486
0
  struct te_rules_extra args;
1487
1488
0
  args.out = out;
1489
0
  args.mls = mls;
1490
1491
0
  cil_block_te_rules_to_policy(out, head, mls);
1492
0
  cil_tree_walk(head, __cil_te_rules_to_policy_helper, NULL, NULL, &args);
1493
0
}
1494
1495
static void cil_roles_to_policy(FILE *out, struct cil_list *rules)
1496
0
{
1497
0
  struct cil_list_item *i1;
1498
0
  struct cil_role *role;
1499
1500
0
  cil_list_for_each(i1, rules) {
1501
0
    role = i1->data;
1502
0
    if (strcmp(role->datum.fqn,"object_r") == 0)
1503
0
      continue;
1504
0
    fprintf(out, "role %s;\n", role->datum.fqn);
1505
0
  }
1506
0
}
1507
1508
static void cil_role_types_to_policy(FILE *out, struct cil_list *roles, struct cil_list *types)
1509
0
{
1510
0
  struct cil_list_item *i1, *i2;
1511
0
  struct cil_role *role;
1512
0
  struct cil_type *type;
1513
0
  int first = CIL_TRUE;
1514
1515
0
  cil_list_for_each(i1, roles) {
1516
0
    role = i1->data;
1517
0
    if (strcmp(role->datum.fqn,"object_r") == 0)
1518
0
      continue;
1519
0
    if (role->types) {
1520
0
      cil_list_for_each(i2, types) {
1521
0
        type = i2->data;
1522
0
        if (ebitmap_get_bit(role->types, type->value)) {
1523
0
          if (first) {
1524
0
            fprintf(out, "role %s types { %s", role->datum.fqn, type->datum.fqn);
1525
0
            first = CIL_FALSE;
1526
0
          } else {
1527
0
            fprintf(out, " %s", type->datum.fqn);
1528
0
          }
1529
0
        }
1530
0
      }
1531
0
      if (!first) {
1532
0
        fprintf(out, " }");
1533
0
        first = CIL_TRUE;
1534
0
      }
1535
0
      fprintf(out, ";\n");
1536
0
    }
1537
0
  }
1538
0
}
1539
1540
static void cil_roleattributes_to_policy(FILE *out, struct cil_list *roles, struct cil_list *attributes)
1541
0
{
1542
0
  struct cil_list_item *i1, *i2;
1543
0
  struct cil_role *role;
1544
0
  struct cil_roleattribute *attribute;
1545
0
  int first = CIL_TRUE;
1546
1547
0
  cil_list_for_each(i1, roles) {
1548
0
    role = i1->data;
1549
0
    if (strcmp(role->datum.fqn,"object_r") == 0)
1550
0
      continue;
1551
0
    cil_list_for_each(i2, attributes) {
1552
0
      attribute = i2->data;
1553
0
      if (ebitmap_get_bit(attribute->roles, role->value)) {
1554
0
        if (first) {
1555
0
          fprintf(out, "roleattribute %s %s", role->datum.fqn, attribute->datum.fqn);
1556
0
          first = CIL_FALSE;
1557
0
        } else {
1558
0
          fprintf(out, ", %s", attribute->datum.fqn);
1559
0
        }
1560
0
      }
1561
0
    }
1562
0
    if (!first) {
1563
0
      fprintf(out, ";\n");
1564
0
      first = CIL_TRUE;
1565
0
    }
1566
0
  }
1567
0
}
1568
1569
static void cil_roleallows_to_policy(FILE *out, struct cil_list *roleallows)
1570
0
{
1571
0
  struct cil_list_item *i1;
1572
0
  struct cil_roleallow *allow;
1573
1574
0
  cil_list_for_each(i1, roleallows) {
1575
0
    allow = i1->data;
1576
0
    fprintf(out, "allow %s %s;\n", DATUM(allow->src)->fqn, DATUM(allow->tgt)->fqn);
1577
0
  }
1578
0
}
1579
1580
static void cil_roletransitions_to_policy(FILE *out, struct cil_list *roletransitions)
1581
0
{
1582
0
  struct cil_list_item *i1, *i2;
1583
0
  struct cil_list *class_list;
1584
0
  struct cil_roletransition *trans;
1585
1586
1587
0
  cil_list_for_each(i1, roletransitions) {
1588
0
    trans = i1->data;
1589
0
    class_list = cil_expand_class(trans->obj);
1590
0
    cil_list_for_each(i2, class_list) {
1591
0
      fprintf(out, "role_transition %s %s : %s %s;\n", DATUM(trans->src)->fqn, DATUM(trans->tgt)->fqn, DATUM(i2->data)->fqn, DATUM(trans->result)->fqn);
1592
0
    }
1593
0
    cil_list_destroy(&class_list, CIL_FALSE);
1594
0
  }
1595
0
}
1596
1597
static void cil_users_to_policy(FILE *out, int mls, struct cil_list *users, struct cil_list *all_roles)
1598
0
{
1599
0
  struct cil_list_item *i1, *i2;
1600
0
  struct cil_user *user;
1601
0
  struct cil_list *roles = NULL;
1602
0
  struct cil_role *role;
1603
0
  int num_roles;
1604
1605
0
  cil_list_for_each(i1, users) {
1606
0
    user = i1->data;
1607
0
    num_roles = 0;
1608
0
    fprintf(out, "user %s",user->datum.fqn);
1609
0
    cil_list_for_each(i2, all_roles) {
1610
0
      role = i2->data;
1611
0
      if (ebitmap_get_bit(user->roles, role->value)) {
1612
0
        if (num_roles == 0) {
1613
0
          cil_list_init(&roles, CIL_LIST);
1614
0
        }
1615
0
        cil_list_append(roles, CIL_ROLE, role);
1616
0
        num_roles++;
1617
0
      }
1618
0
    }
1619
0
    if (num_roles > 0) {
1620
0
      fprintf(out, " roles");
1621
0
      if (num_roles > 1) {
1622
0
        fprintf(out, " {");
1623
0
      }
1624
0
      cil_list_for_each(i2, roles) {
1625
0
        role = i2->data;
1626
0
        fprintf(out, " %s", role->datum.fqn);
1627
0
      }
1628
0
      if (num_roles > 1) {
1629
0
        fprintf(out, " }");
1630
0
      }
1631
0
      cil_list_destroy(&roles, CIL_FALSE);
1632
0
    }
1633
1634
0
    if (mls == CIL_TRUE && user->dftlevel != NULL) {
1635
0
      fprintf(out, " level ");
1636
0
      cil_level_to_policy(out, user->dftlevel);
1637
0
    }
1638
1639
0
    if (mls == CIL_TRUE && user->range != NULL) {
1640
0
      fprintf(out, " range ");
1641
0
      cil_levelrange_to_policy(out, user->range);
1642
0
    }
1643
1644
0
    fprintf(out,";\n");
1645
0
  }
1646
0
}
1647
1648
static void cil_constrains_to_policy(FILE *out, struct cil_db *db, struct cil_list *constrains)
1649
0
{
1650
0
  struct cil_list_item *i1, *i2;
1651
0
  struct cil_constrain *cons;
1652
0
  struct cil_list *classperms_strs;
1653
0
  char *cp_str;
1654
0
  char *expr_str;
1655
1656
0
  cil_list_for_each(i1, constrains) {
1657
0
    cons = i1->data;
1658
0
    cil_list_init(&classperms_strs, CIL_LIST);
1659
0
    cil_classperms_to_strings(cons->classperms, classperms_strs);
1660
0
    expr_str = cil_cons_expr_to_string(db, cons->datum_expr);
1661
0
    cil_list_for_each(i2, classperms_strs) {
1662
0
      cp_str = i2->data;
1663
0
      fprintf(out, "constrain %s %s;\n",cp_str, expr_str);
1664
0
      free(cp_str);
1665
0
    }
1666
0
    free(expr_str);
1667
0
    cil_list_destroy(&classperms_strs, CIL_FALSE);
1668
0
  }
1669
0
}
1670
1671
static void cil_sid_contexts_to_policy(FILE *out, struct cil_list *sids, int mls)
1672
0
{
1673
0
  struct cil_list_item *i1;
1674
0
  struct cil_sid *sid;
1675
1676
0
  cil_list_for_each(i1, sids) {
1677
0
    sid = i1->data;
1678
0
    if (sid->context) {
1679
0
      fprintf(out, "sid %s ", sid->datum.fqn);
1680
0
      cil_context_to_policy(out, sid->context, mls);
1681
0
      fprintf(out,"\n");
1682
0
    }
1683
0
  }
1684
0
}
1685
1686
static void cil_fsuses_to_policy(FILE *out, struct cil_sort *fsuses, int mls)
1687
0
{
1688
0
  unsigned i;
1689
0
  struct cil_fsuse *fsuse;
1690
1691
0
  for (i=0; i<fsuses->count; i++) {
1692
0
    fsuse = fsuses->array[i];
1693
0
    if (fsuse->type == CIL_FSUSE_XATTR) {
1694
0
      fprintf(out, "fs_use_xattr %s ", fsuse->fs_str);
1695
0
      cil_context_to_policy(out, fsuse->context, mls);
1696
0
      fprintf(out,";\n");
1697
0
    }
1698
0
  }
1699
1700
0
  for (i=0; i<fsuses->count; i++) {
1701
0
    fsuse = fsuses->array[i];
1702
0
    if (fsuse->type == CIL_FSUSE_TASK) {
1703
0
      fprintf(out, "fs_use_task %s ", fsuse->fs_str);
1704
0
      cil_context_to_policy(out, fsuse->context, mls);
1705
0
      fprintf(out,";\n");
1706
0
    }
1707
0
  }
1708
1709
0
  for (i=0; i<fsuses->count; i++) {
1710
0
    fsuse = fsuses->array[i];
1711
0
    if (fsuse->type == CIL_FSUSE_TRANS) {
1712
0
      fprintf(out, "fs_use_trans %s ", fsuse->fs_str);
1713
0
      cil_context_to_policy(out, fsuse->context, mls);
1714
0
      fprintf(out,";\n");
1715
0
    }
1716
0
  }
1717
0
}
1718
1719
static void cil_genfscons_to_policy(FILE *out, struct cil_sort *genfscons, int mls)
1720
0
{
1721
0
  unsigned i;
1722
0
  struct cil_genfscon *genfscon;
1723
1724
0
  for (i=0; i<genfscons->count; i++) {
1725
0
    genfscon = genfscons->array[i];
1726
0
    fprintf(out, "genfscon %s %s ", genfscon->fs_str, genfscon->path_str);
1727
0
    cil_context_to_policy(out, genfscon->context, mls);
1728
0
    fprintf(out, "\n");
1729
0
  }
1730
0
}
1731
1732
static void cil_ibpkeycons_to_policy(FILE *out, struct cil_sort *ibpkeycons, int mls)
1733
0
{
1734
0
  uint32_t i = 0;
1735
1736
0
  for (i = 0; i < ibpkeycons->count; i++) {
1737
0
    struct cil_ibpkeycon *ibpkeycon = (struct cil_ibpkeycon *)ibpkeycons->array[i];
1738
1739
0
    fprintf(out, "ibpkeycon %s ", ibpkeycon->subnet_prefix_str);
1740
0
    fprintf(out, "%d ", ibpkeycon->pkey_low);
1741
0
    fprintf(out, "%d ", ibpkeycon->pkey_high);
1742
0
    cil_context_to_policy(out, ibpkeycon->context, mls);
1743
0
    fprintf(out, "\n");
1744
0
  }
1745
0
}
1746
1747
static void cil_ibendportcons_to_policy(FILE *out, struct cil_sort *ibendportcons, int mls)
1748
0
{
1749
0
  uint32_t i;
1750
1751
0
  for (i = 0; i < ibendportcons->count; i++) {
1752
0
    struct cil_ibendportcon *ibendportcon = (struct cil_ibendportcon *)ibendportcons->array[i];
1753
1754
0
    fprintf(out, "ibendportcon %s ", ibendportcon->dev_name_str);
1755
0
    fprintf(out, "%u ", ibendportcon->port);
1756
0
    cil_context_to_policy(out, ibendportcon->context, mls);
1757
0
    fprintf(out, "\n");
1758
0
  }
1759
0
}
1760
1761
static void cil_portcons_to_policy(FILE *out, struct cil_sort *portcons, int mls)
1762
0
{
1763
0
  unsigned i;
1764
0
  struct cil_portcon *portcon;
1765
1766
0
  for (i=0; i<portcons->count; i++) {
1767
0
    portcon = portcons->array[i];
1768
0
    fprintf(out, "portcon ");
1769
0
    if (portcon->proto == CIL_PROTOCOL_UDP) {
1770
0
      fprintf(out, "udp ");
1771
0
    } else if (portcon->proto == CIL_PROTOCOL_TCP) {
1772
0
      fprintf(out, "tcp ");
1773
0
    } else if (portcon->proto == CIL_PROTOCOL_DCCP) {
1774
0
      fprintf(out, "dccp ");
1775
0
    } else if (portcon->proto == CIL_PROTOCOL_SCTP) {
1776
0
      fprintf(out, "sctp ");
1777
0
    }
1778
0
    if (portcon->port_low == portcon->port_high) {
1779
0
      fprintf(out, "%d ", portcon->port_low);
1780
0
    } else {
1781
0
      fprintf(out, "%d-%d ", portcon->port_low, portcon->port_high);
1782
0
    }
1783
0
    cil_context_to_policy(out, portcon->context, mls);
1784
0
    fprintf(out, "\n");
1785
0
  }
1786
0
}
1787
1788
static void cil_netifcons_to_policy(FILE *out, struct cil_sort *netifcons, int mls)
1789
0
{
1790
0
  unsigned i;
1791
0
  struct cil_netifcon *netifcon;
1792
1793
0
  for (i=0; i<netifcons->count; i++) {
1794
0
    netifcon = netifcons->array[i];
1795
0
    fprintf(out, "netifcon %s ", netifcon->interface_str);
1796
0
    cil_context_to_policy(out, netifcon->if_context, mls);
1797
0
    fprintf(out, " ");
1798
0
    cil_context_to_policy(out, netifcon->packet_context, mls);
1799
0
    fprintf(out, "\n");
1800
0
  }
1801
0
}
1802
1803
static void cil_nodecons_to_policy(FILE *out, struct cil_sort *nodecons, int mls)
1804
0
{
1805
0
  unsigned i;
1806
0
  struct cil_nodecon *nodecon;
1807
0
  char *addr, *mask;
1808
1809
0
  for (i=0; i<nodecons->count; i++) {
1810
0
    nodecon = nodecons->array[i];
1811
0
    fprintf(out, "nodecon ");
1812
1813
0
    if (nodecon->addr->family == AF_INET) {
1814
0
      errno = 0;
1815
0
      addr = cil_malloc(INET_ADDRSTRLEN);
1816
0
      inet_ntop(nodecon->addr->family, &nodecon->addr->ip.v4, addr, INET_ADDRSTRLEN);
1817
0
      if (errno == 0) {
1818
0
        fprintf(out, "%s ",addr);
1819
0
      } else {
1820
0
        fprintf(out, "[INVALID] ");
1821
0
      }
1822
0
      free(addr);
1823
1824
0
      errno = 0;
1825
0
      mask = cil_malloc(INET_ADDRSTRLEN);
1826
0
      inet_ntop(nodecon->mask->family, &nodecon->mask->ip.v4, mask, INET_ADDRSTRLEN);
1827
0
      if (errno == 0) {
1828
0
        fprintf(out, "%s ",mask);
1829
0
      } else {
1830
0
        fprintf(out, "[INVALID] ");
1831
0
      }
1832
0
      free(mask);
1833
0
    } else {
1834
0
      errno = 0;
1835
0
      addr = cil_malloc(INET6_ADDRSTRLEN);
1836
0
      inet_ntop(nodecon->addr->family, &nodecon->addr->ip.v6, addr, INET6_ADDRSTRLEN);
1837
0
      if (errno == 0) {
1838
0
        fprintf(out, "%s ",addr);
1839
0
      } else {
1840
0
        fprintf(out, "[INVALID] ");
1841
0
      }
1842
0
      free(addr);
1843
1844
0
      errno = 0;
1845
0
      mask = cil_malloc(INET6_ADDRSTRLEN);
1846
0
      inet_ntop(nodecon->mask->family, &nodecon->mask->ip.v6, mask, INET6_ADDRSTRLEN);
1847
0
      if (errno == 0) {
1848
0
        fprintf(out, "%s ",mask);
1849
0
      } else {
1850
0
        fprintf(out, "[INVALID] ");
1851
0
      }
1852
0
      free(mask);
1853
0
    }
1854
1855
0
    cil_context_to_policy(out, nodecon->context, mls);
1856
0
    fprintf(out, "\n");
1857
0
  }
1858
0
}
1859
1860
static void cil_pirqcons_to_policy(FILE *out, struct cil_sort *pirqcons, int mls)
1861
0
{
1862
0
  unsigned i;
1863
0
  struct cil_pirqcon *pirqcon;
1864
1865
0
  for (i = 0; i<pirqcons->count; i++) {
1866
0
    pirqcon = pirqcons->array[i];
1867
0
    fprintf(out, "pirqcon %d ", pirqcon->pirq);
1868
0
    cil_context_to_policy(out, pirqcon->context, mls);
1869
0
    fprintf(out, ";\n");
1870
0
  }
1871
0
}
1872
1873
static void cil_iomemcons_to_policy(FILE *out, struct cil_sort *iomemcons, int mls)
1874
0
{
1875
0
  unsigned i;
1876
0
  struct cil_iomemcon *iomemcon;
1877
1878
0
  for (i = 0; i<iomemcons->count; i++) {
1879
0
    iomemcon = iomemcons->array[i];
1880
0
    if (iomemcon->iomem_low == iomemcon->iomem_high) {
1881
0
      fprintf(out, "iomemcon %"PRIx64" ", iomemcon->iomem_low);
1882
0
    } else {
1883
0
      fprintf(out, "iomemcon %"PRIx64"-%"PRIx64" ", iomemcon->iomem_low, iomemcon->iomem_high);
1884
0
    }
1885
0
    cil_context_to_policy(out, iomemcon->context, mls);
1886
0
    fprintf(out, ";\n");
1887
0
  }
1888
0
}
1889
1890
static void cil_ioportcons_to_policy(FILE *out, struct cil_sort *ioportcons, int mls)
1891
0
{
1892
0
  unsigned i;
1893
0
  struct cil_ioportcon *ioportcon;
1894
1895
0
  for (i = 0; i < ioportcons->count; i++) {
1896
0
    ioportcon = ioportcons->array[i];
1897
0
    fprintf(out, "ioportcon 0x%x-0x%x ", ioportcon->ioport_low, ioportcon->ioport_high);
1898
0
    cil_context_to_policy(out, ioportcon->context, mls);
1899
0
    fprintf(out, ";\n");
1900
0
  }
1901
0
}
1902
1903
static void cil_pcidevicecons_to_policy(FILE *out, struct cil_sort *pcidevicecons, int mls)
1904
0
{
1905
0
  unsigned i;
1906
0
  struct cil_pcidevicecon *pcidevicecon;
1907
1908
0
  for (i = 0; i < pcidevicecons->count; i++) {
1909
0
    pcidevicecon = pcidevicecons->array[i];
1910
0
    fprintf(out, "pcidevicecon 0x%x ", pcidevicecon->dev);
1911
0
    cil_context_to_policy(out, pcidevicecon->context, mls);
1912
0
    fprintf(out, ";\n");
1913
0
  }
1914
0
}
1915
1916
static void cil_devicetreecons_to_policy(FILE *out, struct cil_sort *devicetreecons, int mls)
1917
0
{
1918
0
  unsigned i;
1919
0
  struct cil_devicetreecon *devicetreecon;
1920
1921
0
  for (i = 0; i < devicetreecons->count; i++) {
1922
0
    devicetreecon = devicetreecons->array[i];
1923
0
    fprintf(out, "devicetreecon %s ", devicetreecon->path);
1924
0
    cil_context_to_policy(out, devicetreecon->context, mls);
1925
0
    fprintf(out, ";\n");
1926
0
  }
1927
0
}
1928
1929
void cil_gen_policy(FILE *out, struct cil_db *db)
1930
0
{
1931
0
  unsigned i;
1932
0
  struct cil_tree_node *head = db->ast->root;
1933
0
  struct cil_list *lists[CIL_LIST_NUM_LISTS];
1934
1935
0
  for (i=0; i<CIL_LIST_NUM_LISTS; i++) {
1936
0
    cil_list_init(&lists[i], CIL_LIST);
1937
0
  }
1938
1939
0
  cil_gather_statements(head, lists);
1940
1941
0
  cil_class_decls_to_policy(out, db->classorder);
1942
1943
0
  cil_sid_decls_to_policy(out, db->sidorder);
1944
1945
0
  cil_commons_to_policy(out, lists[CIL_LIST_COMMON]);
1946
0
  cil_classes_to_policy(out, db->classorder);
1947
1948
0
  cil_defaults_to_policy(out, lists[CIL_LIST_DEFAULT_USER], "default_user");
1949
0
  cil_defaults_to_policy(out, lists[CIL_LIST_DEFAULT_ROLE], "default_role");
1950
0
  cil_defaults_to_policy(out, lists[CIL_LIST_DEFAULT_TYPE], "default_type");
1951
1952
0
  if (db->mls == CIL_TRUE) {
1953
0
    cil_default_ranges_to_policy(out, lists[CIL_LIST_DEFAULT_RANGE]);
1954
0
    cil_sensitivities_to_policy(out, db->sensitivityorder, lists[CIL_LIST_SENSALIAS]);
1955
0
    cil_dominance_to_policy(out, db->sensitivityorder);
1956
0
    cil_categories_to_policy(out, db->catorder, lists[CIL_LIST_CATALIAS]);
1957
0
    cil_levels_to_policy(out, db->sensitivityorder);
1958
0
    cil_mlsconstrains_to_policy(out, db, lists[CIL_LIST_MLSCONSTRAIN]);
1959
0
    cil_validatetrans_to_policy(out, db, lists[CIL_LIST_MLSVALIDATETRANS], CIL_KEY_MLSVALIDATETRANS);
1960
0
  }
1961
1962
0
  cil_simple_rules_to_policy(out, lists[CIL_LIST_POLICYCAP], CIL_KEY_POLICYCAP);
1963
1964
0
  cil_simple_rules_to_policy(out, lists[CIL_LIST_TYPEATTRIBUTE], "attribute");
1965
0
  cil_simple_rules_to_policy(out, lists[CIL_LIST_ROLEATTRIBUTE], "attribute_role");
1966
1967
0
  cil_bools_to_policy(out, lists[CIL_LIST_BOOL]);
1968
1969
0
  cil_simple_rules_to_policy(out, lists[CIL_LIST_TYPE], "type");
1970
0
  cil_typealiases_to_policy(out, lists[CIL_LIST_TYPE], lists[CIL_LIST_TYPEALIAS]);
1971
0
  cil_typebounds_to_policy(out, lists[CIL_LIST_TYPE]);
1972
0
  cil_typeattributes_to_policy(out, lists[CIL_LIST_TYPE], lists[CIL_LIST_TYPEATTRIBUTE]);
1973
0
  cil_te_rules_to_policy(out, head, db->mls);
1974
1975
0
  cil_roles_to_policy(out, lists[CIL_LIST_ROLE]);
1976
0
  cil_role_types_to_policy(out, lists[CIL_LIST_ROLE], lists[CIL_LIST_TYPE]);
1977
0
  cil_roleattributes_to_policy(out, lists[CIL_LIST_ROLE], lists[CIL_LIST_ROLEATTRIBUTE]);
1978
0
  cil_roleallows_to_policy(out, lists[CIL_LIST_ROLEALLOW]);
1979
0
  cil_roletransitions_to_policy(out, lists[CIL_LIST_ROLETRANSITION]);
1980
1981
0
  cil_users_to_policy(out, db->mls, lists[CIL_LIST_USER], lists[CIL_LIST_ROLE]);
1982
1983
0
  cil_constrains_to_policy(out, db, lists[CIL_LIST_CONSTRAINT]);
1984
0
  cil_validatetrans_to_policy(out, db, lists[CIL_LIST_VALIDATETRANS], CIL_KEY_VALIDATETRANS);
1985
1986
0
  cil_sid_contexts_to_policy(out, db->sidorder, db->mls);
1987
0
  cil_fsuses_to_policy(out, db->fsuse, db->mls);
1988
0
  cil_genfscons_to_policy(out, db->genfscon, db->mls);
1989
0
  cil_portcons_to_policy(out, db->portcon, db->mls);
1990
0
  cil_netifcons_to_policy(out, db->netifcon, db->mls);
1991
0
  cil_ibpkeycons_to_policy(out, db->ibpkeycon, db->mls);
1992
0
  cil_ibendportcons_to_policy(out, db->ibendportcon, db->mls);
1993
0
  cil_nodecons_to_policy(out, db->nodecon, db->mls);
1994
0
  cil_pirqcons_to_policy(out, db->pirqcon, db->mls);
1995
0
  cil_iomemcons_to_policy(out, db->iomemcon, db->mls);
1996
0
  cil_ioportcons_to_policy(out, db->ioportcon, db->mls);
1997
0
  cil_pcidevicecons_to_policy(out, db->pcidevicecon, db->mls);
1998
0
  cil_devicetreecons_to_policy(out, db->devicetreecon, db->mls);
1999
2000
0
  for (i=0; i<CIL_LIST_NUM_LISTS; i++) {
2001
0
    cil_list_destroy(&lists[i], CIL_FALSE);
2002
0
  }
2003
2004
0
}