Coverage Report

Created: 2026-09-01 06:10

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/selinux/libsepol/src/write.c
Line
Count
Source
1
2
/* Author : Stephen Smalley, <stephen.smalley.work@gmail.com> */
3
4
/*
5
 * Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com>
6
 *
7
 *  Support for enhanced MLS infrastructure.
8
 *
9
 * Updated: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com>
10
 *
11
 *  Added conditional policy language extensions
12
 * 
13
 * Updated: Joshua Brindle <jbrindle@tresys.com> and Jason Tang <jtang@tresys.org>
14
 *
15
 *  Module writing support
16
 *
17
 * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
18
 * Copyright (C) 2003-2005 Tresys Technology, LLC
19
 * Copyright (C) 2017 Mellanox Technologies Inc.
20
 *
21
 *  This library is free software; you can redistribute it and/or
22
 *  modify it under the terms of the GNU Lesser General Public
23
 *  License as published by the Free Software Foundation; either
24
 *  version 2.1 of the License, or (at your option) any later version.
25
 *
26
 *  This library is distributed in the hope that it will be useful,
27
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
28
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
29
 *  Lesser General Public License for more details.
30
 *
31
 *  You should have received a copy of the GNU Lesser General Public
32
 *  License along with this library; if not, write to the Free Software
33
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
34
 */
35
#include <assert.h>
36
#include <stdlib.h>
37
38
#include <sepol/policydb/ebitmap.h>
39
#include <sepol/policydb/avtab.h>
40
#include <sepol/policydb/policydb.h>
41
#include <sepol/policydb/conditional.h>
42
#include <sepol/policydb/expand.h>
43
44
#include "debug.h"
45
#include "private.h"
46
#include "mls.h"
47
48
#define glblub_version                                 \
49
5.93k
  ((p->policy_type == POLICY_KERN &&             \
50
2.96k
    p->policyvers >= POLICYDB_VERSION_GLBLUB) || \
51
5.93k
   (p->policy_type == POLICY_BASE &&             \
52
1.19k
    p->policyvers >= MOD_POLICYDB_VERSION_GLBLUB))
53
54
struct policy_data {
55
  struct policy_file *fp;
56
  struct policydb *p;
57
};
58
59
static int avrule_write_list(policydb_t *p, avrule_t *avrules,
60
           struct policy_file *fp, unsigned conditional);
61
62
static int ebitmap_write(ebitmap_t *e, struct policy_file *fp)
63
27.9k
{
64
27.9k
  ebitmap_node_t *n;
65
27.9k
  uint32_t buf[32], bit, count;
66
27.9k
  uint64_t map;
67
27.9k
  size_t items;
68
69
27.9k
  buf[0] = cpu_to_le32(MAPSIZE);
70
27.9k
  buf[1] = cpu_to_le32(e->highbit);
71
72
27.9k
  count = 0;
73
37.9k
  for (n = e->node; n; n = n->next)
74
9.96k
    count++;
75
27.9k
  buf[2] = cpu_to_le32(count);
76
77
27.9k
  items = put_entry(buf, sizeof(uint32_t), 3, fp);
78
27.9k
  if (items != 3)
79
0
    return POLICYDB_ERROR;
80
81
37.9k
  for (n = e->node; n; n = n->next) {
82
9.96k
    bit = cpu_to_le32(n->startbit);
83
9.96k
    items = put_entry(&bit, sizeof(uint32_t), 1, fp);
84
9.96k
    if (items != 1)
85
0
      return POLICYDB_ERROR;
86
9.96k
    map = cpu_to_le64(n->map);
87
9.96k
    items = put_entry(&map, sizeof(uint64_t), 1, fp);
88
9.96k
    if (items != 1)
89
0
      return POLICYDB_ERROR;
90
9.96k
  }
91
92
27.9k
  return POLICYDB_SUCCESS;
93
27.9k
}
94
95
static int avtab_write_item(policydb_t *p, avtab_ptr_t cur,
96
          struct policy_file *fp, unsigned conditional)
97
3.70k
{
98
3.70k
  uint8_t buf8;
99
3.70k
  uint16_t buf16[4];
100
3.70k
  uint32_t buf32[10];
101
3.70k
  size_t items;
102
3.70k
  unsigned int i;
103
104
  /* Generate the new avtab format. */
105
3.70k
  buf16[0] = cpu_to_le16(cur->key.source_type);
106
3.70k
  buf16[1] = cpu_to_le16(cur->key.target_type);
107
3.70k
  buf16[2] = cpu_to_le16(cur->key.target_class);
108
3.70k
  buf16[3] = cpu_to_le16(cur->key.specified);
109
3.70k
  items = put_entry(buf16, sizeof(uint16_t), 4, fp);
110
3.70k
  if (items != 4)
111
0
    return POLICYDB_ERROR;
112
3.70k
  if ((p->policyvers < POLICYDB_VERSION_XPERMS_IOCTL) &&
113
22
      (cur->key.specified & AVTAB_XPERMS)) {
114
0
    ERR(fp->handle,
115
0
        "policy version %u does not support extended "
116
0
        "permissions rules and one was specified",
117
0
        p->policyvers);
118
0
    return POLICYDB_ERROR;
119
0
  }
120
121
3.70k
  if (!policydb_has_cond_xperms_feature(p) &&
122
812
      (cur->key.specified & AVTAB_XPERMS) && conditional) {
123
0
    ERR(fp->handle,
124
0
        "policy version %u does not support extended "
125
0
        "permissions rules in conditional policies and one was specified",
126
0
        p->policyvers);
127
0
    return POLICYDB_ERROR;
128
0
  }
129
130
3.70k
  if (p->target_platform != SEPOL_TARGET_SELINUX &&
131
216
      (cur->key.specified & AVTAB_XPERMS)) {
132
0
    ERR(fp->handle,
133
0
        "Target platform %s does not support "
134
0
        "extended permissions rules and one was specified",
135
0
        policydb_target_strings[p->target_platform]);
136
0
    return POLICYDB_ERROR;
137
0
  }
138
139
3.70k
  if (cur->key.specified & AVTAB_XPERMS) {
140
3.07k
    buf8 = cur->datum.xperms->specified;
141
3.07k
    items = put_entry(&buf8, sizeof(uint8_t), 1, fp);
142
3.07k
    if (items != 1)
143
0
      return POLICYDB_ERROR;
144
3.07k
    buf8 = cur->datum.xperms->driver;
145
3.07k
    items = put_entry(&buf8, sizeof(uint8_t), 1, fp);
146
3.07k
    if (items != 1)
147
0
      return POLICYDB_ERROR;
148
27.6k
    for (i = 0; i < ARRAY_SIZE(cur->datum.xperms->perms); i++)
149
24.5k
      buf32[i] = cpu_to_le32(cur->datum.xperms->perms[i]);
150
3.07k
    items = put_entry(buf32, sizeof(uint32_t), 8, fp);
151
3.07k
    if (items != 8)
152
0
      return POLICYDB_ERROR;
153
3.07k
  } else {
154
636
    buf32[0] = cpu_to_le32(cur->datum.data);
155
636
    items = put_entry(buf32, sizeof(uint32_t), 1, fp);
156
636
    if (items != 1)
157
0
      return POLICYDB_ERROR;
158
636
  }
159
160
3.70k
  return POLICYDB_SUCCESS;
161
3.70k
}
162
163
static int avtab_write(struct policydb *p, avtab_t *a, struct policy_file *fp)
164
1.25k
{
165
1.25k
  unsigned int i;
166
1.25k
  int rc;
167
1.25k
  avtab_ptr_t cur;
168
1.25k
  uint32_t nel;
169
1.25k
  size_t items;
170
171
1.25k
  nel = cpu_to_le32(a->nel);
172
1.25k
  items = put_entry(&nel, sizeof(uint32_t), 1, fp);
173
1.25k
  if (items != 1)
174
0
    return POLICYDB_ERROR;
175
176
419M
  for (i = 0; i < a->nslot; i++) {
177
419M
    for (cur = a->htable[i]; cur; cur = cur->next) {
178
1.71k
      if (avtab_write_item(p, cur, fp, 0)) {
179
0
        rc = -1;
180
0
        goto out;
181
0
      }
182
1.71k
    }
183
419M
  }
184
185
1.25k
  rc = 0;
186
1.25k
out:
187
1.25k
  return rc;
188
1.25k
}
189
190
/*
191
 * Write a semantic MLS level structure to a policydb binary 
192
 * representation file.
193
 */
194
static int mls_write_semantic_level_helper(mls_semantic_level_t *l,
195
             struct policy_file *fp)
196
177
{
197
177
  uint32_t buf[2], ncat = 0;
198
177
  size_t items;
199
177
  mls_semantic_cat_t *cat;
200
201
808
  for (cat = l->cat; cat; cat = cat->next)
202
631
    ncat++;
203
204
177
  buf[0] = cpu_to_le32(l->sens);
205
177
  buf[1] = cpu_to_le32(ncat);
206
177
  items = put_entry(buf, sizeof(uint32_t), 2, fp);
207
177
  if (items != 2)
208
0
    return POLICYDB_ERROR;
209
210
808
  for (cat = l->cat; cat; cat = cat->next) {
211
631
    buf[0] = cpu_to_le32(cat->low);
212
631
    buf[1] = cpu_to_le32(cat->high);
213
631
    items = put_entry(buf, sizeof(uint32_t), 2, fp);
214
631
    if (items != 2)
215
0
      return POLICYDB_ERROR;
216
631
  }
217
218
177
  return POLICYDB_SUCCESS;
219
177
}
220
221
/*
222
 * Read a semantic MLS range structure to a policydb binary 
223
 * representation file.
224
 */
225
static int mls_write_semantic_range_helper(mls_semantic_range_t *r,
226
             struct policy_file *fp)
227
59
{
228
59
  int rc;
229
230
59
  rc = mls_write_semantic_level_helper(&r->level[0], fp);
231
59
  if (rc)
232
0
    return rc;
233
234
59
  rc = mls_write_semantic_level_helper(&r->level[1], fp);
235
236
59
  return rc;
237
59
}
238
239
/*
240
 * Write a MLS level structure to a policydb binary 
241
 * representation file.
242
 */
243
static int mls_write_level(mls_level_t *l, struct policy_file *fp)
244
1.06k
{
245
1.06k
  uint32_t sens;
246
1.06k
  size_t items;
247
248
1.06k
  sens = cpu_to_le32(l->sens);
249
1.06k
  items = put_entry(&sens, sizeof(uint32_t), 1, fp);
250
1.06k
  if (items != 1)
251
0
    return POLICYDB_ERROR;
252
253
1.06k
  if (ebitmap_write(&l->cat, fp))
254
0
    return POLICYDB_ERROR;
255
256
1.06k
  return POLICYDB_SUCCESS;
257
1.06k
}
258
259
/*
260
 * Write a MLS range structure to a policydb binary 
261
 * representation file.
262
 */
