Commit cee74f47a6baba0ac457e87687fdcf0abd599f0a

Authored by Eric Paris
Committed by James Morris
1 parent 00d85c83ac

SELinux: allow userspace to read policy back out of the kernel

There is interest in being able to see what the actual policy is that was
loaded into the kernel.  The patch creates a new selinuxfs file
/selinux/policy which can be read by userspace.  The actual policy that is
loaded into the kernel will be written back out to userspace.

Signed-off-by: Eric Paris <eparis@redhat.com>
Signed-off-by: James Morris <jmorris@namei.org>

Showing 12 changed files with 1256 additions and 3 deletions Side-by-side Diff

security/selinux/include/classmap.h
... ... @@ -17,7 +17,7 @@
17 17 { "compute_av", "compute_create", "compute_member",
18 18 "check_context", "load_policy", "compute_relabel",
19 19 "compute_user", "setenforce", "setbool", "setsecparam",
20   - "setcheckreqprot", NULL } },
  20 + "setcheckreqprot", "read_policy", NULL } },
21 21 { "process",
22 22 { "fork", "transition", "sigchld", "sigkill",
23 23 "sigstop", "signull", "signal", "ptrace", "getsched", "setsched",
security/selinux/include/security.h
... ... @@ -83,6 +83,8 @@
83 83 int security_mls_enabled(void);
84 84  
85 85 int security_load_policy(void *data, size_t len);
  86 +int security_read_policy(void **data, ssize_t *len);
  87 +size_t security_policydb_len(void);
86 88  
87 89 int security_policycap_supported(unsigned int req_cap);
88 90  
security/selinux/selinuxfs.c
... ... @@ -68,6 +68,8 @@
68 68 static struct dentry *class_dir;
69 69 static unsigned long last_class_ino;
70 70  
  71 +static char policy_opened;
  72 +
71 73 /* global data for policy capabilities */
72 74 static struct dentry *policycap_dir;
73 75  
... ... @@ -111,6 +113,7 @@
111 113 SEL_REJECT_UNKNOWN, /* export unknown reject handling to userspace */
112 114 SEL_DENY_UNKNOWN, /* export unknown deny handling to userspace */
113 115 SEL_STATUS, /* export current status using mmap() */
  116 + SEL_POLICY, /* allow userspace to read the in kernel policy */
114 117 SEL_INO_NEXT, /* The next inode number to use */
115 118 };
116 119  
... ... @@ -351,6 +354,97 @@
351 354 .llseek = generic_file_llseek,
352 355 };
353 356  
  357 +struct policy_load_memory {
  358 + size_t len;
  359 + void *data;
  360 +};
  361 +
  362 +static int sel_open_policy(struct inode *inode, struct file *filp)
  363 +{
  364 + struct policy_load_memory *plm = NULL;
  365 + int rc;
  366 +
  367 + BUG_ON(filp->private_data);
  368 +
  369 + mutex_lock(&sel_mutex);
  370 +
  371 + rc = task_has_security(current, SECURITY__READ_POLICY);
  372 + if (rc)
  373 + goto err;
  374 +
  375 + rc = -EBUSY;
  376 + if (policy_opened)
  377 + goto err;
  378 +
  379 + rc = -ENOMEM;
  380 + plm = kzalloc(sizeof(*plm), GFP_KERNEL);
  381 + if (!plm)
  382 + goto err;
  383 +
  384 + if (i_size_read(inode) != security_policydb_len()) {
  385 + mutex_lock(&inode->i_mutex);
  386 + i_size_write(inode, security_policydb_len());
  387 + mutex_unlock(&inode->i_mutex);
  388 + }
  389 +
  390 + rc = security_read_policy(&plm->data, &plm->len);
  391 + if (rc)
  392 + goto err;
  393 +
  394 + policy_opened = 1;
  395 +
  396 + filp->private_data = plm;
  397 +
  398 + mutex_unlock(&sel_mutex);
  399 +
  400 + return 0;
  401 +err:
  402 + mutex_unlock(&sel_mutex);
  403 +
  404 + if (plm)
  405 + vfree(plm->data);
  406 + kfree(plm);
  407 + return rc;
  408 +}
  409 +
  410 +static int sel_release_policy(struct inode *inode, struct file *filp)
  411 +{
  412 + struct policy_load_memory *plm = filp->private_data;
  413 +
  414 + BUG_ON(!plm);
  415 +
  416 + policy_opened = 0;
  417 +
  418 + vfree(plm->data);
  419 + kfree(plm);
  420 +
  421 + return 0;
  422 +}
  423 +
  424 +static ssize_t sel_read_policy(struct file *filp, char __user *buf,
  425 + size_t count, loff_t *ppos)
  426 +{
  427 + struct policy_load_memory *plm = filp->private_data;
  428 + int ret;
  429 +
  430 + mutex_lock(&sel_mutex);
  431 +
  432 + ret = task_has_security(current, SECURITY__READ_POLICY);
  433 + if (ret)
  434 + goto out;
  435 +
  436 + ret = simple_read_from_buffer(buf, count, ppos, plm->data, plm->len);
  437 +out:
  438 + mutex_unlock(&sel_mutex);
  439 + return ret;
  440 +}
  441 +
  442 +static const struct file_operations sel_policy_ops = {
  443 + .open = sel_open_policy,
  444 + .read = sel_read_policy,
  445 + .release = sel_release_policy,
  446 +};
  447 +
354 448 static ssize_t sel_write_load(struct file *file, const char __user *buf,
355 449 size_t count, loff_t *ppos)
356 450  
... ... @@ -1668,6 +1762,7 @@
1668 1762 [SEL_REJECT_UNKNOWN] = {"reject_unknown", &sel_handle_unknown_ops, S_IRUGO},
1669 1763 [SEL_DENY_UNKNOWN] = {"deny_unknown", &sel_handle_unknown_ops, S_IRUGO},
1670 1764 [SEL_STATUS] = {"status", &sel_handle_status_ops, S_IRUGO},
  1765 + [SEL_POLICY] = {"policy", &sel_policy_ops, S_IRUSR},
