aboutsummaryrefslogtreecommitdiffstats
path: root/security/selinux/ss/policydb.c
diff options
context:
space:
mode:
authorEric Paris <eparis@redhat.com>2010-10-13 17:50:25 -0400
committerJames Morris <jmorris@namei.org>2010-10-20 19:12:58 -0400
commitcee74f47a6baba0ac457e87687fdcf0abd599f0a (patch)
tree3d9fdb073050664e62d9cdb6c28112090cd138da /security/selinux/ss/policydb.c
parent00d85c83ac52e2c1a66397f1abc589f80c543425 (diff)
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>
Diffstat (limited to 'security/selinux/ss/policydb.c')
-rw-r--r--security/selinux/ss/policydb.c841
1 files changed, 841 insertions, 0 deletions
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
index 97fb0cf0eb69..94f630d93a5c 100644
--- a/security/selinux/ss/policydb.c
+++ b/security/selinux/ss/policydb.c
@@ -37,6 +37,7 @@
37#include "policydb.h" 37#include "policydb.h"
38#include "conditional.h" 38#include "conditional.h"
39#include "mls.h" 39#include "mls.h"
40#include "services.h"
40 41
41#define _DEBUG_HASHES 42#define _DEBUG_HASHES
42 43
@@ -2316,3 +2317,843 @@ bad:
2316 policydb_destroy(p); 2317 policydb_destroy(p);
2317 goto out; 2318 goto out;
2318} 2319}
2320
2321/*
2322 * Write a MLS level structure to a policydb binary
2323 * representation file.
2324 */
2325static 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 */
2346static 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
2381static 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
2409static 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
2434static 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
2460static 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 */
2488static 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
2515static 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
2537static 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
2567static 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
2608static 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
2679static 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
2718static 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
2759static 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
2800static 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
2813static 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
2910static 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
2962static int range_count(void *key, void *data, void *ptr)
2963{
2964 int *cnt = ptr;
2965 *cnt = *cnt + 1;
2966
2967 return 0;
2968}
2969
2970static 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
2998static 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 */
3032int 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;
3159}