263
static int mls_write_range_helper(mls_range_t *r, struct policy_file *fp)
264
1.24k
{
265
1.24k
  uint32_t buf[3];
266
1.24k
  size_t items, items2;
267
1.24k
  int eq;
268
269
1.24k
  eq = mls_level_eq(&r->level[1], &r->level[0]);
270
271
1.24k
  items = 1; /* item 0 is used for the item count */
272
1.24k
  buf[items++] = cpu_to_le32(r->level[0].sens);
273
1.24k
  if (!eq)
274
513
    buf[items++] = cpu_to_le32(r->level[1].sens);
275
1.24k
  buf[0] = cpu_to_le32(items - 1);
276
277
1.24k
  items2 = put_entry(buf, sizeof(uint32_t), items, fp);
278
1.24k
  if (items2 != items)
279
0
    return POLICYDB_ERROR;
280
281
1.24k
  if (ebitmap_write(&r->level[0].cat, fp))
282
0
    return POLICYDB_ERROR;
283
1.24k
  if (!eq)
284
513
    if (ebitmap_write(&r->level[1].cat, fp))
285
0
      return POLICYDB_ERROR;
286
287
1.24k
  return POLICYDB_SUCCESS;
288
1.24k
}
289
290
static int sens_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
291
491
{
292
491
  level_datum_t *levdatum;
293
491
  uint32_t buf[32];
294
491
  size_t items, items2, len;
295
491
  struct policy_data *pd = ptr;
296
491
  struct policy_file *fp = pd->fp;
297
298
491
  levdatum = (level_datum_t *)datum;
299
300
491
  len = strlen(key);
301
491
  items = 0;
302
491
  buf[items++] = cpu_to_le32(len);
303
491
  buf[items++] = cpu_to_le32(levdatum->isalias);
304
491
  items2 = put_entry(buf, sizeof(uint32_t), items, fp);
305
491
  if (items != items2)
306
0
    return POLICYDB_ERROR;
307
308
491
  items = put_entry(key, 1, len, fp);
309
491
  if (items != len)
310
0
    return POLICYDB_ERROR;
311
312
491
  if (mls_write_level(levdatum->level, fp))
313
0
    return POLICYDB_ERROR;
314
315
491
  return POLICYDB_SUCCESS;
316
491
}
317
318
static int cat_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
319
544
{
320
544
  cat_datum_t *catdatum;
321
544
  uint32_t buf[32];
322
544
  size_t items, items2, len;
323
544
  struct policy_data *pd = ptr;
324
544
  struct policy_file *fp = pd->fp;
325
326
544
  catdatum = (cat_datum_t *)datum;
327
328
544
  len = strlen(key);
329
544
  items = 0;
330
544
  buf[items++] = cpu_to_le32(len);
331
544
  buf[items++] = cpu_to_le32(catdatum->s.value);
332
544
  buf[items++] = cpu_to_le32(catdatum->isalias);
333
544
  items2 = put_entry(buf, sizeof(uint32_t), items, fp);
334
544
  if (items != items2)
335
0
    return POLICYDB_ERROR;
336
337
544
  items = put_entry(key, 1, len, fp);
338
544
  if (items != len)
339
0
    return POLICYDB_ERROR;
340
341
544
  return POLICYDB_SUCCESS;
342
544
}
343
344
static int role_trans_write(policydb_t *p, struct policy_file *fp)
345
1.25k
{
346
1.25k
  role_trans_t *r = p->role_tr;
347
1.25k
  role_trans_t *tr;
348
1.25k
  uint32_t buf[3];
349
1.25k
  size_t nel, items;
350
1.25k
  int new_roletr = (p->policy_type == POLICY_KERN &&
351
1.25k
        p->policyvers >= POLICYDB_VERSION_ROLETRANS);
352
1.25k
  int warning_issued = 0;
353
354
1.25k
  nel = 0;
355
1.29k
  for (tr = r; tr; tr = tr->next)
356
37
    if (new_roletr || tr->tclass == p->process_class)
357
37
      nel++;
358
359
1.25k
  buf[0] = cpu_to_le32(nel);
360
1.25k
  items = put_entry(buf, sizeof(uint32_t), 1, fp);
361
1.25k
  if (items != 1)
362
0
    return POLICYDB_ERROR;
363
1.29k
  for (tr = r; tr; tr = tr->next) {
364
37
    if (!new_roletr && tr->tclass != p->process_class) {
365
0
      if (!warning_issued)
366
0
        WARN(fp->handle,
367
0
             "Discarding role_transition "
368
0
             "rules for security classes other than "
369
0
             "\"process\"");
370
0
      warning_issued = 1;
371
0
      continue;
372
0
    }
373
37
    buf[0] = cpu_to_le32(tr->role);
374
37
    buf[1] = cpu_to_le32(tr->type);
375
37
    buf[2] = cpu_to_le32(tr->new_role);
376
37
    items = put_entry(buf, sizeof(uint32_t), 3, fp);
377
37
    if (items != 3)
378
0
      return POLICYDB_ERROR;
379
37
    if (new_roletr) {
380
37
      buf[0] = cpu_to_le32(tr->tclass);
381
37
      items = put_entry(buf, sizeof(uint32_t), 1, fp);
382
37
      if (items != 1)
383
0
        return POLICYDB_ERROR;
384
37
    }
385
37
  }
386
387
1.25k
  return POLICYDB_SUCCESS;
388
1.25k
}
389
390
static int role_allow_write(role_allow_t *r, struct policy_file *fp)
391
1.25k
{
392
1.25k
  role_allow_t *ra;
393
1.25k
  uint32_t buf[2];
394
1.25k
  size_t nel, items;
395
396
1.25k
  nel = 0;
397
23.2k
  for (ra = r; ra; ra = ra->next)
398
22.0k
    nel++;
399
1.25k
  buf[0] = cpu_to_le32(nel);
400
1.25k
  items = put_entry(buf, sizeof(uint32_t), 1, fp);
401
1.25k
  if (items != 1)
402
0
    return POLICYDB_ERROR;
403
23.2k
  for (ra = r; ra; ra = ra->next) {
404
22.0k
    buf[0] = cpu_to_le32(ra->role);
405
22.0k
    buf[1] = cpu_to_le32(ra->new_role);
406
22.0k
    items = put_entry(buf, sizeof(uint32_t), 2, fp);
407
22.0k
    if (items != 2)
408
0
      return POLICYDB_ERROR;
409
22.0k
  }
410
1.25k
  return POLICYDB_SUCCESS;
411
1.25k
}
412
413
static int filename_write_one_compat(hashtab_key_t key, void *data, void *ptr)
414
1
{
415
1
  uint32_t bit, buf[4];
416
1
  size_t items, len;
417
1
  filename_trans_key_t *ft = (filename_trans_key_t *)key;
418
1
  filename_trans_datum_t *datum = data;
419
1
  ebitmap_node_t *node;
420
1
  void *fp = ptr;
421
422
1
  len = strlen(ft->name);
423
1
  do {
424
64
    ebitmap_for_each_positive_bit(&datum->stypes, node, bit) {
425
1
      buf[0] = cpu_to_le32(len);
426
1
      items = put_entry(buf, sizeof(uint32_t), 1, fp);
427
1
      if (items != 1)
428
0
        return POLICYDB_ERROR;
429
430
1
      items = put_entry(ft->name, sizeof(char), len, fp);
431
1
      if (items != len)
432
0
        return POLICYDB_ERROR;
433
434
1
      buf[0] = cpu_to_le32(bit + 1);
435
1
      buf[1] = cpu_to_le32(ft->ttype);
436
1
      buf[2] = cpu_to_le32(ft->tclass);
437
1
      buf[3] = cpu_to_le32(datum->otype);
438
1
      items = put_entry(buf, sizeof(uint32_t), 4, fp);
439
1
      if (items != 4)
440
0
        return POLICYDB_ERROR;
441
1
    }
442
443
1
    datum = datum->next;
444
1
  } while (datum);
445
446
1
  return 0;
447
1
}
448
449
static int filename_write_one(hashtab_key_t key, void *data, void *ptr)
450
0
{
451
0
  uint32_t buf[3];
452
0
  size_t items, len, ndatum;
453
0
  filename_trans_key_t *ft = (filename_trans_key_t *)key;
454
0
  filename_trans_datum_t *datum;
455
0
  void *fp = ptr;
456
457
0
  len = strlen(ft->name);
458
0
  buf[0] = cpu_to_le32(len);
459
0
  items = put_entry(buf, sizeof(uint32_t), 1, fp);
460
0
  if (items != 1)
461
0
    return POLICYDB_ERROR;
462
463
0
  items = put_entry(ft->name, sizeof(char), len, fp);
464
0
  if (items != len)
465
0
    return POLICYDB_ERROR;
466
467
0
  ndatum = 0;
468
0
  datum = data;
469
0
  do {
470
0
    ndatum++;
471
0
    datum = datum->next;
472
0
  } while (datum);
473
474
0
  buf[0] = cpu_to_le32(ft->ttype);
475
0
  buf[1] = cpu_to_le32(ft->tclass);
476
0
  buf[2] = cpu_to_le32(ndatum);
477
0
  items = put_entry(buf, sizeof(uint32_t), 3, fp);
478
0
  if (items != 3)
479
0
    return POLICYDB_ERROR;
480
481
0
  datum = data;
482
0
  do {
483
0
    if (ebitmap_write(&datum->stypes, fp))
484
0
      return POLICYDB_ERROR;
485
486
0
    buf[0] = cpu_to_le32(datum->otype);
487
0
    items = put_entry(buf, sizeof(uint32_t), 1, fp);
488
0
    if (items != 1)
489
0
      return POLICYDB_ERROR;
490
491
0
    datum = datum->next;
492
0
  } while (datum);
493
494
0
  return 0;
495
0
}
496
497
static int filename_trans_write(struct policydb *p, void *fp)
498
1.24k
{
499
1.24k
  size_t items;
500
1.24k
  uint32_t buf[1];
501
1.24k
  int rc;
502
503
1.24k
  if (p->policyvers < POLICYDB_VERSION_FILENAME_TRANS)
504
0
    return 0;
505
506
1.24k
  if (p->policyvers < POLICYDB_VERSION_COMP_FTRANS) {
507
568
    buf[0] = cpu_to_le32(p->filename_trans_count);
508
568
    items = put_entry(buf, sizeof(uint32_t), 1, fp);
509
568
    if (items != 1)
510
0
      return POLICYDB_ERROR;
511
512
568
    rc = hashtab_map(p->filename_trans, filename_write_one_compat,
513
568
         fp);
514
681
  } else {
515
681
    buf[0] = cpu_to_le32(p->filename_trans->nel);
516
681
    items = put_entry(buf, sizeof(uint32_t), 1, fp);
517
681
    if (items != 1)
518
0
      return POLICYDB_ERROR;
519
520
681
    rc = hashtab_map(p->filename_trans, filename_write_one, fp);
521
681
  }
522
1.24k
  return rc;
523
1.24k
}
524
525
static int role_set_write(role_set_t *x, struct policy_file *fp)
526
187
{
527
187
  size_t items;
528
187
  uint32_t buf[1];
529
530
187
  if (ebitmap_write(&x->roles, fp))
531
0
    return POLICYDB_ERROR;
532
533
187
  buf[0] = cpu_to_le32(x->flags);
534
187
  items = put_entry(buf, sizeof(uint32_t), 1, fp);
535
187
  if (items != 1)
536
0
    return POLICYDB_ERROR;
537
538
187
  return POLICYDB_SUCCESS;
539
187
}
540
541
static int type_set_write(type_set_t *x, struct policy_file *fp)
542
253
{
543
253
  size_t items;
544
253
  uint32_t buf[1];
545
546
253
  if (ebitmap_write(&x->types, fp))
547
0
    return POLICYDB_ERROR;
548
253
  if (ebitmap_write(&x->negset, fp))
549
0
    return POLICYDB_ERROR;
550
551
253
  buf[0] = cpu_to_le32(x->flags);
552
253
  items = put_entry(buf, sizeof(uint32_t), 1, fp);
553
253
  if (items != 1)
554
0
    return POLICYDB_ERROR;
555
556
253
  return POLICYDB_SUCCESS;
557
253
}
558
559
static int cond_write_bool(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
560
400
{
561
400
  cond_bool_datum_t *booldatum;
562
400
  uint32_t buf[3], len;
563
400
  unsigned int items, items2;
564
400
  struct policy_data *pd = ptr;
565
400
  struct policy_file *fp = pd->fp;
566
400
  struct policydb *p = pd->p;
567
568
400
  booldatum = (cond_bool_datum_t *)datum;
569
570
400
  len = strlen(key);
571
400
  items = 0;
572
400
  buf[items++] = cpu_to_le32(booldatum->s.value);
573
400
  buf[items++] = cpu_to_le32(booldatum->state);
574
400
  buf[items++] = cpu_to_le32(len);
575
400
  items2 = put_entry(buf, sizeof(uint32_t), items, fp);
576
400
  if (items != items2)
577
0
    return POLICYDB_ERROR;
578
400
  items = put_entry(key, 1, len, fp);
579
400
  if (items != len)
580
0
    return POLICYDB_ERROR;
581
582
400
  if (p->policy_type != POLICY_KERN &&
583
18
      p->policyvers >= MOD_POLICYDB_VERSION_TUNABLE_SEP) {
584
14
    buf[0] = cpu_to_le32(booldatum->flags);
585
14
    items = put_entry(buf, sizeof(uint32_t), 1, fp);
586
14
    if (items != 1)
587
0
      return POLICYDB_ERROR;
588
14
  }
589
590
400
  return POLICYDB_SUCCESS;
591
400
}
592
593
/*
594
 * cond_write_cond_av_list doesn't write out the av_list nodes.
595
 * Instead it writes out the key/value pairs from the avtab. This
596
 * is necessary because there is no way to uniquely identifying rules
597
 * in the avtab so it is not possible to associate individual rules
598
 * in the avtab with a conditional without saving them as part of
599
 * the conditional. This means that the avtab with the conditional
600
 * rules will not be saved but will be rebuilt on policy load.
601
 */
602
static int cond_write_av_list(policydb_t *p, cond_av_list_t *list,
603
            struct policy_file *fp)
604
650
{
605
650
  uint32_t buf[4];
606
650
  cond_av_list_t *cur_list;
607
650
  uint32_t len, items;
608
650
  int rc = -1;
609
610
650
  len = 0;
611
2.64k
  for (cur_list = list; cur_list != NULL; cur_list = cur_list->next) {
612
1.99k
    if (cur_list->node->parse_context)
613
1.99k
      len++;
614
1.99k
  }
615
616
650
  buf[0] = cpu_to_le32(len);
617
650
  items = put_entry(buf, sizeof(uint32_t), 1, fp);
618
650
  if (items != 1)
619
0
    goto out;
620
621
650
  if (len == 0) {
622
263
    rc = 0;
623
263
    goto out;
624
263
  }
625
626
2.37k
  for (cur_list = list; cur_list != NULL; cur_list = cur_list->next) {
627
1.99k
    if (cur_list->node->parse_context)
628
1.99k
      if (avtab_write_item(p, cur_list->node, fp, 1))
629
0
        goto out;
630
1.99k
  }
631
632
387
  rc = 0;
633
650
out:
634
650
  return rc;
635
387
}
636
637
static int cond_write_node(policydb_t *p, cond_node_t *node,
638
         struct policy_file *fp)
639
325
{
640
325
  cond_expr_t *cur_expr;
641
325
  uint32_t buf[2];
642
325
  uint32_t items, items2, len;
643
644
325
  buf[0] = cpu_to_le32(node->cur_state);
645
325
  items = put_entry(buf, sizeof(uint32_t), 1, fp);
646
325
  if (items != 1)
647
0
    return POLICYDB_ERROR;
648
649
  /* expr */
650
325
  len = 0;
651
662
  for (cur_expr = node->expr; cur_expr != NULL; cur_expr = cur_expr->next)
652
337
    len++;
653
654
325
  buf[0] = cpu_to_le32(len);
655
325
  items = put_entry(buf, sizeof(uint32_t), 1, fp);
656
325
  if (items != 1)
657
0
    return POLICYDB_ERROR;
658
659
662
  for (cur_expr = node->expr; cur_expr != NULL;
660
337
       cur_expr = cur_expr->next) {
661
337
    items = 0;
662
337
    buf[items++] = cpu_to_le32(cur_expr->expr_type);
663
337
    buf[items++] = cpu_to_le32(cur_expr->boolean);
664
337
    items2 = put_entry(buf, sizeof(uint32_t), items, fp);
665
337
    if (items2 != items)
666
0
      return POLICYDB_ERROR;
667
337
  }
668
669
325
  if (p->policy_type == POLICY_KERN) {
670
325
    if (cond_write_av_list(p, node->true_list, fp) != 0)
671
0
      return POLICYDB_ERROR;
672
325
    if (cond_write_av_list(p, node->false_list, fp) != 0)
673
0
      return POLICYDB_ERROR;
674
325
  } else {
675
0
    if (avrule_write_list(p, node->avtrue_list, fp, 1))
676
0
      return POLICYDB_ERROR;
677
0
    if (avrule_write_list(p, node->avfalse_list, fp, 1))
678
0
      return POLICYDB_ERROR;
679
0
  }
680
681
325
  if (p->policy_type != POLICY_KERN &&
682
0
      p->policyvers >= MOD_POLICYDB_VERSION_TUNABLE_SEP) {
683
0
    buf[0] = cpu_to_le32(node->flags);
684
0
    items = put_entry(buf, sizeof(uint32_t), 1, fp);
685
0
    if (items != 1)
686
0
      return POLICYDB_ERROR;
687
0
  }
688
689
325
  return POLICYDB_SUCCESS;
690
325
}
691
692
static int cond_write_list(policydb_t *p, cond_list_t *list,
693
         struct policy_file *fp)
694
1.49k
{
695
1.49k
  cond_node_t *cur;
696
1.49k
  uint32_t len, items;
697
1.49k
  uint32_t buf[1];
698
699
1.49k
  len = 0;
700
1.82k
  for (cur = list; cur != NULL; cur = cur->next)
701
325
    len++;
702
1.49k
  buf[0] = cpu_to_le32(len);
703
1.49k
  items = put_entry(buf, sizeof(uint32_t), 1, fp);
704
1.49k
  if (items != 1)
705
0
    return POLICYDB_ERROR;
706
707
1.82k
  for (cur = list; cur != NULL; cur = cur->next) {
708
325
    if (cond_write_node(p, cur, fp) != 0)
709
0
      return POLICYDB_ERROR;
710
325
  }
711
1.49k
  return POLICYDB_SUCCESS;
712
1.49k
}
713
714
/*
715
 * Write a security context structure
716
 * to a policydb binary representation file.
717
 */
718
static int context_write(struct policydb *p, context_struct_t *c,
719
       struct policy_file *fp)
720
673
{
721
673
  uint32_t buf[32];
722
673
  size_t items, items2;
723
724
673
  items = 0;
725
673
  buf[items++] = cpu_to_le32(c->user);
726
673
  buf[items++] = cpu_to_le32(c->role);
727
673
  buf[items++] = cpu_to_le32(c->type);
728
673
  items2 = put_entry(buf, sizeof(uint32_t), items, fp);
729
673
  if (items2 != items)
730
0
    return POLICYDB_ERROR;
731
673
  if ((p->policy_type == POLICY_KERN) || (p->policy_type == POLICY_BASE))
732
673
    if (mls_write_range_helper(&c->range, fp))
733
0
      return POLICYDB_ERROR;
734
735
673
  return POLICYDB_SUCCESS;
736
673
}
737
738
/*
739
 * The following *_write functions are used to
740
 * write the symbol data to a policy database
741
 * binary representation file.
742
 */
743
744
static int perm_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
745
1.54k
{
746
1.54k
  perm_datum_t *perdatum;
747
1.54k
  uint32_t buf[32];
748
1.54k
  size_t items, items2, len;
749
1.54k
  struct policy_data *pd = ptr;
750
1.54k
  struct policy_file *fp = pd->fp;
751
752
1.54k
  perdatum = (perm_datum_t *)datum;
753
754
1.54k
  len = strlen(key);
755
1.54k
  items = 0;
756
1.54k
  buf[items++] = cpu_to_le32(len);
757
1.54k
  buf[items++] = cpu_to_le32(perdatum->s.value);
758
1.54k
  items2 = put_entry(buf, sizeof(uint32_t), items, fp);
759
1.54k
  if (items != items2)
760
0
    return POLICYDB_ERROR;
761
762
1.54k
  items = put_entry(key, 1, len, fp);
763
1.54k
  if (items != len)
764
0
    return POLICYDB_ERROR;
765
766
1.54k
  return POLICYDB_SUCCESS;
767
1.54k
}
768
769
static int common_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
770
0
{
771
0
  common_datum_t *comdatum;
772
0
  uint32_t buf[32];
773
0
  size_t items, items2, len;
774
0
  struct policy_data *pd = ptr;
775
0
  struct policy_file *fp = pd->fp;
776
777
0
  comdatum = (common_datum_t *)datum;
778
779
0
  len = strlen(key);
780
0
  items = 0;
781
0
  buf[items++] = cpu_to_le32(len);
782
0
  buf[items++] = cpu_to_le32(comdatum->s.value);
783
0
  buf[items++] = cpu_to_le32(comdatum->permissions.nprim);
784
0
  buf[items++] = cpu_to_le32(comdatum->permissions.table->nel);
785
0
  items2 = put_entry(buf, sizeof(uint32_t), items, fp);
786
0
  if (items != items2)
787
0
    return POLICYDB_ERROR;
788
789
0
  items = put_entry(key, 1, len, fp);
790
0
  if (items != len)
791
0
    return POLICYDB_ERROR;
792
793
0
  if (hashtab_map(comdatum->permissions.table, perm_write, pd))
794
0
    return POLICYDB_ERROR;
795
796
0
  return POLICYDB_SUCCESS;
797
0
}
798
799
static int write_cons_helper(policydb_t *p, constraint_node_t *node,
800
           int allowxtarget, struct policy_file *fp)
801
6.02k
{
802
6.02k
  constraint_node_t *c;
803
6.02k
  constraint_expr_t *e;
804
6.02k
  uint32_t buf[3], nexpr;
805
6.02k
  int items;
806
807
7.08k
  for (c = node; c; c = c->next) {
808
1.06k
    nexpr = 0;
809
4.75k
    for (e = c->expr; e; e = e->next) {
810
3.69k
      nexpr++;
811
3.69k
    }
812
1.06k
    buf[0] = cpu_to_le32(c->permissions);
813
1.06k
    buf[1] = cpu_to_le32(nexpr);
814
1.06k
    items = put_entry(buf, sizeof(uint32_t), 2, fp);
815
1.06k
    if (items != 2)
816
0
      return POLICYDB_ERROR;
817
4.75k
    for (e = c->expr; e; e = e->next) {
818
3.69k
      buf[0] = cpu_to_le32(e->expr_type);
819
3.69k
      buf[1] = cpu_to_le32(e->attr);
820
3.69k
      buf[2] = cpu_to_le32(e->op);
821
3.69k
      items = put_entry(buf, sizeof(uint32_t), 3, fp);
822
3.69k
      if (items != 3)
823
0
        return POLICYDB_ERROR;
824
825
3.69k
      switch (e->expr_type) {
826
3
      case CEXPR_NAMES:
827
3
        if (!allowxtarget && (e->attr & CEXPR_XTARGET))
828
0
          return POLICYDB_ERROR;
829
3
        if (ebitmap_write(&e->names, fp)) {
830
0
          return POLICYDB_ERROR;
831
0
        }
832
3
        if ((p->policy_type != POLICY_KERN &&
833
0
             type_set_write(e->type_names, fp)) ||
834
3
            (p->policy_type == POLICY_KERN &&
835
3
             (p->policyvers >=
836
3
              POLICYDB_VERSION_CONSTRAINT_NAMES) &&
837
1
             type_set_write(e->type_names, fp))) {
838
0
          return POLICYDB_ERROR;
839
0
        }
840
3
        break;
841
3.69k
      default:
842
3.69k
        break;
843
3.69k
      }
844
3.69k
    }
845
1.06k
  }
846
847
6.02k
  return POLICYDB_SUCCESS;
848
6.02k
}
849
850
static int class_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
851
3.01k
{
852
3.01k
  class_datum_t *cladatum;
853
3.01k
  constraint_node_t *c;
854
3.01k
  uint32_t buf[32], ncons;
855
3.01k
  size_t items, items2, len, len2;
856
3.01k
  struct policy_data *pd = ptr;
857
3.01k
  struct policy_file *fp = pd->fp;
858
3.01k
  struct policydb *p = pd->p;
859
860
3.01k
  cladatum = (class_datum_t *)datum;
861
862
3.01k
  len = strlen(key);
863
3.01k
  if (cladatum->comkey)
864
0
    len2 = strlen(cladatum->comkey);
865
3.01k
  else
866
3.01k
    len2 = 0;
867
868
3.01k
  ncons = 0;
869
4.03k
  for (c = cladatum->constraints; c; c = c->next) {
870
1.02k
    ncons++;
871
1.02k
  }
872
873
3.01k
  items = 0;
874
3.01k
  buf[items++] = cpu_to_le32(len);
875
3.01k
  buf[items++] = cpu_to_le32(len2);
876
3.01k
  buf[items++] = cpu_to_le32(cladatum->s.value);
877
3.01k
  buf[items++] = cpu_to_le32(cladatum->permissions.nprim);
878
3.01k
  if (cladatum->permissions.table)
879
3.01k
    buf[items++] = cpu_to_le32(cladatum->permissions.table->nel);
880
0
  else
881
0
    buf[items++] = 0;
882
3.01k
  buf[items++] = cpu_to_le32(ncons);
883
3.01k
  items2 = put_entry(buf, sizeof(uint32_t), items, fp);
884
3.01k
  if (items != items2)
885
0
    return POLICYDB_ERROR;
886
887
3.01k
  items = put_entry(key, 1, len, fp);
888
3.01k
  if (items != len)
889
0
    return POLICYDB_ERROR;
890
891
3.01k
  if (cladatum->comkey) {
892
0
    items = put_entry(cladatum->comkey, 1, len2, fp);
893
0
    if (items != len2)
894
0
      return POLICYDB_ERROR;
895
0
  }
896
3.01k
  if (hashtab_map(cladatum->permissions.table, perm_write, pd))
897
0
    return POLICYDB_ERROR;
898
899
3.01k
  if (write_cons_helper(p, cladatum->constraints, 0, fp))
900
0
    return POLICYDB_ERROR;
901
902
3.01k
  if ((p->policy_type == POLICY_KERN) ||
903
3.01k
      (p->policy_type == POLICY_BASE)) {
904
    /* write out the validatetrans rule */
905
3.01k
    ncons = 0;
906
3.05k
    for (c = cladatum->validatetrans; c; c = c->next) {
907
44
      ncons++;
908
44
    }
909
3.01k
    buf[0] = cpu_to_le32(ncons);
910
3.01k
    items = put_entry(buf, sizeof(uint32_t), 1, fp);
911
3.01k
    if (items != 1)
912
0
      return POLICYDB_ERROR;
913
3.01k
    if (write_cons_helper(p, cladatum->validatetrans, 1, fp))
914
0
      return POLICYDB_ERROR;
915
3.01k
  }
916
917
3.01k
  if ((p->policy_type == POLICY_KERN &&
918
3.00k
       p->policyvers >= POLICYDB_VERSION_NEW_OBJECT_DEFAULTS) ||
919
47
      (p->policy_type == POLICY_BASE &&
920
2.96k
       p->policyvers >= MOD_POLICYDB_VERSION_NEW_OBJECT_DEFAULTS)) {
921
2.96k
    char default_range = cladatum->default_range;
922
923
2.96k
    buf[0] = cpu_to_le32(cladatum->default_user);
924
2.96k
    buf[1] = cpu_to_le32(cladatum->default_role);
925
2.96k
    if (!glblub_version && default_range == DEFAULT_GLBLUB) {
926
70
      WARN(fp->handle,
927
70
           "class %s default_range set to GLBLUB but %spolicy version is %d (%d required), discarding",
928
70
           p->p_class_val_to_name[cladatum->s.value - 1],
929
70
           p->policy_type == POLICY_KERN ? "" : "module ",
930
70
           p->policyvers,
931
70
           p->policy_type == POLICY_KERN ?
932
70
             POLICYDB_VERSION_GLBLUB :
933
70
             MOD_POLICYDB_VERSION_GLBLUB);
934
70
      default_range = 0;
935
70
    }
936
2.96k
    buf[2] = cpu_to_le32(default_range);
937
2.96k
    items = put_entry(buf, sizeof(uint32_t), 3, fp);
938
2.96k
    if (items != 3)
939
0
      return POLICYDB_ERROR;
940
2.96k
  }
941
942
3.01k
  if ((p->policy_type == POLICY_KERN &&
943
3.00k
       p->policyvers >= POLICYDB_VERSION_DEFAULT_TYPE) ||
944
55
      (p->policy_type == POLICY_BASE &&
945
2.96k
       p->policyvers >= MOD_POLICYDB_VERSION_DEFAULT_TYPE)) {
946
2.96k
    buf[0] = cpu_to_le32(cladatum->default_type);
947
2.96k
    items = put_entry(buf, sizeof(uint32_t), 1, fp);
948
2.96k
    if (items != 1)
949
0
      return POLICYDB_ERROR;
950
2.96k
  }
951
952
3.01k
  return POLICYDB_SUCCESS;
953
3.01k
}
954
955
static int role_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
956
7.94k
{
957
7.94k
  role_datum_t *role;
958
7.94k
  uint32_t buf[32];
959
7.94k
  size_t items, items2, len;
960
7.94k
  struct policy_data *pd = ptr;
961
7.94k
  struct policy_file *fp = pd->fp;
962
7.94k
  struct policydb *p = pd->p;
963
964
7.94k
  role = (role_datum_t *)datum;
965
966
  /*
967
   * Role attributes are redundant for policy.X, skip them
968
   * when writing the roles symbol table. They are also skipped
969
   * when pp is downgraded.
970
   *
971
   * Their numbers would be deducted in policydb_write().
972
   */
973
7.94k
  if ((role->flavor == ROLE_ATTRIB) &&
974
164
      ((p->policy_type == POLICY_KERN) ||
975
0
       (p->policy_type != POLICY_KERN &&
976
0
        p->policyvers < MOD_POLICYDB_VERSION_ROLEATTRIB)))
977
164
    return POLICYDB_SUCCESS;
978
979
7.77k
  len = strlen(key);
980
7.77k
  items = 0;
981
7.77k
  buf[items++] = cpu_to_le32(len);
982
7.77k
  buf[items++] = cpu_to_le32(role->s.value);
983
7.77k
  buf[items++] = cpu_to_le32(role->bounds);
984
7.77k
  items2 = put_entry(buf, sizeof(uint32_t), items, fp);
985
7.77k
  if (items != items2)
986
0
    return POLICYDB_ERROR;
987
988
7.77k
  items = put_entry(key, 1, len, fp);
989
7.77k
  if (items != len)
990
0
    return POLICYDB_ERROR;
991
992
7.77k
  if (ebitmap_write(&role->dominates, fp))
993
0
    return POLICYDB_ERROR;
994
7.77k
  if (p->policy_type == POLICY_KERN) {
995
7.60k
    if (role->s.value == OBJECT_R_VAL) {
996
      /*
997
       * CIL populates object_r's types map
998
       * rather than handling it as a special case.
999
       * However, this creates an inconsistency with
1000
       * the kernel policy read from /sys/fs/selinux/policy
1001
       * because the kernel ignores everything except for
1002
       * object_r's value from the policy file.
1003
       * Make them consistent by writing an empty
1004
       * ebitmap instead.
1005
       */
1006
1.25k
      ebitmap_t empty;
1007
1.25k
      ebitmap_init(&empty);
1008
1.25k
      if (ebitmap_write(&empty, fp))
1009
0
        return POLICYDB_ERROR;
1010
6.35k
    } else {
1011
6.35k
      if (ebitmap_write(&role->types.types, fp))
1012
0
        return POLICYDB_ERROR;
1013
6.35k
    }
1014
7.60k
  } else {
1015
168
    if (type_set_write(&role->types, fp))
1016
0
      return POLICYDB_ERROR;
1017
168
  }
1018
1019
7.77k
  if (p->policy_type != POLICY_KERN &&
1020
168
      p->policyvers >= MOD_POLICYDB_VERSION_ROLEATTRIB) {
1021
116
    buf[0] = cpu_to_le32(role->flavor);
1022
116
    items = put_entry(buf, sizeof(uint32_t), 1, fp);
1023
116
    if (items != 1)
1024
0
      return POLICYDB_ERROR;
1025
1026
116
    if (ebitmap_write(&role->roles, fp))
1027
0
      return POLICYDB_ERROR;
1028
116
  }
1029
1030
7.77k
  return POLICYDB_SUCCESS;
1031
7.77k
}
1032
1033
static int type_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
1034
1.92k
{
1035
1.92k
  type_datum_t *typdatum;
1036
1.92k
  uint32_t buf[32];
1037
1.92k
  size_t items, items2, len;
1038
1.92k
  struct policy_data *pd = ptr;
1039
1.92k
  struct policy_file *fp = pd->fp;
1040
1.92k
  struct policydb *p = pd->p;
1041
1042
1.92k
  typdatum = (type_datum_t *)datum;
1043
1044
1.92k
  len = strlen(key);
1045
1.92k
  items = 0;
1046
1.92k
  buf[items++] = cpu_to_le32(len);
1047
1.92k
  buf[items++] = cpu_to_le32(typdatum->s.value);
1048
1049
1.92k
  if (p->policy_type != POLICY_KERN &&
1050
0
      p->policyvers < MOD_POLICYDB_VERSION_NEVERAUDIT &&
1051
0
      typdatum->flags & TYPE_FLAGS_NEVERAUDIT)
1052
1.92k
    WARN(fp->handle,
1053
1.92k
         "Warning! Module policy "
1054
1.92k
         "version %d cannot support neveraudit "
1055
1.92k
         "types, but one was defined",
1056
1.92k
         p->policyvers);
1057
1058
1.92k
  uint32_t properties = 0;
1059
1060
1.92k
  if (p->policy_type != POLICY_KERN)
1061
0
    buf[items++] = cpu_to_le32(typdatum->primary);
1062
1063
1.92k
  if (typdatum->primary)
1064
1.61k
    properties |= TYPEDATUM_PROPERTY_PRIMARY;
1065
1066
1.92k
  if (typdatum->flavor == TYPE_ATTRIB) {
1067
400
    properties |= TYPEDATUM_PROPERTY_ATTRIBUTE;
1068
1.52k
  } else if (typdatum->flavor == TYPE_ALIAS &&
1069
0
       p->policy_type != POLICY_KERN)
1070
0
    properties |= TYPEDATUM_PROPERTY_ALIAS;
1071
1072
1.92k
  if (typdatum->flags & TYPE_FLAGS_PERMISSIVE &&
1073
0
      p->policy_type != POLICY_KERN)
1074
0
    properties |= TYPEDATUM_PROPERTY_PERMISSIVE;
1075
1076
1.92k
  if (typdatum->flags & TYPE_FLAGS_NEVERAUDIT &&
1077
0
      p->policy_type != POLICY_KERN &&
1078
0
      p->policyvers >= MOD_POLICYDB_VERSION_NEVERAUDIT)
1079
0
    properties |= TYPEDATUM_PROPERTY_NEVERAUDIT;
1080
1081
1.92k
  buf[items++] = cpu_to_le32(properties);
1082
1.92k
  buf[items++] = cpu_to_le32(typdatum->bounds);
1083
1084
1.92k
  items2 = put_entry(buf, sizeof(uint32_t), items, fp);
1085
1.92k
  if (items != items2)
1086
0
    return POLICYDB_ERROR;
1087
1088
1.92k
  if (p->policy_type != POLICY_KERN) {
1089
0
    if (ebitmap_write(&typdatum->types, fp))
1090
0
      return POLICYDB_ERROR;
1091
0
  }
1092
1093
1.92k
  items = put_entry(key, 1, len, fp);
1094
1.92k
  if (items != len)
1095
0
    return POLICYDB_ERROR;
1096
1097
1.92k
  return POLICYDB_SUCCESS;
1098
1.92k
}
1099
1100
static int user_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
1101
635
{
1102
635
  user_datum_t *usrdatum;
1103
635
  uint32_t buf[32];
1104
635
  size_t items, items2, len;
1105
635
  struct policy_data *pd = ptr;
1106
635
  struct policy_file *fp = pd->fp;
1107
635
  struct policydb *p = pd->p;
1108
1109
635
  usrdatum = (user_datum_t *)datum;
1110
1111
635
  len = strlen(key);
1112
635
  items = 0;
1113
635
  buf[items++] = cpu_to_le32(len);
1114
635
  buf[items++] = cpu_to_le32(usrdatum->s.value);
1115
635
  buf[items++] = cpu_to_le32(usrdatum->bounds);
1116
635
  items2 = put_entry(buf, sizeof(uint32_t), items, fp);
1117
635
  if (items != items2)
1118
0
    return POLICYDB_ERROR;
1119
1120
635
  items = put_entry(key, 1, len, fp);
1121
635
  if (items != len)
1122
0
    return POLICYDB_ERROR;
1123
1124
635
  if (p->policy_type == POLICY_KERN) {
1125
576
    if (ebitmap_write(&usrdatum->roles.roles, fp))
1126
0
      return POLICYDB_ERROR;
1127
576
  } else {
1128
59
    if (role_set_write(&usrdatum->roles, fp))
1129
0
      return POLICYDB_ERROR;
1130
59
  }
1131
1132
635
  if (p->policy_type == POLICY_KERN) {
1133
576
    if (mls_write_range_helper(&usrdatum->exp_range, fp))
1134
0
      return POLICYDB_ERROR;
1135
576
    if (mls_write_level(&usrdatum->exp_dfltlevel, fp))
1136
0
      return POLICYDB_ERROR;
1137
576
  } else {
1138
59
    if (mls_write_semantic_range_helper(&usrdatum->range, fp))
1139
0
      return -1;
1140
59
    if (mls_write_semantic_level_helper(&usrdatum->dfltlevel, fp))
1141
0
      return -1;
1142
59
  }
1143
1144
635
  return POLICYDB_SUCCESS;
1145
635
}
1146
1147
static int (*const write_f[SYM_NUM])(hashtab_key_t key, hashtab_datum_t datum,
1148
             void *datap) = {
1149
  common_write, class_write,     role_write, type_write,
1150
  user_write,   cond_write_bool, sens_write, cat_write,
1151
};
1152
1153
static int ocontext_write_xen(const struct policydb_compat_info *info,
1154
            policydb_t *p, struct policy_file *fp)
1155
216
{
1156
216
  unsigned int i, j;
1157
216
  size_t nel, items, len;
1158
216
  uint32_t buf[32];
1159
216
  ocontext_t *c;
1160
1.50k
  for (i = 0; i < info->ocon_num; i++) {
1161
1.29k
    nel = 0;
1162
1.45k
    for (c = p->ocontexts[i]; c; c = c->next) {
1163
165
      if (i == OCON_XEN_ISID && !c->context[0].user) {
1164
0
        INFO(fp->handle,
1165
0
             "No context assigned to SID %s, omitting from policy",
1166
0
             c->u.name);
1167
0
        continue;
1168
0
      }
1169
165
      nel++;
1170
165
    }
1171
1.29k
    buf[0] = cpu_to_le32(nel);
1172
1.29k
    items = put_entry(buf, sizeof(uint32_t), 1, fp);
1173
1.29k
    if (items != 1)
1174
0
      return POLICYDB_ERROR;
1175
1.45k
    for (c = p->ocontexts[i]; c; c = c->next) {
1176
165
      switch (i) {
1177
165
      case OCON_XEN_ISID:
1178
165
        if (!c->context[0].user)
1179
0
          break;
1180
165
        buf[0] = cpu_to_le32(c->sid[0]);
1181
165
        items = put_entry(buf, sizeof(uint32_t), 1, fp);
1182
165
        if (items != 1)
1183
0
          return POLICYDB_ERROR;
1184
165
        if (context_write(p, &c->context[0], fp))
1185
0
          return POLICYDB_ERROR;
1186
165
        break;
1187
165
      case OCON_XEN_PIRQ:
1188
0
        buf[0] = cpu_to_le32(c->u.pirq);
1189
0
        items = put_entry(buf, sizeof(uint32_t), 1, fp);
1190
0
        if (items != 1)
1191
0
          return POLICYDB_ERROR;
1192
0
        if (context_write(p, &c->context[0], fp))
1193
0
          return POLICYDB_ERROR;
1194
0
        break;
1195
0
      case OCON_XEN_IOPORT:
1196
0
        buf[0] = c->u.ioport.low_ioport;
1197
0
        buf[1] = c->u.ioport.high_ioport;
1198
0
        for (j = 0; j < 2; j++)
1199
0
          buf[j] = cpu_to_le32(buf[j]);
1200
0
        items = put_entry(buf, sizeof(uint32_t), 2, fp);
1201
0
        if (items != 2)
1202
0
          return POLICYDB_ERROR;
1203
0
        if (context_write(p, &c->context[0], fp))
1204
0
          return POLICYDB_ERROR;
1205
0
        break;
1206
0
      case OCON_XEN_IOMEM:
1207
0
        if (p->policyvers >=
1208
0
            POLICYDB_VERSION_XEN_DEVICETREE) {
1209
0
          uint64_t b64[2];
1210
0
          b64[0] = c->u.iomem.low_iomem;
1211
0
          b64[1] = c->u.iomem.high_iomem;
1212
0
          for (j = 0; j < 2; j++)
1213
0
            b64[j] = cpu_to_le64(b64[j]);
1214
0
          items = put_entry(b64, sizeof(uint64_t),
1215
0
                2, fp);
1216
0
          if (items != 2)
1217
0
            return POLICYDB_ERROR;
1218
0
        } else {
1219
0
          if (c->u.iomem.high_iomem >
1220
0
              0xFFFFFFFFULL) {
1221
0
            ERR(fp->handle,
1222
0
                "policy version %d"
1223
0
                " cannot represent IOMEM addresses over 16TB",
1224
0
                p->policyvers);
1225
0
            return POLICYDB_ERROR;
1226
0
          }
1227
1228
0
          buf[0] = c->u.iomem.low_iomem;
1229
0
          buf[1] = c->u.iomem.high_iomem;
1230
0
          for (j = 0; j < 2; j++)
1231
0
            buf[j] = cpu_to_le32(buf[j]);
1232
0
          items = put_entry(buf, sizeof(uint32_t),
1233
0
                2, fp);
1234
0
          if (items != 2)
1235
0
            return POLICYDB_ERROR;
1236
0
        }
1237
0
        if (context_write(p, &c->context[0], fp))
1238
0
          return POLICYDB_ERROR;
1239
0
        break;
1240
0
      case OCON_XEN_PCIDEVICE:
1241
0
        buf[0] = cpu_to_le32(c->u.device);
1242
0
        items = put_entry(buf, sizeof(uint32_t), 1, fp);
1243
0
        if (items != 1)
1244
0
          return POLICYDB_ERROR;
1245
0
        if (context_write(p, &c->context[0], fp))
1246
0
          return POLICYDB_ERROR;
1247
0
        break;
1248
0
      case OCON_XEN_DEVICETREE:
1249
0
        len = strlen(c->u.name);
1250
0
        buf[0] = cpu_to_le32(len);
1251
0
        items = put_entry(buf, sizeof(uint32_t), 1, fp);
1252
0
        if (items != 1)
1253
0
          return POLICYDB_ERROR;
1254
0
        items = put_entry(c->u.name, 1, len, fp);
1255
0
        if (items != len)
1256
0
          return POLICYDB_ERROR;
1257
0
        if (context_write(p, &c->context[0], fp))
1258
0
          return POLICYDB_ERROR;
1259
0
        break;
1260
165
      }
1261
165
    }
1262
1.29k
  }
1263
216
  return POLICYDB_SUCCESS;
1264
216
}
1265
1266
static int ocontext_write_selinux(const struct policydb_compat_info *info,
1267
          policydb_t *p, struct policy_file *fp)
1268
1.20k
{
1269
1.20k
  unsigned int i, j;
1270
1.20k
  size_t nel, items, len;
1271
1.20k
  uint32_t buf[32];
1272
1.20k
  ocontext_t *c;
1273
11.5k
  for (i = 0; i < info->ocon_num; i++) {
1274
10.3k
    nel = 0;
1275
10.8k
    for (c = p->ocontexts[i]; c; c = c->next) {
1276
508
      if (i == OCON_ISID && !c->context[0].user) {
1277
0
        INFO(fp->handle,
1278
0
             "No context assigned to SID %s, omitting from policy",
1279
0
             c->u.name);
1280
0
        continue;
1281
0
      }
1282
508
      nel++;
1283
508
    }
1284
10.3k
    buf[0] = cpu_to_le32(nel);
1285
10.3k
    items = put_entry(buf, sizeof(uint32_t), 1, fp);
1286
10.3k
    if (items != 1)
1287
0
      return POLICYDB_ERROR;
1288
10.8k
    for (c = p->ocontexts[i]; c; c = c->next) {
1289
508
      switch (i) {
1290
460
      case OCON_ISID:
1291
460
        if (!c->context[0].user)
1292
0
          break;
1293
460
        buf[0] = cpu_to_le32(c->sid[0]);
1294
460
        items = put_entry(buf, sizeof(uint32_t), 1, fp);
1295
460
        if (items != 1)
1296
0
          return POLICYDB_ERROR;
1297
460
        if (context_write(p, &c->context[0], fp))
1298
0
          return POLICYDB_ERROR;
1299
460
        break;
1300
460
      case OCON_FS:
1301
0
      case OCON_NETIF:
1302
0
        len = strlen(c->u.name);
1303
0
        buf[0] = cpu_to_le32(len);
1304
0
        items = put_entry(buf, sizeof(uint32_t), 1, fp);
1305
0
        if (items != 1)
1306
0
          return POLICYDB_ERROR;
1307
0
        items = put_entry(c->u.name, 1, len, fp);
1308
0
        if (items != len)
1309
0
          return POLICYDB_ERROR;
1310
0
        if (context_write(p, &c->context[0], fp))
1311
0
          return POLICYDB_ERROR;
1312
0
        if (context_write(p, &c->context[1], fp))
1313
0
          return POLICYDB_ERROR;
1314
0
        break;
1315
10
      case OCON_IBPKEY:
1316
        /* The subnet prefix is in network order */
1317
10
        memcpy(buf, &c->u.ibpkey.subnet_prefix,
1318
10
               sizeof(c->u.ibpkey.subnet_prefix));
1319
1320
10
        buf[2] = cpu_to_le32(c->u.ibpkey.low_pkey);
1321
10
        buf[3] = cpu_to_le32(c->u.ibpkey.high_pkey);
1322
1323
10
        items = put_entry(buf, sizeof(uint32_t), 4, fp);
1324
10
        if (items != 4)
1325
0
          return POLICYDB_ERROR;
1326
1327
10
        if (context_write(p, &c->context[0], fp))
1328
0
          return POLICYDB_ERROR;
1329
10
        break;
1330
10
      case OCON_IBENDPORT:
1331
0
        len = strlen(c->u.ibendport.dev_name);
1332
0
        buf[0] = cpu_to_le32(len);
1333
0
        buf[1] = cpu_to_le32(c->u.ibendport.port);
1334
0
        items = put_entry(buf, sizeof(uint32_t), 2, fp);
1335
0
        if (items != 2)
1336
0
          return POLICYDB_ERROR;
1337
0
        items = put_entry(c->u.ibendport.dev_name, 1,
1338
0
              len, fp);
1339
0
        if (items != len)
1340
0
          return POLICYDB_ERROR;
1341
1342
0
        if (context_write(p, &c->context[0], fp))
1343
0
          return POLICYDB_ERROR;
1344
0
        break;
1345
0
      case OCON_PORT:
1346
0
        buf[0] = c->u.port.protocol;
1347
0
        buf[1] = c->u.port.low_port;
1348
0
        buf[2] = c->u.port.high_port;
1349
0
        for (j = 0; j < 3; j++) {
1350
0
          buf[j] = cpu_to_le32(buf[j]);
1351
0
        }
1352
0
        items = put_entry(buf, sizeof(uint32_t), 3, fp);
1353
0
        if (items != 3)
1354
0
          return POLICYDB_ERROR;
1355
0
        if (context_write(p, &c->context[0], fp))
1356
0
          return POLICYDB_ERROR;
1357
0
        break;
1358
0
      case OCON_NODE:
1359
0
        buf[0] = c->u.node.addr; /* network order */
1360
0
        buf[1] = c->u.node.mask; /* network order */
1361
0
        items = put_entry(buf, sizeof(uint32_t), 2, fp);
1362
0
        if (items != 2)
1363
0
          return POLICYDB_ERROR;
1364
0
        if (context_write(p, &c->context[0], fp))
1365
0
          return POLICYDB_ERROR;
1366
0
        break;
1367
32
      case OCON_FSUSE:
1368
32
        buf[0] = cpu_to_le32(c->v.behavior);
1369
32
        len = strlen(c->u.name);
1370
32
        buf[1] = cpu_to_le32(len);
1371
32
        items = put_entry(buf, sizeof(uint32_t), 2, fp);
1372
32
        if (items != 2)
1373
0
          return POLICYDB_ERROR;
1374
32
        items = put_entry(c->u.name, 1, len, fp);
1375
32
        if (items != len)
1376
0
          return POLICYDB_ERROR;
1377
32
        if (context_write(p, &c->context[0], fp))
1378
0
          return POLICYDB_ERROR;
1379
32
        break;
1380
32
      case OCON_NODE6:
1381
30
        for (j = 0; j < 4; j++)
1382
24
          buf[j] =
1383
24
            c->u.node6.addr
1384
24
              [j]; /* network order */
1385
30
        for (j = 0; j < 4; j++)
1386
24
          buf[j + 4] =
1387
24
            c->u.node6.mask
1388
24
              [j]; /* network order */
1389
6
        items = put_entry(buf, sizeof(uint32_t), 8, fp);
1390
6
        if (items != 8)
1391
0
          return POLICYDB_ERROR;
1392
6
        if (context_write(p, &c->context[0], fp))
1393
0
          return POLICYDB_ERROR;
1394
6
        break;
1395
508
      }
1396
508
    }
1397
10.3k
  }
1398
1.20k
  return POLICYDB_SUCCESS;
1399
1.20k
}
1400
1401
static int ocontext_write(const struct policydb_compat_info *info,
1402
        policydb_t *p, struct policy_file *fp)
1403
1.42k
{
1404
1.42k
  int rc = POLICYDB_ERROR;
1405
1.42k
  switch (p->target_platform) {
1406
1.20k
  case SEPOL_TARGET_SELINUX:
1407
1.20k
    rc = ocontext_write_selinux(info, p, fp);
1408
1.20k
    break;
1409
216
  case SEPOL_TARGET_XEN:
1410
216
    rc = ocontext_write_xen(info, p, fp);
1411
216
    break;
1412
1.42k
  }
1413
1.42k
  return rc;
1414
1.42k
}
1415
1416
static int genfs_write(policydb_t *p, struct policy_file *fp)
1417
1.42k
{
1418
1.42k
  genfs_t *genfs;
1419
1.42k
  ocontext_t *c;
1420
1.42k
  size_t nel = 0, items, len;
1421
1.42k
  uint32_t buf[32];
1422
1423
1.42k
  for (genfs = p->genfs; genfs; genfs = genfs->next)
1424
3
    nel++;
1425
1.42k
  buf[0] = cpu_to_le32(nel);
1426
1.42k
  items = put_entry(buf, sizeof(uint32_t), 1, fp);
1427
1.42k
  if (items != 1)
1428
0
    return POLICYDB_ERROR;
1429
1.42k
  for (genfs = p->genfs; genfs; genfs = genfs->next) {
1430
3
    len = strlen(genfs->fstype);
1431
3
    buf[0] = cpu_to_le32(len);
1432
3
    items = put_entry(buf, sizeof(uint32_t), 1, fp);
1433
3
    if (items != 1)
1434
0
      return POLICYDB_ERROR;
1435
3
    items = put_entry(genfs->fstype, 1, len, fp);
1436
3
    if (items != len)
1437
0
      return POLICYDB_ERROR;
1438
3
    nel = 0;
1439
3
    for (c = genfs->head; c; c = c->next)
1440
0
      nel++;
1441
3
    buf[0] = cpu_to_le32(nel);
1442
3
    items = put_entry(buf, sizeof(uint32_t), 1, fp);
1443
3
    if (items != 1)
1444
0
      return POLICYDB_ERROR;
1445
3
    for (c = genfs->head; c; c = c->next) {
1446
0
      len = strlen(c->u.name);
1447
0
      buf[0] = cpu_to_le32(len);
1448
0
      items = put_entry(buf, sizeof(uint32_t), 1, fp);
1449
0
      if (items != 1)
1450
0
        return POLICYDB_ERROR;
1451
0
      items = put_entry(c->u.name, 1, len, fp);
1452
0
      if (items != len)
1453
0
        return POLICYDB_ERROR;
1454
0
      buf[0] = cpu_to_le32(c->v.sclass);
1455
0
      items = put_entry(buf, sizeof(uint32_t), 1, fp);
1456
0
      if (items != 1)
1457
0
        return POLICYDB_ERROR;
1458
0
      if (context_write(p, &c->context[0], fp))
1459
0
        return POLICYDB_ERROR;
1460
0
    }
1461
3
  }
1462
1.42k
  return POLICYDB_SUCCESS;
1463
1.42k
}
1464
1465
struct rangetrans_write_args {
1466
  size_t nel;
1467
  int new_rangetr;
1468
  struct policy_file *fp;
1469
  struct policydb *p;
1470
};
1471
1472
static int rangetrans_count(hashtab_key_t key,
1473
          void *data __attribute__((unused)), void *ptr)
1474
0
{
1475
0
  struct range_trans *rt = (struct range_trans *)key;
1476
0
  struct rangetrans_write_args *args = ptr;
1477
0
  struct policydb *p = args->p;
1478
1479
  /* all range_transitions are written for the new format, only
1480
     process related range_transitions are written for the old
1481
     format, so count accordingly */
1482
0
  if (args->new_rangetr || rt->target_class == p->process_class)
1483
0
    args->nel++;
1484
0
  return 0;
1485
0
}
1486
1487
static int range_write_helper(hashtab_key_t key, void *data, void *ptr)
1488
0
{
1489
0
  uint32_t buf[2];
1490
0
  struct range_trans *rt = (struct range_trans *)key;
1491
0
  struct mls_range *r = data;
1492
0
  struct rangetrans_write_args *args = ptr;
1493
0
  struct policy_file *fp = args->fp;
1494
0
  struct policydb *p = args->p;
1495
0
  int new_rangetr = args->new_rangetr;
1496
0
  size_t items;
1497
0
  static int warning_issued = 0;
1498
0
  int rc;
1499
1500
0
  if (!new_rangetr && rt->target_class != p->process_class) {
1501
0
    if (!warning_issued)
1502
0
      WARN(fp->handle,
1503
0
           "Discarding range_transition "
1504
0
           "rules for security classes other than "
1505
0
           "\"process\"");
1506
0
    warning_issued = 1;
1507
0
    return 0;
1508
0
  }
1509
1510
0
  buf[0] = cpu_to_le32(rt->source_type);
1511
0
  buf[1] = cpu_to_le32(rt->target_type);
1512
0
  items = put_entry(buf, sizeof(uint32_t), 2, fp);
1513
0
  if (items != 2)
1514
0
    return POLICYDB_ERROR;
1515
0
  if (new_rangetr) {
1516
0
    buf[0] = cpu_to_le32(rt->target_class);
1517
0
    items = put_entry(buf, sizeof(uint32_t), 1, fp);
1518
0
    if (items != 1)
1519
0
      return POLICYDB_ERROR;
1520
0
  }
1521
0
  rc = mls_write_range_helper(r, fp);
1522
0
  if (rc)
1523
0
    return rc;
1524
1525
0
  return 0;
1526
0
}
1527
1528
static int range_write(policydb_t *p, struct policy_file *fp)
1529
1.25k
{
1530
1.25k
  size_t items;
1531
1.25k
  uint32_t buf[2];
1532
1.25k
  int new_rangetr = (p->policy_type == POLICY_KERN);
1533
1.25k
  struct rangetrans_write_args args;
1534
1.25k
  int rc;
1535
1536
1.25k
  args.nel = 0;
1537
1.25k
  args.new_rangetr = new_rangetr;
1538
1.25k
  args.fp = fp;
1539
1.25k
  args.p = p;
1540
1.25k
  rc = hashtab_map(p->range_tr, rangetrans_count, &args);
1541
1.25k
  if (rc)
1542
0
    return rc;
1543
1544
1.25k
  buf[0] = cpu_to_le32(args.nel);
1545
1.25k
  items = put_entry(buf, sizeof(uint32_t), 1, fp);
1546
1.25k
  if (items != 1)
1547
0
    return POLICYDB_ERROR;
1548
1549
1.25k
  return hashtab_map(p->range_tr, range_write_helper, &args);
1550
1.25k
}
1551
1552
/************** module writing functions below **************/
1553
1554
static int avrule_write(policydb_t *p, avrule_t *avrule, struct policy_file *fp,
1555
      unsigned conditional)
1556
40
{
1557
40
  size_t items, items2;
1558
40
  uint32_t buf[32], len;
1559
40
  class_perm_node_t *cur;
1560
1561
40
  if (p->policyvers < MOD_POLICYDB_VERSION_SELF_TYPETRANS &&
1562
40
      (avrule->specified & AVRULE_TYPE) && (avrule->flags & RULE_SELF)) {
1563
0
    ERR(fp->handle,
1564
0
        "Module contains a self rule not supported by the target module policy version");
1565
0
    return POLICYDB_ERROR;
1566
0
  }
1567
1568
40
  items = 0;
1569
40
  buf[items++] = cpu_to_le32(avrule->specified);
1570
40
  buf[items++] = cpu_to_le32(avrule->flags);
1571
40
  items2 = put_entry(buf, sizeof(uint32_t), items, fp);
1572
40
  if (items2 != items)
1573
0
    return POLICYDB_ERROR;
1574
1575
40
  if (type_set_write(&avrule->stypes, fp))
1576
0
    return POLICYDB_ERROR;
1577
1578
40
  if (type_set_write(&avrule->ttypes, fp))
1579
0
    return POLICYDB_ERROR;
1580
1581
40
  cur = avrule->perms;
1582
40
  len = 0;
1583
40
  while (cur) {
1584
0
    len++;
1585
0
    cur = cur->next;
1586
0
  }
1587
40
  items = 0;
1588
40
  buf[items++] = cpu_to_le32(len);
1589
40
  items2 = put_entry(buf, sizeof(uint32_t), items, fp);
1590
40
  if (items2 != items)
1591
0
    return POLICYDB_ERROR;
1592
40
  cur = avrule->perms;
1593
40
  while (cur) {
1594
0
    items = 0;
1595
0
    buf[items++] = cpu_to_le32(cur->tclass);
1596
0
    buf[items++] = cpu_to_le32(cur->data);
1597
0
    items2 = put_entry(buf, sizeof(uint32_t), items, fp);
1598
0
    if (items2 != items)
1599
0
      return POLICYDB_ERROR;
1600
1601
0
    cur = cur->next;
1602
0
  }
1603
1604
40
  if (avrule->specified & AVRULE_XPERMS) {
1605
0
    size_t nel = ARRAY_SIZE(avrule->xperms->perms);
1606
0
    uint32_t buf32[nel];
1607
0
    uint8_t buf8;
1608
0
    unsigned int i;
1609
1610
0
    if (p->policyvers < MOD_POLICYDB_VERSION_XPERMS_IOCTL) {
1611
0
      ERR(fp->handle,
1612
0
          "module policy version %u does not support"
1613
0
          " extended permissions rules and one was specified",
1614
0
          p->policyvers);
1615
0
      return POLICYDB_ERROR;
1616
0
    }
1617
1618
0
    if (conditional && !policydb_has_cond_xperms_feature(p)) {
1619
0
      ERR(fp->handle,
1620
0
          "module policy version %u does not support"
1621
0
          " extended permissions rules in conditional policies and one was specified",
1622
0
          p->policyvers);
1623
0
      return POLICYDB_ERROR;
1624
0
    }
1625
1626
0
    if (p->target_platform != SEPOL_TARGET_SELINUX) {
1627
0
      ERR(fp->handle,
1628
0
          "Target platform %s does not support"
1629
0
          " extended permissions rules and one was specified",
1630
0
          policydb_target_strings[p->target_platform]);
1631
0
      return POLICYDB_ERROR;
1632
0
    }
1633
1634
0
    buf8 = avrule->xperms->specified;
1635
0
    items = put_entry(&buf8, sizeof(uint8_t), 1, fp);
1636
0
    if (items != 1)
1637
0
      return POLICYDB_ERROR;
1638
0
    buf8 = avrule->xperms->driver;
1639
0
    items = put_entry(&buf8, sizeof(uint8_t), 1, fp);
1640
0
    if (items != 1)
1641
0
      return POLICYDB_ERROR;
1642
0
    for (i = 0; i < nel; i++)
1643
0
      buf32[i] = cpu_to_le32(avrule->xperms->perms[i]);
1644
0
    items = put_entry(buf32, sizeof(uint32_t), nel, fp);
1645
0
    if (items != nel)
1646
0
      return POLICYDB_ERROR;
1647
0
  }
1648
1649
40
  return POLICYDB_SUCCESS;
1650
40
}
1651
1652
static int avrule_write_list(policydb_t *p, avrule_t *avrules,
1653
           struct policy_file *fp, unsigned conditional)
1654
240
{
1655
240
  uint32_t buf[32], len;
1656
240
  avrule_t *avrule;
1657
1658
240
  avrule = avrules;
1659
240
  len = 0;
1660
280
  while (avrule) {
1661
40
    len++;
1662
40
    avrule = avrule->next;
1663
40
  }
1664
1665
240
  buf[0] = cpu_to_le32(len);
1666
240
  if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1)
1667
0
    return POLICYDB_ERROR;
1668
1669
240
  avrule = avrules;
1670
280
  while (avrule) {
1671
40
    if (avrule_write(p, avrule, fp, conditional))
1672
0
      return POLICYDB_ERROR;
1673
40
    avrule = avrule->next;
1674
40
  }
1675
1676
240
  return POLICYDB_SUCCESS;
1677
240
}
1678
1679
static int only_process(ebitmap_t *in, struct policydb *p)
1680
0
{
1681
0
  unsigned int i, value;
1682
0
  ebitmap_node_t *node;
1683
1684
0
  if (!p->process_class)
1685
0
    return 0;
1686
1687
0
  value = p->process_class - 1;
1688
1689
0
  ebitmap_for_each_positive_bit(in, node, i) {
1690
0
    if (i != value)
1691
0
      return 0;
1692
0
  }
1693
0
  return 1;
1694
0
}
1695
1696
static int role_trans_rule_write(policydb_t *p, role_trans_rule_t *t,
1697
         struct policy_file *fp)