1671 1766 /* last one */ {""}
1672 1767 };
1673 1768 ret = simple_fill_super(sb, SELINUX_MAGIC, selinux_files);
security/selinux/ss/avtab.c
... ... @@ -501,6 +501,48 @@
501 501 goto out;
502 502 }
503 503  
  504 +int avtab_write_item(struct policydb *p, struct avtab_node *cur, void *fp)
  505 +{
  506 + __le16 buf16[4];
  507 + __le32 buf32[1];
  508 + int rc;
  509 +
  510 + buf16[0] = cpu_to_le16(cur->key.source_type);
  511 + buf16[1] = cpu_to_le16(cur->key.target_type);
  512 + buf16[2] = cpu_to_le16(cur->key.target_class);
  513 + buf16[3] = cpu_to_le16(cur->key.specified);
  514 + rc = put_entry(buf16, sizeof(u16), 4, fp);
  515 + if (rc)
  516 + return rc;
  517 + buf32[0] = cpu_to_le32(cur->datum.data);
  518 + rc = put_entry(buf32, sizeof(u32), 1, fp);
  519 + if (rc)
  520 + return rc;
  521 + return 0;
  522 +}
  523 +
  524 +int avtab_write(struct policydb *p, struct avtab *a, void *fp)
  525 +{
  526 + unsigned int i;
  527 + int rc = 0;
  528 + struct avtab_node *cur;
  529 + __le32 buf[1];
  530 +
  531 + buf[0] = cpu_to_le32(a->nel);
  532 + rc = put_entry(buf, sizeof(u32), 1, fp);
  533 + if (rc)
  534 + return rc;
  535 +
  536 + for (i = 0; i < a->nslot; i++) {
  537 + for (cur = a->htable[i]; cur; cur = cur->next) {
  538 + rc = avtab_write_item(p, cur, fp);
  539 + if (rc)
  540 + return rc;
  541 + }
  542 + }
  543 +
  544 + return rc;
  545 +}
504 546 void avtab_cache_init(void)
505 547 {
506 548 avtab_node_cachep = kmem_cache_create("avtab_node",
security/selinux/ss/avtab.h
... ... @@ -71,6 +71,8 @@
71 71 void *p);
72 72  
73 73 int avtab_read(struct avtab *a, void *fp, struct policydb *pol);
  74 +int avtab_write_item(struct policydb *p, struct avtab_node *cur, void *fp);
  75 +int avtab_write(struct policydb *p, struct avtab *a, void *fp);
74 76  
75 77 struct avtab_node *avtab_insert_nonunique(struct avtab *h, struct avtab_key *key,
76 78 struct avtab_datum *datum);
security/selinux/ss/conditional.c
... ... @@ -490,6 +490,129 @@
490 490 return rc;
491 491 }
492 492  
  493 +int cond_write_bool(void *vkey, void *datum, void *ptr)
  494 +{
  495 + char *key = vkey;
  496 + struct cond_bool_datum *booldatum = datum;
  497 + struct policy_data *pd = ptr;
  498 + void *fp = pd->fp;
  499 + __le32 buf[3];
  500 + u32 len;
  501 + int rc;
  502 +
  503 + len = strlen(key);
  504 + buf[0] = cpu_to_le32(booldatum->value);
  505 + buf[1] = cpu_to_le32(booldatum->state);
  506 + buf[2] = cpu_to_le32(len);
  507 + rc = put_entry(buf, sizeof(u32), 3, fp);
  508 + if (rc)
  509 + return rc;
  510 + rc = put_entry(key, 1, len, fp);
  511 + if (rc)
  512 + return rc;
  513 + return 0;
  514 +}
  515 +
  516 +/*
  517 + * cond_write_cond_av_list doesn't write out the av_list nodes.
  518 + * Instead it writes out the key/value pairs from the avtab. This
  519 + * is necessary because there is no way to uniquely identifying rules
  520 + * in the avtab so it is not possible to associate individual rules
  521 + * in the avtab with a conditional without saving them as part of
  522 + * the conditional. This means that the avtab with the conditional
  523 + * rules will not be saved but will be rebuilt on policy load.
  524 + */
  525 +static int cond_write_av_list(struct policydb *p,
  526 + struct cond_av_list *list, struct policy_file *fp)
  527 +{
  528 + __le32 buf[1];
  529 + struct cond_av_list *cur_list;
  530 + u32 len;
  531 + int rc;
  532 +
  533 + len = 0;
  534 + for (cur_list = list; cur_list != NULL; cur_list = cur_list->next)
  535 + len++;
  536 +
  537 + buf[0] = cpu_to_le32(len);
  538 + rc = put_entry(buf, sizeof(u32), 1, fp);
  539 + if (rc)
  540 + return rc;
  541 +
  542 + if (len == 0)
  543 + return 0;
  544 +
  545 + for (cur_list = list; cur_list != NULL; cur_list = cur_list->next) {
  546 + rc = avtab_write_item(p, cur_list->node, fp);
  547 + if (rc)
  548 + return rc;
  549 + }
  550 +
  551 + return 0;
  552 +}
  553 +
  554 +int cond_write_node(struct policydb *p, struct cond_node *node,
  555 + struct policy_file *fp)
  556 +{
  557 + struct cond_expr *cur_expr;
  558 + __le32 buf[2];
  559 + int rc;
  560 + u32 len = 0;
  561 +
  562 + buf[0] = cpu_to_le32(node->cur_state);
  563 + rc = put_entry(buf, sizeof(u32), 1, fp);
  564 + if (rc)
  565 + return rc;
  566 +
  567 + for (cur_expr = node->expr; cur_expr != NULL; cur_expr = cur_expr->next)
  568 + len++;
  569 +
  570 + buf[0] = cpu_to_le32(len);
  571 + rc = put_entry(buf, sizeof(u32), 1, fp);
  572 + if (rc)
  573 + return rc;
  574 +
  575 + for (cur_expr = node->expr; cur_expr != NULL; cur_expr = cur_expr->next) {
  576 + buf[0] = cpu_to_le32(cur_expr->expr_type);
  577 + buf[1] = cpu_to_le32(cur_expr->bool);
  578 + rc = put_entry(buf, sizeof(u32), 2, fp);
  579 + if (rc)
  580 + return rc;
  581 + }
  582 +
  583 + rc = cond_write_av_list(p, node->true_list, fp);
  584 + if (rc)
  585 + return rc;
  586 + rc = cond_write_av_list(p, node->false_list, fp);
  587 + if (rc)
  588 + return rc;
  589 +
  590 + return 0;
  591 +}
  592 +
  593 +int cond_write_list(struct policydb *p, struct cond_node *list, void *fp)
  594 +{
  595 + struct cond_node *cur;
  596 + u32 len;
  597 + __le32 buf[1];
  598 + int rc;
  599 +
  600 + len = 0;
  601 + for (cur = list; cur != NULL; cur = cur->next)
  602 + len++;
  603 + buf[0] = cpu_to_le32(len);
  604 + rc = put_entry(buf, sizeof(u32), 1, fp);
  605 + if (rc)
  606 + return rc;
  607 +
  608 + for (cur = list; cur != NULL; cur = cur->next) {
  609 + rc = cond_write_node(p, cur, fp);
  610 + if (rc)
  611 + return rc;
  612 + }
  613 +
  614 + return 0;
  615 +}
493 616 /* Determine whether additional permissions are granted by the conditional
494 617 * av table, and if so, add them to the result
495 618 */
security/selinux/ss/conditional.h
... ... @@ -69,6 +69,8 @@
69 69  
70 70 int cond_read_bool(struct policydb *p, struct hashtab *h, void *fp);
71 71 int cond_read_list(struct policydb *p, void *fp);
  72 +int cond_write_bool(void *key, void *datum, void *ptr);
  73 +int cond_write_list(struct policydb *p, struct cond_node *list, void *fp);
