diff options
Diffstat (limited to 'security/selinux/ss/policydb.c')
-rw-r--r-- | security/selinux/ss/policydb.c | 841 |
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 | */ | ||
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; | ||
3159 | } | ||