1698
240
{
1699
240
  int nel = 0;
1700
240
  size_t items;
1701
240
  uint32_t buf[1];
1702
240
  role_trans_rule_t *tr;
1703
240
  int warned = 0;
1704
240
  int new_role = p->policyvers >= MOD_POLICYDB_VERSION_ROLETRANS;
1705
1706
244
  for (tr = t; tr; tr = tr->next)
1707
4
    if (new_role || only_process(&tr->classes, p))
1708
4
      nel++;
1709
1710
240
  buf[0] = cpu_to_le32(nel);
1711
240
  items = put_entry(buf, sizeof(uint32_t), 1, fp);
1712
240
  if (items != 1)
1713
0
    return POLICYDB_ERROR;
1714
244
  for (tr = t; tr; tr = tr->next) {
1715
4
    if (!new_role && !only_process(&tr->classes, p)) {
1716
0
      if (!warned)
1717
0
        WARN(fp->handle,
1718
0
             "Discarding role_transition "
1719
0
             "rules for security classes other than "
1720
0
             "\"process\"");
1721
0
      warned = 1;
1722
0
      continue;
1723
0
    }
1724
4
    if (role_set_write(&tr->roles, fp))
1725
0
      return POLICYDB_ERROR;
1726
4
    if (type_set_write(&tr->types, fp))
1727
0
      return POLICYDB_ERROR;
1728
4
    if (new_role)
1729
4
      if (ebitmap_write(&tr->classes, fp))
1730
0
        return POLICYDB_ERROR;
1731
4
    buf[0] = cpu_to_le32(tr->new_role);
1732
4
    items = put_entry(buf, sizeof(uint32_t), 1, fp);
1733
4
    if (items != 1)
1734
0
      return POLICYDB_ERROR;
1735
4
  }
1736
240
  return POLICYDB_SUCCESS;
1737
240
}
1738
1739
static int role_allow_rule_write(role_allow_rule_t *r, struct policy_file *fp)
1740
240
{
1741
240
  int nel = 0;
1742
240
  size_t items;
1743
240
  uint32_t buf[1];
1744
240
  role_allow_rule_t *ra;
1745
1746
302
  for (ra = r; ra; ra = ra->next)
1747
62
    nel++;
1748
240
  buf[0] = cpu_to_le32(nel);
1749
240
  items = put_entry(buf, sizeof(uint32_t), 1, fp);
1750
240
  if (items != 1)
1751
0
    return POLICYDB_ERROR;
1752
302
  for (ra = r; ra; ra = ra->next) {
1753
62
    if (role_set_write(&ra->roles, fp))
1754
0
      return POLICYDB_ERROR;
1755
62
    if (role_set_write(&ra->new_roles, fp))
1756
0
      return POLICYDB_ERROR;
1757
62
  }
1758
240
  return POLICYDB_SUCCESS;
1759
240
}
1760
1761
static int filename_trans_rule_write(policydb_t *p, filename_trans_rule_t *t,
1762
             struct policy_file *fp)