72 74  
73 75 void cond_compute_av(struct avtab *ctab, struct avtab_key *key, struct av_decision *avd);
74 76  
security/selinux/ss/ebitmap.c
... ... @@ -22,6 +22,8 @@
22 22 #include "ebitmap.h"
23 23 #include "policydb.h"
24 24  
  25 +#define BITS_PER_U64 (sizeof(u64) * 8)
  26 +
25 27 int ebitmap_cmp(struct ebitmap *e1, struct ebitmap *e2)
26 28 {
27 29 struct ebitmap_node *n1, *n2;
28 30  
... ... @@ -363,10 +365,10 @@
363 365 e->highbit = le32_to_cpu(buf[1]);
364 366 count = le32_to_cpu(buf[2]);
365 367  
366   - if (mapunit != sizeof(u64) * 8) {
  368 + if (mapunit != BITS_PER_U64) {
367 369 printk(KERN_ERR "SELinux: ebitmap: map size %u does not "
368 370 "match my size %Zd (high bit was %d)\n",
369   - mapunit, sizeof(u64) * 8, e->highbit);
  371 + mapunit, BITS_PER_U64, e->highbit);
370 372 goto bad;
371 373 }
372 374  
... ... @@ -445,5 +447,80 @@
445 447 rc = -EINVAL;
446 448 ebitmap_destroy(e);
447 449 goto out;
  450 +}
  451 +
  452 +int ebitmap_write(struct ebitmap *e, void *fp)
  453 +{
  454 + struct ebitmap_node *n;
  455 + u32 count;
  456 + __le32 buf[3];
  457 + u64 map;
  458 + int bit, last_bit, last_startbit, rc;
  459 +
  460 + buf[0] = cpu_to_le32(BITS_PER_U64);
  461 +
  462 + count = 0;
  463 + last_bit = 0;
  464 + last_startbit = -1;
  465 + ebitmap_for_each_positive_bit(e, n, bit) {
  466 + if (rounddown(bit, (int)BITS_PER_U64) > last_startbit) {
  467 + count++;
  468 + last_startbit = rounddown(bit, BITS_PER_U64);
  469 + }
  470 + last_bit = roundup(bit + 1, BITS_PER_U64);
  471 + }
  472 + buf[1] = cpu_to_le32(last_bit);
  473 + buf[2] = cpu_to_le32(count);
  474 +
  475 + rc = put_entry(buf, sizeof(u32), 3, fp);
  476 + if (rc)
  477 + return rc;
  478 +
  479 + map = 0;
  480 + last_startbit = INT_MIN;
  481 + ebitmap_for_each_positive_bit(e, n, bit) {
  482 + if (rounddown(bit, (int)BITS_PER_U64) > last_startbit) {
  483 + __le64 buf64[1];
  484 +
  485 + /* this is the very first bit */
  486 + if (!map) {
  487 + last_startbit = rounddown(bit, BITS_PER_U64);
  488 + map = (u64)1 << (bit - last_startbit);
  489 + continue;
  490 + }
  491 +
  492 + /* write the last node */
  493 + buf[0] = cpu_to_le32(last_startbit);
  494 + rc = put_entry(buf, sizeof(u32), 1, fp);
  495 + if (rc)
  496 + return rc;
  497 +
  498 + buf64[0] = cpu_to_le64(map);
  499 + rc = put_entry(buf64, sizeof(u64), 1, fp);
  500 + if (rc)
  501 + return rc;
  502 +
  503 + /* set up for the next node */
  504 + map = 0;
  505 + last_startbit = rounddown(bit, BITS_PER_U64);
  506 + }
  507 + map |= (u64)1 << (bit - last_startbit);
  508 + }
  509 + /* write the last node */
  510 + if (map) {
  511 + __le64 buf64[1];
  512 +
  513 + /* write the last node */
  514 + buf[0] = cpu_to_le32(last_startbit);
  515 + rc = put_entry(buf, sizeof(u32), 1, fp);
  516 + if (rc)
  517 + return rc;
  518 +
  519 + buf64[0] = cpu_to_le64(map);
  520 + rc = put_entry(buf64, sizeof(u64), 1, fp);
  521 + if (rc)
  522 + return rc;
  523 + }
  524 + return 0;
448 525 }
security/selinux/ss/ebitmap.h
... ... @@ -123,6 +123,7 @@
123 123 int ebitmap_set_bit(struct ebitmap *e, unsigned long bit, int value);
124 124 void ebitmap_destroy(struct ebitmap *e);
125 125 int ebitmap_read(struct ebitmap *e, void *fp);
  126 +int ebitmap_write(struct ebitmap *e, void *fp);
