Coverage Report

Created: 2026-03-21 06:47

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