1763
189
{
1764
189
  int nel = 0;
1765
189
  size_t items, entries;
1766
189
  uint32_t buf[3], len;
1767
189
  filename_trans_rule_t *ftr;
1768
1769
189
  for (ftr = t; ftr; ftr = ftr->next)
1770
0
    nel++;
1771
1772
189
  buf[0] = cpu_to_le32(nel);
1773
189
  items = put_entry(buf, sizeof(uint32_t), 1, fp);
1774
189
  if (items != 1)
1775
0
    return POLICYDB_ERROR;
1776
1777
189
  for (ftr = t; ftr; ftr = ftr->next) {
1778
0
    len = strlen(ftr->name);
1779
0
    buf[0] = cpu_to_le32(len);
1780
0
    items = put_entry(buf, sizeof(uint32_t), 1, fp);
1781
0
    if (items != 1)
1782
0
      return POLICYDB_ERROR;
1783
1784
0
    items = put_entry(ftr->name, sizeof(char), len, fp);
1785
0
    if (items != len)
1786
0
      return POLICYDB_ERROR;
1787
1788
0
    if (type_set_write(&ftr->stypes, fp))
1789
0
      return POLICYDB_ERROR;
1790
0
    if (type_set_write(&ftr->ttypes, fp))
1791
0
      return POLICYDB_ERROR;
1792
1793
0
    buf[0] = cpu_to_le32(ftr->tclass);
1794
0
    buf[1] = cpu_to_le32(ftr->otype);
1795
0
    buf[2] = cpu_to_le32(ftr->flags);
1796
1797
0
    if (p->policyvers >= MOD_POLICYDB_VERSION_SELF_TYPETRANS) {
1798
0
      entries = 3;
1799
0
    } else if (!(ftr->flags & RULE_SELF)) {
1800
0
      entries = 2;
1801
0
    } else {
1802
0
      ERR(fp->handle,
1803
0
          "Module contains a self rule not supported by the target module policy version");
1804
0
      return POLICYDB_ERROR;
1805
0
    }
1806
1807
0
    items = put_entry(buf, sizeof(uint32_t), entries, fp);
1808
0
    if (items != entries)
1809
0
      return POLICYDB_ERROR;
1810
0
  }
1811
189
  return POLICYDB_SUCCESS;
1812
189
}
1813
1814
static int range_trans_rule_write(range_trans_rule_t *t, struct policy_file *fp)
1815
240
{
1816
240
  int nel = 0;
1817
240
  size_t items;
1818
240
  uint32_t buf[1];
1819
240
  range_trans_rule_t *rt;
1820
1821
240
  for (rt = t; rt; rt = rt->next)
1822
0
    nel++;
1823
240
  buf[0] = cpu_to_le32(nel);
1824
240
  items = put_entry(buf, sizeof(uint32_t), 1, fp);
1825
240
  if (items != 1)
1826
0
    return POLICYDB_ERROR;
1827
240
  for (rt = t; rt; rt = rt->next) {
1828
0
    if (type_set_write(&rt->stypes, fp))
1829
0
      return POLICYDB_ERROR;
1830
0
    if (type_set_write(&rt->ttypes, fp))
1831
0
      return POLICYDB_ERROR;
1832
0
    if (ebitmap_write(&rt->tclasses, fp))
1833
0
      return POLICYDB_ERROR;
1834
0
    if (mls_write_semantic_range_helper(&rt->trange, fp))
1835
0
      return POLICYDB_ERROR;
1836
0
  }
1837
240
  return POLICYDB_SUCCESS;
1838
240
}
1839
1840
static int scope_index_write(scope_index_t *scope_index,
1841
           unsigned int num_scope_syms,
1842
           struct policy_file *fp)