126 127  
127 128 #ifdef CONFIG_NETLABEL
128 129 int ebitmap_netlbl_export(struct ebitmap *ebmap,
security/selinux/ss/policydb.c
... ... @@ -37,6 +37,7 @@
37 37 #include "policydb.h"
38 38 #include "conditional.h"
39 39 #include "mls.h"
  40 +#include "services.h"
40 41  
41 42 #define _DEBUG_HASHES
42 43  
... ... @@ -2315,5 +2316,845 @@
2315 2316 rc = -EINVAL;
2316 2317 policydb_destroy(p);
2317 2318 goto out;
  2319 +}
  2320 +
  2321 +/*
  2322 + * Write a MLS level structure to a policydb binary
  2323 + * representation file.
  2324 + */
  2325 +static int mls_write_level(struct mls_level *l, void *fp)
  2326 +{
  2327 + __le32 buf[1];
  2328 + int rc;
  2329 +
  2330 + buf[0] = cpu_to_le32(l->sens);
  2331 + rc = put_entry(buf, sizeof(u32), 1, fp);
  2332 + if (rc)
  2333 + return rc;
  2334 +
  2335 + rc = ebitmap_write(&l->cat, fp);
  2336 + if (rc)
  2337 + return rc;
  2338 +
  2339 + return 0;
  2340 +}
  2341 +
  2342 +/*
  2343 + * Write a MLS range structure to a policydb binary
  2344 + * representation file.
  2345 + */
  2346 +static int mls_write_range_helper(struct mls_range *r, void *fp)
  2347 +{
  2348 + __le32 buf[3];
  2349 + size_t items;
  2350 + int rc, eq;
  2351 +
  2352 + eq = mls_level_eq(&r->level[1], &r->level[0]);
  2353 +
  2354 + if (eq)
  2355 + items = 2;
  2356 + else
  2357 + items = 3;
  2358 + buf[0] = cpu_to_le32(items-1);
  2359 + buf[1] = cpu_to_le32(r->level[0].sens);
  2360 + if (!eq)
  2361 + buf[2] = cpu_to_le32(r->level[1].sens);
  2362 +
  2363 + BUG_ON(items > (sizeof(buf)/sizeof(buf[0])));
  2364 +
  2365 + rc = put_entry(buf, sizeof(u32), items, fp);
  2366 + if (rc)
  2367 + return rc;
  2368 +
  2369 + rc = ebitmap_write(&r->level[0].cat, fp);
  2370 + if (rc)
  2371 + return rc;
  2372 + if (!eq) {
  2373 + rc = ebitmap_write(&r->level[1].cat, fp);
  2374 + if (rc)
  2375 + return rc;
  2376 + }
  2377 +
  2378 + return 0;
  2379 +}
  2380 +
  2381 +static int sens_write(void *vkey, void *datum, void *ptr)
  2382 +{
  2383 + char *key = vkey;
  2384 + struct level_datum *levdatum = datum;
  2385 + struct policy_data *pd = ptr;
  2386 + void *fp = pd->fp;
  2387 + __le32 buf[2];
  2388 + size_t len;
  2389 + int rc;
  2390 +
  2391 + len = strlen(key);
  2392 + buf[0] = cpu_to_le32(len);
  2393 + buf[1] = cpu_to_le32(levdatum->isalias);
  2394 + rc = put_entry(buf, sizeof(u32), 2, fp);
  2395 + if (rc)
  2396 + return rc;
  2397 +
  2398 + rc = put_entry(key, 1, len, fp);
  2399 + if (rc)
  2400 + return rc;
  2401 +
  2402 + rc = mls_write_level(levdatum->level, fp);
  2403 + if (rc)
  2404 + return rc;
  2405 +
  2406 + return 0;
  2407 +}
  2408 +
  2409 +static int cat_write(void *vkey, void *datum, void *ptr)
  2410 +{
  2411 + char *key = vkey;
  2412 + struct cat_datum *catdatum = datum;
  2413 + struct policy_data *pd = ptr;
  2414 + void *fp = pd->fp;
  2415 + __le32 buf[3];
  2416 + size_t len;
  2417 + int rc;
  2418 +
  2419 + len = strlen(key);
  2420 + buf[0] = cpu_to_le32(len);
  2421 + buf[1] = cpu_to_le32(catdatum->value);
  2422 + buf[2] = cpu_to_le32(catdatum->isalias);
  2423 + rc = put_entry(buf, sizeof(u32), 3, fp);
  2424 + if (rc)
  2425 + return rc;
  2426 +
  2427 + rc = put_entry(key, 1, len, fp);
  2428 + if (rc)
  2429 + return rc;
  2430 +
  2431 + return 0;
  2432 +}
  2433 +
  2434 +static int role_trans_write(struct role_trans *r, void *fp)
  2435 +{
  2436 + struct role_trans *tr;
  2437 + u32 buf[3];
  2438 + size_t nel;
  2439 + int rc;
  2440 +
  2441 + nel = 0;
  2442 + for (tr = r; tr; tr = tr->next)
  2443 + nel++;
  2444 + buf[0] = cpu_to_le32(nel);
  2445 + rc = put_entry(buf, sizeof(u32), 1, fp);
  2446 + if (rc)
  2447 + return rc;
  2448 + for (tr = r; tr; tr = tr->next) {
  2449 + buf[0] = cpu_to_le32(tr->role);
  2450 + buf[1] = cpu_to_le32(tr->type);
  2451 + buf[2] = cpu_to_le32(tr->new_role);
  2452 + rc = put_entry(buf, sizeof(u32), 3, fp);
  2453 + if (rc)
  2454 + return rc;
  2455 + }
  2456 +
  2457 + return 0;
  2458 +}
  2459 +
  2460 +static int role_allow_write(struct role_allow *r, void *fp)
  2461 +{
  2462 + struct role_allow *ra;
  2463 + u32 buf[2];
  2464 + size_t nel;
  2465 + int rc;
  2466 +
  2467 + nel = 0;
  2468 + for (ra = r; ra; ra = ra->next)
  2469 + nel++;
  2470 + buf[0] = cpu_to_le32(nel);
  2471 + rc = put_entry(buf, sizeof(u32), 1, fp);
  2472 + if (rc)
  2473 + return rc;
  2474 + for (ra = r; ra; ra = ra->next) {
  2475 + buf[0] = cpu_to_le32(ra->role);
  2476 + buf[1] = cpu_to_le32(ra->new_role);
  2477 + rc = put_entry(buf, sizeof(u32), 2, fp);
  2478 + if (rc)
  2479 + return rc;
  2480 + }
  2481 + return 0;
  2482 +}
  2483 +
  2484 +/*
  2485 + * Write a security context structure
  2486 + * to a policydb binary representation file.
  2487 + */
  2488 +static int context_write(struct policydb *p, struct context *c,
  2489 + void *fp)
  2490 +{
  2491 + int rc;
  2492 + __le32 buf[3];
  2493 +
  2494 + buf[0] = cpu_to_le32(c->user);
  2495 + buf[1] = cpu_to_le32(c->role);
  2496 + buf[2] = cpu_to_le32(c->type);
  2497 +
  2498 + rc = put_entry(buf, sizeof(u32), 3, fp);
  2499 + if (rc)
  2500 + return rc;
  2501 +
  2502 + rc = mls_write_range_helper(&c->range, fp);
  2503 + if (rc)
  2504 + return rc;
  2505 +
  2506 + return 0;
  2507 +}
  2508 +
  2509 +/*
  2510 + * The following *_write functions are used to
  2511 + * write the symbol data to a policy database
  2512 + * binary representation file.
  2513 + */
  2514 +
  2515 +static int perm_write(void *vkey, void *datum, void *fp)
  2516 +{
  2517 + char *key = vkey;
  2518 + struct perm_datum *perdatum = datum;
  2519 + __le32 buf[2];
  2520 + size_t len;
  2521 + int rc;
  2522 +
  2523 + len = strlen(key);
  2524 + buf[0] = cpu_to_le32(len);
  2525 + buf[1] = cpu_to_le32(perdatum->value);
  2526 + rc = put_entry(buf, sizeof(u32), 2, fp);
  2527 + if (rc)
  2528 + return rc;
  2529 +
  2530 + rc = put_entry(key, 1, len, fp);
  2531 + if (rc)
  2532 + return rc;
  2533 +
  2534 + return 0;
  2535 +}
  2536 +
  2537 +static int common_write(void *vkey, void *datum, void *ptr)
  2538 +{
  2539 + char *key = vkey;
  2540 + struct common_datum *comdatum = datum;
  2541 + struct policy_data *pd = ptr;
  2542 + void *fp = pd->fp;
  2543 + __le32 buf[4];
  2544 + size_t len;
  2545 + int rc;
  2546 +
  2547 + len = strlen(key);
  2548 + buf[0] = cpu_to_le32(len);
  2549 + buf[1] = cpu_to_le32(comdatum->value);
  2550 + buf[2] = cpu_to_le32(comdatum->permissions.nprim);
  2551 + buf[3] = cpu_to_le32(comdatum->permissions.table->nel);
  2552 + rc = put_entry(buf, sizeof(u32), 4, fp);
  2553 + if (rc)
  2554 + return rc;
  2555 +
  2556 + rc = put_entry(key, 1, len, fp);
  2557 + if (rc)
  2558 + return rc;
  2559 +
  2560 + rc = hashtab_map(comdatum->permissions.table, perm_write, fp);
  2561 + if (rc)
  2562 + return rc;
  2563 +
  2564 + return 0;
  2565 +}
  2566 +
  2567 +static int write_cons_helper(struct policydb *p, struct constraint_node *node,
  2568 + void *fp)
  2569 +{
  2570 + struct constraint_node *c;
  2571 + struct constraint_expr *e;
  2572 + __le32 buf[3];
  2573 + u32 nel;
  2574 + int rc;
  2575 +
  2576 + for (c = node; c; c = c->next) {
  2577 + nel = 0;
  2578 + for (e = c->expr; e; e = e->next)
  2579 + nel++;
  2580 + buf[0] = cpu_to_le32(c->permissions);
  2581 + buf[1] = cpu_to_le32(nel);
  2582 + rc = put_entry(buf, sizeof(u32), 2, fp);
  2583 + if (rc)
  2584 + return rc;
  2585 + for (e = c->expr; e; e = e->next) {
  2586 + buf[0] = cpu_to_le32(e->expr_type);
  2587 + buf[1] = cpu_to_le32(e->attr);
  2588 + buf[2] = cpu_to_le32(e->op);
  2589 + rc = put_entry(buf, sizeof(u32), 3, fp);
  2590 + if (rc)
  2591 + return rc;
  2592 +
  2593 + switch (e->expr_type) {
  2594 + case CEXPR_NAMES:
  2595 + rc = ebitmap_write(&e->names, fp);
  2596 + if (rc)
  2597 + return rc;
  2598 + break;
  2599 + default:
  2600 + break;
  2601 + }
  2602 + }
  2603 + }
  2604 +
  2605 + return 0;
  2606 +}
  2607 +
  2608 +static int class_write(void *vkey, void *datum, void *ptr)
  2609 +{
  2610 + char *key = vkey;
  2611 + struct class_datum *cladatum = datum;
  2612 + struct policy_data *pd = ptr;
  2613 + void *fp = pd->fp;
  2614 + struct policydb *p = pd->p;
  2615 + struct constraint_node *c;
  2616 + __le32 buf[6];
  2617 + u32 ncons;
  2618 + size_t len, len2;
  2619 + int rc;
  2620 +
  2621 + len = strlen(key);
  2622 + if (cladatum->comkey)
  2623 + len2 = strlen(cladatum->comkey);
  2624 + else
  2625 + len2 = 0;
  2626 +
  2627 + ncons = 0;
  2628 + for (c = cladatum->constraints; c; c = c->next)
  2629 + ncons++;
  2630 +
  2631 + buf[0] = cpu_to_le32(len);
  2632 + buf[1] = cpu_to_le32(len2);
  2633 + buf[2] = cpu_to_le32(cladatum->value);
  2634 + buf[3] = cpu_to_le32(cladatum->permissions.nprim);
  2635 + if (cladatum->permissions.table)
  2636 + buf[4] = cpu_to_le32(cladatum->permissions.table->nel);
  2637 + else
  2638 + buf[4] = 0;
  2639 + buf[5] = cpu_to_le32(ncons);
  2640 + rc = put_entry(buf, sizeof(u32), 6, fp);
  2641 + if (rc)
  2642 + return rc;
  2643 +
  2644 + rc = put_entry(key, 1, len, fp);
  2645 + if (rc)
  2646 + return rc;
  2647 +
  2648 + if (cladatum->comkey) {
  2649 + rc = put_entry(cladatum->comkey, 1, len2, fp);
  2650 + if (rc)
  2651 + return rc;
  2652 + }
  2653 +
  2654 + rc = hashtab_map(cladatum->permissions.table, perm_write, fp);
  2655 + if (rc)
  2656 + return rc;
  2657 +
  2658 + rc = write_cons_helper(p, cladatum->constraints, fp);
  2659 + if (rc)
  2660 + return rc;
  2661 +
  2662 + /* write out the validatetrans rule */
  2663 + ncons = 0;
  2664 + for (c = cladatum->validatetrans; c; c = c->next)
  2665 + ncons++;
  2666 +
  2667 + buf[0] = cpu_to_le32(ncons);
  2668 + rc = put_entry(buf, sizeof(u32), 1, fp);
  2669 + if (rc)
  2670 + return rc;
  2671 +
  2672 + rc = write_cons_helper(p, cladatum->validatetrans, fp);
  2673 + if (rc)
  2674 + return rc;
  2675 +
  2676 + return 0;
  2677 +}
  2678 +
  2679 +static int role_write(void *vkey, void *datum, void *ptr)
  2680 +{
  2681 + char *key = vkey;
  2682 + struct role_datum *role = datum;
  2683 + struct policy_data *pd = ptr;
  2684 + void *fp = pd->fp;
  2685 + struct policydb *p = pd->p;
  2686 + __le32 buf[3];
  2687 + size_t items, len;
  2688 + int rc;
  2689 +
  2690 + len = strlen(key);
  2691 + items = 0;
  2692 + buf[items++] = cpu_to_le32(len);
  2693 + buf[items++] = cpu_to_le32(role->value);
  2694 + if (p->policyvers >= POLICYDB_VERSION_BOUNDARY)
  2695 + buf[items++] = cpu_to_le32(role->bounds);
  2696 +
  2697 + BUG_ON(items > (sizeof(buf)/sizeof(buf[0])));
  2698 +
  2699 + rc = put_entry(buf, sizeof(u32), items, fp);
  2700 + if (rc)
  2701 + return rc;
  2702 +
  2703 + rc = put_entry(key, 1, len, fp);
  2704 + if (rc)
  2705 + return rc;
  2706 +
  2707 + rc = ebitmap_write(&role->dominates, fp);
  2708 + if (rc)
  2709 + return rc;
  2710 +
  2711 + rc = ebitmap_write(&role->types, fp);
  2712 + if (rc)
  2713 + return rc;
  2714 +
  2715 + return 0;
  2716 +}
  2717 +
  2718 +static int type_write(void *vkey, void *datum, void *ptr)
  2719 +{
  2720 + char *key = vkey;
  2721 + struct type_datum *typdatum = datum;
  2722 + struct policy_data *pd = ptr;
  2723 + struct policydb *p = pd->p;
  2724 + void *fp = pd->fp;
  2725 + __le32 buf[4];
  2726 + int rc;
  2727 + size_t items, len;
  2728 +
  2729 + len = strlen(key);
  2730 + items = 0;
  2731 + buf[items++] = cpu_to_le32(len);
  2732 + buf[items++] = cpu_to_le32(typdatum->value);
  2733 + if (p->policyvers >= POLICYDB_VERSION_BOUNDARY) {
  2734 + u32 properties = 0;
  2735 +
  2736 + if (typdatum->primary)
  2737 + properties |= TYPEDATUM_PROPERTY_PRIMARY;
  2738 +
  2739 + if (typdatum->attribute)
  2740 + properties |= TYPEDATUM_PROPERTY_ATTRIBUTE;
  2741 +
  2742 + buf[items++] = cpu_to_le32(properties);
  2743 + buf[items++] = cpu_to_le32(typdatum->bounds);
  2744 + } else {
  2745 + buf[items++] = cpu_to_le32(typdatum->primary);
  2746 + }
  2747 + BUG_ON(items > (sizeof(buf) / sizeof(buf[0])));
  2748 + rc = put_entry(buf, sizeof(u32), items, fp);
  2749 + if (rc)
  2750 + return rc;
  2751 +
  2752 + rc = put_entry(key, 1, len, fp);
  2753 + if (rc)
  2754 + return rc;
  2755 +
  2756 + return 0;
  2757 +}
  2758 +
  2759 +static int user_write(void *vkey, void *datum, void *ptr)
  2760 +{
  2761 + char *key = vkey;
  2762 + struct user_datum *usrdatum = datum;
  2763 + struct policy_data *pd = ptr;
  2764 + struct policydb *p = pd->p;
  2765 + void *fp = pd->fp;
  2766 + __le32 buf[3];
  2767 + size_t items, len;
  2768 + int rc;
  2769 +
  2770 + len = strlen(key);
  2771 + items = 0;
  2772 + buf[items++] = cpu_to_le32(len);
  2773 + buf[items++] = cpu_to_le32(usrdatum->value);
  2774 + if (p->policyvers >= POLICYDB_VERSION_BOUNDARY)
  2775 + buf[items++] = cpu_to_le32(usrdatum->bounds);
  2776 + BUG_ON(items > (sizeof(buf) / sizeof(buf[0])));
  2777 + rc = put_entry(buf, sizeof(u32), items, fp);
  2778 + if (rc)
  2779 + return rc;
  2780 +
  2781 + rc = put_entry(key, 1, len, fp);
  2782 + if (rc)
  2783 + return rc;
  2784 +
  2785 + rc = ebitmap_write(&usrdatum->roles, fp);
  2786 + if (rc)
  2787 + return rc;
  2788 +
  2789 + rc = mls_write_range_helper(&usrdatum->range, fp);
  2790 + if (rc)
  2791 + return rc;
  2792 +
  2793 + rc = mls_write_level(&usrdatum->dfltlevel, fp);
  2794 + if (rc)
  2795 + return rc;
  2796 +
  2797 + return 0;
  2798 +}
  2799 +
  2800 +static int (*write_f[SYM_NUM]) (void *key, void *datum,
  2801 + void *datap) =
  2802 +{
  2803 + common_write,
  2804 + class_write,
  2805 + role_write,
  2806 + type_write,
  2807 + user_write,
  2808 + cond_write_bool,
  2809 + sens_write,
  2810 + cat_write,
  2811 +};
  2812 +
  2813 +static int ocontext_write(struct policydb *p, struct policydb_compat_info *info,
  2814 + void *fp)
  2815 +{
  2816 + unsigned int i, j, rc;
  2817 + size_t nel, len;
  2818 + __le32 buf[3];
  2819 + u32 nodebuf[8];
  2820 + struct ocontext *c;
  2821 + for (i = 0; i < info->ocon_num; i++) {
  2822 + nel = 0;
  2823 + for (c = p->ocontexts[i]; c; c = c->next)
  2824 + nel++;
  2825 + buf[0] = cpu_to_le32(nel);
  2826 + rc = put_entry(buf, sizeof(u32), 1, fp);
  2827 + if (rc)
  2828 + return rc;
  2829 + for (c = p->ocontexts[i]; c; c = c->next) {
  2830 + switch (i) {
  2831 + case OCON_ISID:
  2832 + buf[0] = cpu_to_le32(c->sid[0]);
  2833 + rc = put_entry(buf, sizeof(u32), 1, fp);
  2834 + if (rc)
  2835 + return rc;
  2836 + rc = context_write(p, &c->context[0], fp);
  2837 + if (rc)
  2838 + return rc;
  2839 + break;
  2840 + case OCON_FS:
  2841 + case OCON_NETIF:
  2842 + len = strlen(c->u.name);
  2843 + buf[0] = cpu_to_le32(len);
  2844 + rc = put_entry(buf, sizeof(u32), 1, fp);
  2845 + if (rc)
  2846 + return rc;
  2847 + rc = put_entry(c->u.name, 1, len, fp);
  2848 + if (rc)
  2849 + return rc;
  2850 + rc = context_write(p, &c->context[0], fp);
  2851 + if (rc)
  2852 + return rc;
  2853 + rc = context_write(p, &c->context[1], fp);
  2854 + if (rc)
  2855 + return rc;
  2856 + break;
  2857 + case OCON_PORT:
  2858 + buf[0] = cpu_to_le32(c->u.port.protocol);
  2859 + buf[1] = cpu_to_le32(c->u.port.low_port);
  2860 + buf[2] = cpu_to_le32(c->u.port.high_port);
  2861 + rc = put_entry(buf, sizeof(u32), 3, fp);
  2862 + if (rc)
  2863 + return rc;
  2864 + rc = context_write(p, &c->context[0], fp);
  2865 + if (rc)
  2866 + return rc;
  2867 + break;
  2868 + case OCON_NODE:
  2869 + nodebuf[0] = c->u.node.addr; /* network order */
  2870 + nodebuf[1] = c->u.node.mask; /* network order */
  2871 + rc = put_entry(nodebuf, sizeof(u32), 2, fp);
  2872 + if (rc)
  2873 + return rc;
  2874 + rc = context_write(p, &c->context[0], fp);
  2875 + if (rc)
  2876 + return rc;
  2877 + break;
  2878 + case OCON_FSUSE:
  2879 + buf[0] = cpu_to_le32(c->v.behavior);
  2880 + len = strlen(c->u.name);
  2881 + buf[1] = cpu_to_le32(len);
  2882 + rc = put_entry(buf, sizeof(u32), 2, fp);
  2883 + if (rc)
  2884 + return rc;
  2885 + rc = put_entry(c->u.name, 1, len, fp);
  2886 + if (rc)
  2887 + return rc;
  2888 + rc = context_write(p, &c->context[0], fp);
  2889 + if (rc)
  2890 + return rc;
  2891 + break;
  2892 + case OCON_NODE6:
  2893 + for (j = 0; j < 4; j++)
  2894 + nodebuf[j] = c->u.node6.addr[j]; /* network order */
  2895 + for (j = 0; j < 4; j++)
  2896 + nodebuf[j + 4] = c->u.node6.mask[j]; /* network order */
  2897 + rc = put_entry(nodebuf, sizeof(u32), 8, fp);
  2898 + if (rc)
  2899 + return rc;
  2900 + rc = context_write(p, &c->context[0], fp);
  2901 + if (rc)
  2902 + return rc;
  2903 + break;
  2904 + }
  2905 + }
  2906 + }
  2907 + return 0;
  2908 +}
  2909 +
  2910 +static int genfs_write(struct policydb *p, void *fp)
  2911 +{
  2912 + struct genfs *genfs;
  2913 + struct ocontext *c;
  2914 + size_t len;
  2915 + __le32 buf[1];
  2916 + int rc;
  2917 +
  2918 + len = 0;
  2919 + for (genfs = p->genfs; genfs; genfs = genfs->next)
  2920 + len++;
  2921 + buf[0] = cpu_to_le32(len);
  2922 + rc = put_entry(buf, sizeof(u32), 1, fp);
  2923 + if (rc)
  2924 + return rc;
  2925 + for (genfs = p->genfs; genfs; genfs = genfs->next) {
  2926 + len = strlen(genfs->fstype);
  2927 + buf[0] = cpu_to_le32(len);
  2928 + rc = put_entry(buf, sizeof(u32), 1, fp);
  2929 + if (rc)
  2930 + return rc;
  2931 + rc = put_entry(genfs->fstype, 1, len, fp);
  2932 + if (rc)
  2933 + return rc;
  2934 + len = 0;
  2935 + for (c = genfs->head; c; c = c->next)
  2936 + len++;
  2937 + buf[0] = cpu_to_le32(len);
  2938 + rc = put_entry(buf, sizeof(u32), 1, fp);
  2939 + if (rc)
  2940 + return rc;
  2941 + for (c = genfs->head; c; c = c->next) {
  2942 + len = strlen(c->u.name);
  2943 + buf[0] = cpu_to_le32(len);
  2944 + rc = put_entry(buf, sizeof(u32), 1, fp);
  2945 + if (rc)
  2946 + return rc;
  2947 + rc = put_entry(c->u.name, 1, len, fp);
  2948 + if (rc)
  2949 + return rc;
  2950 + buf[0] = cpu_to_le32(c->v.sclass);
  2951 + rc = put_entry(buf, sizeof(u32), 1, fp);
  2952 + if (rc)
  2953 + return rc;
  2954 + rc = context_write(p, &c->context[0], fp);
  2955 + if (rc)
  2956 + return rc;
  2957 + }
  2958 + }
  2959 + return 0;
  2960 +}
  2961 +
  2962 +static int range_count(void *key, void *data, void *ptr)
  2963 +{
  2964 + int *cnt = ptr;
  2965 + *cnt = *cnt + 1;
  2966 +
  2967 + return 0;
  2968 +}
  2969 +
  2970 +static int range_write_helper(void *key, void *data, void *ptr)
  2971 +{
  2972 + __le32 buf[2];
  2973 + struct range_trans *rt = key;
  2974 + struct mls_range *r = data;
  2975 + struct policy_data *pd = ptr;
  2976 + void *fp = pd->fp;
  2977 + struct policydb *p = pd->p;
  2978 + int rc;
  2979 +
  2980 + buf[0] = cpu_to_le32(rt->source_type);
  2981 + buf[1] = cpu_to_le32(rt->target_type);
  2982 + rc = put_entry(buf, sizeof(u32), 2, fp);
  2983 + if (rc)
  2984 + return rc;
  2985 + if (p->policyvers >= POLICYDB_VERSION_RANGETRANS) {
  2986 + buf[0] = cpu_to_le32(rt->target_class);
  2987 + rc = put_entry(buf, sizeof(u32), 1, fp);
  2988 + if (rc)
  2989 + return rc;
  2990 + }
  2991 + rc = mls_write_range_helper(r, fp);
  2992 + if (rc)
  2993 + return rc;
  2994 +
  2995 + return 0;
  2996 +}
  2997 +
  2998 +static int range_write(struct policydb *p, void *fp)
  2999 +{
  3000 + size_t nel;
  3001 + __le32 buf[1];
  3002 + int rc;
  3003 + struct policy_data pd;
  3004 +
  3005 + pd.p = p;
  3006 + pd.fp = fp;
  3007 +
  3008 + /* count the number of entries in the hashtab */
  3009 + nel = 0;
  3010 + rc = hashtab_map(p->range_tr, range_count, &nel);
  3011 + if (rc)
  3012 + return rc;
  3013 +
  3014 + buf[0] = cpu_to_le32(nel);
  3015 + rc = put_entry(buf, sizeof(u32), 1, fp);
  3016 + if (rc)
  3017 + return rc;
  3018 +
  3019 + /* actually write all of the entries */
  3020 + rc = hashtab_map(p->range_tr, range_write_helper, &pd);
  3021 + if (rc)
  3022 + return rc;
  3023 +
  3024 + return 0;
  3025 +}
  3026 +
  3027 +/*
  3028 + * Write the configuration data in a policy database
  3029 + * structure to a policy database binary representation
  3030 + * file.
  3031 + */
  3032 +int policydb_write(struct policydb *p, void *fp)
  3033 +{
  3034 + unsigned int i, num_syms;
  3035 + int rc;
  3036 + __le32 buf[4];
  3037 + u32 config;
  3038 + size_t len;
  3039 + struct policydb_compat_info *info;
  3040 +
  3041 + /*
  3042 + * refuse to write policy older than compressed avtab
  3043 + * to simplify the writer. There are other tests dropped
  3044 + * since we assume this throughout the writer code. Be
  3045 + * careful if you ever try to remove this restriction
  3046 + */
  3047 + if (p->policyvers < POLICYDB_VERSION_AVTAB) {
  3048 + printk(KERN_ERR "SELinux: refusing to write policy version %d."
  3049 + " Because it is less than version %d\n", p->policyvers,
  3050 + POLICYDB_VERSION_AVTAB);
  3051 + return -EINVAL;
  3052 + }
  3053 +
  3054 + config = 0;
  3055 + if (p->mls_enabled)
  3056 + config |= POLICYDB_CONFIG_MLS;
  3057 +
  3058 + if (p->reject_unknown)
  3059 + config |= REJECT_UNKNOWN;
  3060 + if (p->allow_unknown)
  3061 + config |= ALLOW_UNKNOWN;
  3062 +
  3063 + /* Write the magic number and string identifiers. */
  3064 + buf[0] = cpu_to_le32(POLICYDB_MAGIC);
  3065 + len = strlen(POLICYDB_STRING);
  3066 + buf[1] = cpu_to_le32(len);
  3067 + rc = put_entry(buf, sizeof(u32), 2, fp);
  3068 + if (rc)
  3069 + return rc;
  3070 + rc = put_entry(POLICYDB_STRING, 1, len, fp);
  3071 + if (rc)
  3072 + return rc;
  3073 +
  3074 + /* Write the version, config, and table sizes. */
  3075 + info = policydb_lookup_compat(p->policyvers);
  3076 + if (!info) {
  3077 + printk(KERN_ERR "SELinux: compatibility lookup failed for policy "
  3078 + "version %d", p->policyvers);
  3079 + return rc;
  3080 + }
  3081 +
  3082 + buf[0] = cpu_to_le32(p->policyvers);
  3083 + buf[1] = cpu_to_le32(config);
  3084 + buf[2] = cpu_to_le32(info->sym_num);
  3085 + buf[3] = cpu_to_le32(info->ocon_num);
  3086 +
  3087 + rc = put_entry(buf, sizeof(u32), 4, fp);
  3088 + if (rc)
  3089 + return rc;
  3090 +
  3091 + if (p->policyvers >= POLICYDB_VERSION_POLCAP) {
  3092 + rc = ebitmap_write(&p->policycaps, fp);
  3093 + if (rc)
  3094 + return rc;
  3095 + }
  3096 +
  3097 + if (p->policyvers >= POLICYDB_VERSION_PERMISSIVE) {
  3098 + rc = ebitmap_write(&p->permissive_map, fp);
  3099 + if (rc)
  3100 + return rc;
  3101 + }
  3102 +
  3103 + num_syms = info->sym_num;
  3104 + for (i = 0; i < num_syms; i++) {
  3105 + struct policy_data pd;
  3106 +
  3107 + pd.fp = fp;
  3108 + pd.p = p;
  3109 +
  3110 + buf[0] = cpu_to_le32(p->symtab[i].nprim);
  3111 + buf[1] = cpu_to_le32(p->symtab[i].table->nel);
  3112 +
  3113 + rc = put_entry(buf, sizeof(u32), 2, fp);
  3114 + if (rc)
  3115 + return rc;
  3116 + rc = hashtab_map(p->symtab[i].table, write_f[i], &pd);
  3117 + if (rc)
  3118 + return rc;
  3119 + }
  3120 +
  3121 + rc = avtab_write(p, &p->te_avtab, fp);
  3122 + if (rc)
  3123 + return rc;
  3124 +
  3125 + rc = cond_write_list(p, p->cond_list, fp);
  3126 + if (rc)
  3127 + return rc;
  3128 +
  3129 + rc = role_trans_write(p->role_tr, fp);
  3130 + if (rc)
  3131 + return rc;
  3132 +
  3133 + rc = role_allow_write(p->role_allow, fp);
  3134 + if (rc)
  3135 + return rc;
  3136 +
  3137 + rc = ocontext_write(p, info, fp);
  3138 + if (rc)
  3139 + return rc;
  3140 +
  3141 + rc = genfs_write(p, fp);
  3142 + if (rc)
  3143 + return rc;
  3144 +
  3145 + rc = range_write(p, fp);
  3146 + if (rc)
  3147 + return rc;
  3148 +
  3149 + for (i = 0; i < p->p_types.nprim; i++) {
  3150 + struct ebitmap *e = flex_array_get(p->type_attr_map_array, i);
  3151 +
  3152 + BUG_ON(!e);
  3153 + rc = ebitmap_write(e, fp);
  3154 + if (rc)
  3155 + return rc;
  3156 + }
  3157 +
  3158 + return 0;
2318 3159 }
security/selinux/ss/policydb.h
... ... @@ -254,6 +254,9 @@
254 254  
255 255 struct ebitmap permissive_map;
256 256  
  257 + /* length of this policy when it was loaded */
  258 + size_t len;
  259 +