1843
480
{
1844
480
  unsigned int i;
1845
480
  uint32_t buf[1];
1846
4.32k
  for (i = 0; i < num_scope_syms; i++) {
1847
3.84k
    if (ebitmap_write(scope_index->scope + i, fp) == -1) {
1848
0
      return POLICYDB_ERROR;
1849
0
    }
1850
3.84k
  }
1851
480
  buf[0] = cpu_to_le32(scope_index->class_perms_len);
1852
480
  if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1) {
1853
0
    return POLICYDB_ERROR;
1854
0
  }
1855
481
  for (i = 0; i < scope_index->class_perms_len; i++) {
1856
1
    if (ebitmap_write(scope_index->class_perms_map + i, fp) == -1) {
1857
0
      return POLICYDB_ERROR;
1858
0
    }
1859
1
  }
1860
480
  return POLICYDB_SUCCESS;
1861
480
}
1862
1863
static int avrule_decl_write(avrule_decl_t *decl, int num_scope_syms,
1864
           policydb_t *p, struct policy_file *fp)
1865
240
{
1866
240
  struct policy_data pd;
1867
240
  uint32_t buf[2];
1868
240
  int i;
1869
240
  buf[0] = cpu_to_le32(decl->decl_id);
1870
240
  buf[1] = cpu_to_le32(decl->enabled);
1871
240
  if (put_entry(buf, sizeof(uint32_t), 2, fp) != 2) {
1872
0
    return POLICYDB_ERROR;
1873
0
  }
1874
240
  if (cond_write_list(p, decl->cond_list, fp) == -1 ||
1875
240
      avrule_write_list(p, decl->avrules, fp, 0) == -1 ||
1876
240
      role_trans_rule_write(p, decl->role_tr_rules, fp) == -1 ||
1877
240
      role_allow_rule_write(decl->role_allow_rules, fp) == -1) {
1878
0
    return POLICYDB_ERROR;
1879
0
  }
1880
1881
240
  if (p->policyvers >= MOD_POLICYDB_VERSION_FILENAME_TRANS &&
1882
189
      filename_trans_rule_write(p, decl->filename_trans_rules, fp))
1883
0
    return POLICYDB_ERROR;
1884
1885
240
  if (range_trans_rule_write(decl->range_tr_rules, fp) == -1) {
1886
0
    return POLICYDB_ERROR;
1887
0
  }
1888
240
  if (scope_index_write(&decl->required, num_scope_syms, fp) == -1 ||
1889
240
      scope_index_write(&decl->declared, num_scope_syms, fp) == -1) {
1890
0
    return POLICYDB_ERROR;
1891
0
  }
1892
240
  pd.fp = fp;
1893
240
  pd.p = p;
1894
2.16k
  for (i = 0; i < num_scope_syms; i++) {
1895
1.92k
    buf[0] = cpu_to_le32(decl->symtab[i].nprim);
1896
1.92k
    buf[1] = cpu_to_le32(decl->symtab[i].table->nel);
1897
1.92k
    if (put_entry(buf, sizeof(uint32_t), 2, fp) != 2) {
1898
0
      return POLICYDB_ERROR;
1899
0
    }
1900
1.92k
    if (hashtab_map(decl->symtab[i].table, write_f[i], &pd)) {
1901
0
      return POLICYDB_ERROR;
1902
0
    }
1903
1.92k
  }
1904
240
  return POLICYDB_SUCCESS;
1905
240
}
1906
1907
static int avrule_block_write(avrule_block_t *block, int num_scope_syms,
1908
            policydb_t *p, struct policy_file *fp)
1909
167
{
1910
  /* first write a count of the total number of blocks */
1911
167
  uint32_t buf[1], num_blocks = 0;
1912
167
  avrule_block_t *cur;
1913
1.86k
  for (cur = block; cur != NULL; cur = cur->next) {
1914
1.69k
    num_blocks++;
1915
1.69k
  }
1916
167
  buf[0] = cpu_to_le32(num_blocks);
1917
167
  if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1) {
1918
0
    return POLICYDB_ERROR;
1919
0
  }
1920
1921
  /* now write each block */
1922
1.86k
  for (cur = block; cur != NULL; cur = cur->next) {
1923
1.69k
    uint32_t num_decls = 0;
1924
1.69k
    avrule_decl_t *decl;
1925
    /* write a count of number of branches */
1926
1.93k
    for (decl = cur->branch_list; decl != NULL; decl = decl->next) {
1927
240
      num_decls++;
1928
240
    }
1929
1.69k
    buf[0] = cpu_to_le32(num_decls);
1930
1.69k
    if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1) {
1931
0
      return POLICYDB_ERROR;
1932
0
    }
1933
1.93k
    for (decl = cur->branch_list; decl != NULL; decl = decl->next) {
1934
240
      if (avrule_decl_write(decl, num_scope_syms, p, fp) ==
1935
240
          -1) {
1936
0
        return POLICYDB_ERROR;
1937
0
      }
1938
240
    }