257 260 unsigned int policyvers;
258 261  
259 262 unsigned int reject_unknown : 1;
... ... @@ -270,6 +273,7 @@
270 273 extern int policydb_type_isvalid(struct policydb *p, unsigned int type);
271 274 extern int policydb_role_isvalid(struct policydb *p, unsigned int role);
272 275 extern int policydb_read(struct policydb *p, void *fp);
  276 +extern int policydb_write(struct policydb *p, void *fp);
273 277  
274 278 #define PERM_SYMTAB_SIZE 32
275 279  
... ... @@ -290,6 +294,11 @@
290 294 size_t len;
291 295 };
292 296  
  297 +struct policy_data {
  298 + struct policydb *p;
  299 + void *fp;
  300 +};
  301 +
293 302 static inline int next_entry(void *buf, struct policy_file *fp, size_t bytes)
294 303 {
295 304 if (bytes > fp->len)
... ... @@ -298,6 +307,17 @@
298 307 memcpy(buf, fp->data, bytes);
299 308 fp->data += bytes;
300 309 fp->len -= bytes;
  310 + return 0;
  311 +}
  312 +
  313 +static inline int put_entry(void *buf, size_t bytes, int num, struct policy_file *fp)
  314 +{
  315 + size_t len = bytes * num;
  316 +
  317 + memcpy(fp->data, buf, len);
  318 + fp->data += len;
  319 + fp->len -= len;
  320 +
301 321 return 0;
302 322 }
303 323  
security/selinux/ss/services.c
... ... @@ -1776,6 +1776,7 @@
1776 1776 return rc;
1777 1777 }
1778 1778  
  1779 + policydb.len = len;
1779 1780 rc = selinux_set_mapping(&policydb, secclass_map,
1780 1781 &current_mapping,
1781 1782 &current_mapping_size);
... ... @@ -1812,6 +1813,7 @@
1812 1813 if (rc)
1813 1814 return rc;
1814 1815  
  1816 + newpolicydb.len = len;
1815 1817 /* If switching between different policy types, log MLS status */
1816 1818 if (policydb.mls_enabled && !newpolicydb.mls_enabled)
1817 1819 printk(KERN_INFO "SELinux: Disabling MLS support...\n");
... ... @@ -1892,6 +1894,17 @@
1892 1894  
1893 1895 }
1894 1896  
  1897 +size_t security_policydb_len(void)
  1898 +{
  1899 + size_t len;
  1900 +
  1901 + read_lock(&policy_rwlock);
  1902 + len = policydb.len;
  1903 + read_unlock(&policy_rwlock);
  1904 +
  1905 + return len;
  1906 +}
  1907 +
1895 1908 /**
1896 1909 * security_port_sid - Obtain the SID for a port.
1897 1910 * @protocol: protocol number
... ... @@ -3139,4 +3152,39 @@
3139 3152 return rc;
3140 3153 }
3141 3154 #endif /* CONFIG_NETLABEL */
  3155 +
  3156 +/**
  3157 + * security_read_policy - read the policy.
  3158 + * @data: binary policy data
  3159 + * @len: length of data in bytes
  3160 + *
  3161 + */
  3162 +int security_read_policy(void **data, ssize_t *len)
  3163 +{
  3164 + int rc;
  3165 + struct policy_file fp;
  3166 +
  3167 + if (!ss_initialized)
  3168 + return -EINVAL;
  3169 +
  3170 + *len = security_policydb_len();
  3171 +
  3172 + *data = vmalloc(*len);
  3173 + if (!*data)
  3174 + return -ENOMEM;
  3175 +
  3176 + fp.data = *data;
  3177 + fp.len = *len;
  3178 +
  3179 + read_lock(&policy_rwlock);
  3180 + rc = policydb_write(&policydb, &fp);
  3181 + read_unlock(&policy_rwlock);
  3182 +
  3183 + if (rc)
  3184 + return rc;
  3185 +
  3186 + *len = (unsigned long)fp.data - (unsigned long)*data;
  3187 + return 0;
  3188 +
  3189 +}