1939
1.69k
  }
1940
167
  return POLICYDB_SUCCESS;
1941
167
}
1942
1943
static int scope_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
1944
175
{
1945
175
  scope_datum_t *scope = (scope_datum_t *)datum;
1946
175
  struct policy_data *pd = ptr;
1947
175
  struct policy_file *fp = pd->fp;
1948
175
  uint32_t static_buf[32], *dyn_buf = NULL, *buf;
1949
175
  size_t key_len = strlen(key);
1950
175
  size_t items = 2 + scope->decl_ids_len;
1951
175
  uint32_t i;
1952
175
  int rc;
1953
1954
175
  buf = static_buf;
1955
175
  if (items >= (sizeof(static_buf) / 4)) {
1956
    /* too many things required, so dynamically create a
1957
     * buffer.  this would have been easier with C99's
1958
     * dynamic arrays... */
1959
0
    rc = POLICYDB_ERROR;
1960
0
    dyn_buf = calloc(items, sizeof(*dyn_buf));
1961
0
    if (!dyn_buf)
1962
0
      goto err;
1963
0
    buf = dyn_buf;
1964
0
  }
1965
175
  buf[0] = cpu_to_le32(key_len);
1966
1967
175
  rc = POLICYDB_ERROR;
1968
175
  if (put_entry(buf, sizeof(*buf), 1, fp) != 1 ||
1969
175
      put_entry(key, 1, key_len, fp) != key_len)
1970
0
    goto err;
1971
175
  buf[0] = cpu_to_le32(scope->scope);
1972
175
  buf[1] = cpu_to_le32(scope->decl_ids_len);
1973
1974
392
  for (i = 0; i < scope->decl_ids_len; i++)
1975
217
    buf[2 + i] = cpu_to_le32(scope->decl_ids[i]);
1976
1977
175
  rc = POLICYDB_ERROR;
1978
175
  if (put_entry(buf, sizeof(*buf), items, fp) != items)
1979
0
    goto err;
1980
175
  rc = POLICYDB_SUCCESS;
1981
175
err:
1982
175
  free(dyn_buf);
1983
175
  return rc;
1984
175
}
1985
1986
static int role_attr_uncount(hashtab_key_t key __attribute__((unused)),
1987
           hashtab_datum_t datum, void *args)
1988
7.82k
{
1989
7.82k
  role_datum_t *role = datum;
1990
7.82k
  uint32_t *p_nel = args;
1991
1992
7.82k
  if (role->flavor == ROLE_ATTRIB) {
1993
    /* uncount attribute from total number of roles */
1994
164
    (*p_nel)--;
1995
164
  }
1996
7.82k
  return 0;
1997
7.82k
}
1998
1999
/*
2000
 * Write the configuration data in a policy database
2001
 * structure to a policy database binary representation
2002
 * file.
2003
 */
2004
int policydb_write(policydb_t *p, struct policy_file *fp)
2005
1.42k
{
2006
1.42k
  unsigned int i, num_syms;
2007
1.42k
  uint32_t buf[32], config;
2008
1.42k
  size_t items, items2, len;
2009
1.42k
  const struct policydb_compat_info *info;
2010
1.42k
  struct policy_data pd;
2011
1.42k
  const char *policydb_str;
2012
2013
1.42k
  if (p->unsupported_format)
2014
0
    return POLICYDB_UNSUPPORTED;
2015
2016
1.42k
  pd.fp = fp;
2017
1.42k
  pd.p = p;
2018
2019
1.42k
  config = 0;
2020
1.42k
  if (p->mls)
2021
1.10k
    config |= POLICYDB_CONFIG_MLS;
2022
2023
1.42k
  config |= (POLICYDB_CONFIG_UNKNOWN_MASK & p->handle_unknown);
2024
2025
  /* Write the magic number and string identifiers. */
2026
1.42k
  items = 0;
2027
1.42k
  if (p->policy_type == POLICY_KERN) {
2028
1.25k
    buf[items++] = cpu_to_le32(POLICYDB_MAGIC);
2029
1.25k
    len = strlen(policydb_target_strings[p->target_platform]);
2030
1.25k
    policydb_str = policydb_target_strings[p->target_platform];
2031
1.25k
  } else {
2032
167
    buf[items++] = cpu_to_le32(POLICYDB_MOD_MAGIC);
2033
167
    len = strlen(POLICYDB_MOD_STRING);
2034
167
    policydb_str = POLICYDB_MOD_STRING;
2035
167
  }
2036
1.42k
  buf[items++] = cpu_to_le32(len);
2037
1.42k
  items2 = put_entry(buf, sizeof(uint32_t), items, fp);
2038
1.42k
  if (items != items2)
2039
0
    return POLICYDB_ERROR;
2040
1.42k
  items = put_entry(policydb_str, 1, len, fp);
2041
1.42k
  if (items != len)
2042
0
    return POLICYDB_ERROR;
2043
2044
  /* Write the version, config, and table sizes. */
2045
1.42k
  items = 0;
2046
1.42k
  info = policydb_lookup_compat(p->policyvers, p->policy_type,
2047
1.42k
              p->target_platform);
2048
1.42k
  if (!info) {
2049
0
    ERR(fp->handle,
2050
0
        "compatibility lookup failed for %s%s policy version %d",
2051
0
        p->target_platform == SEPOL_TARGET_SELINUX ? "selinux" :
2052
0
                 "xen",
2053
0
        p->policy_type == POLICY_KERN ? "" : " module",
2054
0
        p->policyvers);
2055
0
    return POLICYDB_ERROR;
2056
0
  }
2057
2058
1.42k
  if (p->policy_type != POLICY_KERN) {
2059
167
    buf[items++] = cpu_to_le32(p->policy_type);
2060
167
  }
2061
1.42k
  buf[items++] = cpu_to_le32(p->policyvers);
2062
1.42k
  buf[items++] = cpu_to_le32(config);
2063
1.42k
  buf[items++] = cpu_to_le32(info->sym_num);
2064
1.42k
  buf[items++] = cpu_to_le32(info->ocon_num);
2065
2066
1.42k
  items2 = put_entry(buf, sizeof(uint32_t), items, fp);
2067
1.42k
  if (items != items2)
2068
0
    return POLICYDB_ERROR;
2069
2070
1.42k
  if (p->policy_type == POLICY_MOD) {
2071
    /* Write module name and version */
2072
8
    len = strlen(p->name);
2073
8
    buf[0] = cpu_to_le32(len);
2074
8
    items = put_entry(buf, sizeof(uint32_t), 1, fp);
2075
8
    if (items != 1)
2076
0
      return POLICYDB_ERROR;
2077
8
    items = put_entry(p->name, 1, len, fp);
2078
8
    if (items != len)
2079
0
      return POLICYDB_ERROR;
2080
8
    len = strlen(p->version);
2081
8
    buf[0] = cpu_to_le32(len);
2082
8
    items = put_entry(buf, sizeof(uint32_t), 1, fp);
2083
8
    if (items != 1)
2084
0
      return POLICYDB_ERROR;
2085
8
    items = put_entry(p->version, 1, len, fp);
2086
8
    if (items != len)
2087
0
      return POLICYDB_ERROR;
2088
8
  }
2089
2090
1.42k
  if (ebitmap_write(&p->policycaps, fp) == -1)
2091
0
    return POLICYDB_ERROR;
2092
2093
1.42k
  if (p->policy_type == POLICY_KERN) {
2094
1.25k
    if (ebitmap_write(&p->permissive_map, fp) == -1)
2095
0
      return POLICYDB_ERROR;
2096
2097
1.25k
    if (p->policyvers < POLICYDB_VERSION_NEVERAUDIT) {
2098
1.06k
      ebitmap_node_t *tnode;
2099
2100
1.06k
      ebitmap_for_each_positive_bit(&p->neveraudit_map, tnode,
2101
0
                  i) {
2102
0
        WARN(fp->handle,
2103
0
             "Warning! Policy version %d cannot "
2104
0
             "support neveraudit types, but some were defined",
2105
0
             p->policyvers);
2106
0
        break;
2107
0
      }
2108
1.06k
    } else if (ebitmap_write(&p->neveraudit_map, fp) == -1)
2109
0
      return POLICYDB_ERROR;
2110
1.25k
  }
2111
2112
1.42k
  num_syms = info->sym_num;
2113
12.8k
  for (i = 0; i < num_syms; i++) {
2114
11.3k
    buf[0] = cpu_to_le32(p->symtab[i].nprim);
2115
11.3k
    buf[1] = p->symtab[i].table->nel;
2116
2117
    /*
2118
     * Another special case when writing role/attribute symbol
2119
     * table, role attributes are redundant for policy.X, or
2120
     * when the pp's version is not big enough. So deduct
2121
     * their numbers from p_roles.table->nel.
2122
     */
2123
11.3k
    if ((i == SYM_ROLES) &&
2124
1.42k
        ((p->policy_type == POLICY_KERN) ||
2125
167
         (p->policy_type != POLICY_KERN &&
2126
167
          p->policyvers < MOD_POLICYDB_VERSION_ROLEATTRIB)))
2127
1.30k
      (void)hashtab_map(p->symtab[i].table, role_attr_uncount,
2128
1.30k
            &buf[1]);
2129
2130
11.3k
    buf[1] = cpu_to_le32(buf[1]);
2131
11.3k
    items = put_entry(buf, sizeof(uint32_t), 2, fp);
2132
11.3k
    if (items != 2)
2133
0
      return POLICYDB_ERROR;
2134
11.3k
    if (hashtab_map(p->symtab[i].table, write_f[i], &pd))
2135
0
      return POLICYDB_ERROR;
2136
11.3k
  }
2137
2138
1.42k
  if (p->policy_type == POLICY_KERN) {
2139
1.25k
    if (avtab_write(p, &p->te_avtab, fp))
2140
0
      return POLICYDB_ERROR;
2141
1.25k
    if (cond_write_list(p, p->cond_list, fp))
2142
0
      return POLICYDB_ERROR;
2143
1.25k
    if (role_trans_write(p, fp))
2144
0
      return POLICYDB_ERROR;
2145
1.25k
    if (role_allow_write(p->role_allow, fp))
2146
0
      return POLICYDB_ERROR;
2147
1.25k
    if (p->policyvers >= POLICYDB_VERSION_FILENAME_TRANS) {
2148
1.24k
      if (filename_trans_write(p, fp))
2149
0
        return POLICYDB_ERROR;
2150
1.24k
    } else {
2151
7
      if (p->filename_trans)
2152
7
        WARN(fp->handle,
2153
7
             "Discarding filename type transition rules");
2154
7
    }
2155
1.25k
  } else {
2156
167
    if (avrule_block_write(p->global, num_syms, p, fp) == -1) {
2157
0
      return POLICYDB_ERROR;
2158
0
    }
2159
2160
1.50k
    for (i = 0; i < num_syms; i++) {
2161
1.33k
      buf[0] = cpu_to_le32(p->scope[i].table->nel);
2162
1.33k
      if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1) {
2163
0
        return POLICYDB_ERROR;
2164
0
      }
2165
1.33k
      if (hashtab_map(p->scope[i].table, scope_write, &pd))
2166
0
        return POLICYDB_ERROR;
2167
1.33k
    }
2168
167
  }
2169
2170
1.42k
  if (ocontext_write(info, p, fp) == -1 || genfs_write(p, fp) == -1) {
2171
0
    return POLICYDB_ERROR;
2172
0
  }
2173
2174
1.42k
  if (p->policy_type == POLICY_KERN) {
2175
1.25k
    if (range_write(p, fp)) {
2176
0
      return POLICYDB_ERROR;
2177
0
    }
2178
1.25k
  }
2179
2180
1.42k
  if (p->policy_type == POLICY_KERN) {
2181
2.93k
    for (i = 0; i < p->p_types.nprim; i++) {
2182
1.68k
      if (ebitmap_write(&p->type_attr_map[i], fp) == -1)
2183
0
        return POLICYDB_ERROR;
2184
1.68k
    }
2185
1.25k
  }
2186
2187
1.42k
  return POLICYDB_SUCCESS;
2188
1.42k
}