Neverallow rules for ioctl extended permissions will pass in two cases: 1. If extended permissions exist for the source-target-class set the test will pass if the neverallow values are excluded. 2. If extended permissions do not exist for the source-target-class set the test will pass if the ioctl permission is not granted. Signed-off-by: Jeff Vander Stoep <jeffv@xxxxxxxxxx> --- checkpolicy/policy_define.c | 38 +++++- checkpolicy/policy_parse.y | 5 + checkpolicy/policy_scan.l | 8 +- checkpolicy/test/dispol.c | 62 +-------- libsepol/include/sepol/policydb/avtab.h | 1 + libsepol/include/sepol/policydb/policydb.h | 10 +- libsepol/include/sepol/policydb/util.h | 2 + libsepol/src/assertion.c | 194 +++++++++++++++++++++++++++-- libsepol/src/expand.c | 23 +++- libsepol/src/util.c | 72 +++++++++++ 10 files changed, 331 insertions(+), 84 deletions(-) diff --git a/checkpolicy/policy_define.c b/checkpolicy/policy_define.c index 7f32029..ee20fea 100644 --- a/checkpolicy/policy_define.c +++ b/checkpolicy/policy_define.c @@ -1729,10 +1729,6 @@ avrule_t *define_cond_pol_list(avrule_t * avlist, avrule_t * sl) return sl; } -#define xperm_test(x, p) (1 & (p[x >> 5] >> (x & 0x1f))) -#define xperm_set(x, p) (p[x >> 5] |= (1 << (x & 0x1f))) -#define xperm_clear(x, p) (p[x >> 5] &= ~(1 << (x & 0x1f))) - typedef struct av_ioctl_range { uint16_t low; uint16_t high; @@ -1942,6 +1938,8 @@ int define_te_avtab_xperms_helper(int which, avrule_t ** rule) { char *id; class_perm_node_t *perms, *tail = NULL, *cur_perms = NULL; + class_datum_t *cladatum; + perm_datum_t *perdatum = NULL; ebitmap_t tclasses; ebitmap_node_t *node; avrule_t *avrule; @@ -1968,7 +1966,7 @@ int define_te_avtab_xperms_helper(int which, avrule_t ** rule) while ((id = queue_remove(id_queue))) { if (set_types (&avrule->stypes, id, &add, - which == AVRULE_NEVERALLOW ? 1 : 0)) { + which == AVRULE_XPERMS_NEVERALLOW ? 1 : 0)) { ret = -1; goto out; } @@ -1982,7 +1980,7 @@ int define_te_avtab_xperms_helper(int which, avrule_t ** rule) } if (set_types (&avrule->ttypes, id, &add, - which == AVRULE_NEVERALLOW ? 1 : 0)) { + which == AVRULE_XPERMS_NEVERALLOW ? 1 : 0)) { ret = -1; goto out; } @@ -1994,6 +1992,7 @@ int define_te_avtab_xperms_helper(int which, avrule_t ** rule) goto out; perms = NULL; + id = queue_head(id_queue); ebitmap_for_each_bit(&tclasses, node, i) { if (!ebitmap_node_get_bit(node, i)) continue; @@ -2011,6 +2010,29 @@ int define_te_avtab_xperms_helper(int which, avrule_t ** rule) if (tail) tail->next = cur_perms; tail = cur_perms; + + cladatum = policydbp->class_val_to_struct[i]; + perdatum = hashtab_search(cladatum->permissions.table, id); + if (!perdatum) { + if (cladatum->comdatum) { + perdatum = hashtab_search(cladatum->comdatum-> + permissions.table, + id); + } + } + if (!perdatum) { + yyerror2("permission %s is not defined" + " for class %s", id, + policydbp->p_class_val_to_name[i]); + continue; + } else if (!is_perm_in_scope (id, policydbp->p_class_val_to_name[i])) { + yyerror2("permission %s of class %s is" + " not within scope", id, + policydbp->p_class_val_to_name[i]); + continue; + } else { + cur_perms->data |= 1U << (perdatum->s.value - 1); + } } ebitmap_destroy(&tclasses); @@ -2246,6 +2268,10 @@ int avrule_cpy(avrule_t *dest, avrule_t *src) } dest->line = src->line; dest->source_filename = strdup(source_file); + if (!dest->source_filename) { + yyerror("out of memory"); + return -1; + } dest->source_line = src->source_line; /* increment through the class perms and copy over */ diff --git a/checkpolicy/policy_parse.y b/checkpolicy/policy_parse.y index d8b8ac0..3b6a2f8 100644 --- a/checkpolicy/policy_parse.y +++ b/checkpolicy/policy_parse.y @@ -129,6 +129,7 @@ typedef int (* require_func_t)(int pass); %token ALLOWXPERM %token AUDITALLOWXPERM %token DONTAUDITXPERM +%token NEVERALLOWXPERM %token SOURCE %token TARGET %token SAMEUSER @@ -463,6 +464,7 @@ te_avtab_def : allow_def | xperm_allow_def | xperm_auditallow_def | xperm_dontaudit_def + | xperm_neverallow_def ; allow_def : ALLOW names names ':' names names ';' {if (define_te_avtab(AVRULE_ALLOWED)) return -1; } @@ -488,6 +490,9 @@ xperm_auditallow_def : AUDITALLOWXPERM names names ':' names identifier xperms ' xperm_dontaudit_def : DONTAUDITXPERM names names ':' names identifier xperms ';' {if (define_te_avtab_extended_perms(AVRULE_XPERMS_DONTAUDIT)) return -1; } ; +xperm_neverallow_def : NEVERALLOWXPERM names names ':' names identifier xperms ';' + {if (define_te_avtab_extended_perms(AVRULE_XPERMS_NEVERALLOW)) return -1; } + ; attribute_role_def : ATTRIBUTE_ROLE identifier ';' {if (define_attrib_role()) return -1; } ; diff --git a/checkpolicy/policy_scan.l b/checkpolicy/policy_scan.l index e94a917..22da338 100644 --- a/checkpolicy/policy_scan.l +++ b/checkpolicy/policy_scan.l @@ -143,11 +143,13 @@ auditdeny { return(AUDITDENY); } DONTAUDIT | dontaudit { return(DONTAUDIT); } ALLOWXPERM | -allowxperm { return(ALLOWXPERM); } +allowxperm { return(ALLOWXPERM); } AUDITALLOWXPERM | -auditallowxperm { return(AUDITALLOWXPERM); } +auditallowxperm { return(AUDITALLOWXPERM); } DONTAUDITXPERM | -dontauditxperm { return(DONTAUDITXPERM); } +dontauditxperm { return(DONTAUDITXPERM); } +NEVERALLOWXPERM | +neverallowxperm { return(NEVERALLOWXPERM); } SOURCE | source { return(SOURCE); } TARGET | diff --git a/checkpolicy/test/dispol.c b/checkpolicy/test/dispol.c index 0c6b8d8..86f5688 100644 --- a/checkpolicy/test/dispol.c +++ b/checkpolicy/test/dispol.c @@ -54,65 +54,6 @@ int render_access_mask(uint32_t mask, avtab_key_t * key, policydb_t * p, return 0; } -#define xperms_test(x, p) (1 & (p[x >> 5] >> (x & 0x1f))) -#define next_bit_in_range(i, p) \ - ((i + 1 < sizeof(p)*8) && xperms_test((i + 1), p)) - -int render_ioctl(avtab_extended_perms_t * xperms, FILE * fp) -{ - uint16_t value; - uint16_t low_bit; - uint16_t low_value; - unsigned int bit; - unsigned int in_range = 0; - - fprintf(fp, "{ "); - for (bit = 0; bit < sizeof(xperms->perms)*8; bit++) { - if (!xperms_test(bit, xperms->perms)) - continue; - - if (in_range && next_bit_in_range(bit, xperms->perms)) { - /* continue until high value found */ - continue; - } else if (next_bit_in_range(bit, xperms->perms)) { - /* low value */ - low_bit = bit; - in_range = 1; - continue; - } - - if (xperms->specified & AVTAB_XPERMS_IOCTLFUNCTION) { - value = xperms->driver<<8 | bit; - low_value = xperms->driver<<8 | low_bit; - if (in_range) - fprintf(fp, "0x%hx-0x%hx ", low_value, value); - else - fprintf(fp, "0x%hx ", value); - } else if (xperms->specified & AVTAB_XPERMS_IOCTLDRIVER) { - value = bit << 8; - low_value = low_bit << 8; - if (in_range) - fprintf(fp, "0x%hx-0x%hx ", low_value, (uint16_t) (value|0xff)); - else - fprintf(fp, "0x%hx-0x%hx ", value, (uint16_t) (value|0xff)); - - } - if (in_range) - in_range = 0; - } - fprintf(fp, "}"); - return 0; -} - -int render_xperms(avtab_extended_perms_t * xperms, FILE * fp) -{ - if ((xperms->specified == AVTAB_XPERMS_IOCTLFUNCTION) || - (xperms->specified == AVTAB_XPERMS_IOCTLDRIVER)) - render_ioctl(xperms, fp); - - return 0; -} - int render_type(uint32_t type, policydb_t * p, FILE * fp) { fprintf(fp, "%s", p->p_type_val_to_name[type - 1]); @@ -214,8 +155,7 @@ int render_av_rule(avtab_key_t * key, avtab_datum_t * datum, uint32_t what, else if (key->specified & AVTAB_XPERMS_DONTAUDIT) fprintf(fp, "dontauditxperm "); render_key(key, p, fp); - render_xperms(datum->xperms, fp); - fprintf(fp, ";\n"); + fprintf(fp, "%s;\n", sepol_extended_perms_to_string(datum->xperms)); } else { fprintf(fp, " ERROR: no valid rule type specified\n"); return -1; diff --git a/libsepol/include/sepol/policydb/avtab.h b/libsepol/include/sepol/policydb/avtab.h index 14bc082..d3ea84e 100644 --- a/libsepol/include/sepol/policydb/avtab.h +++ b/libsepol/include/sepol/policydb/avtab.h @@ -62,6 +62,7 @@ typedef struct avtab_key { #define AVTAB_XPERMS_ALLOWED 0x0100 #define AVTAB_XPERMS_AUDITALLOW 0x0200 #define AVTAB_XPERMS_DONTAUDIT 0x0400 +#define AVTAB_XPERMS_NEVERALLOW 0x0800 #define AVTAB_XPERMS (AVTAB_XPERMS_ALLOWED | AVTAB_XPERMS_AUDITALLOW | AVTAB_XPERMS_DONTAUDIT) #define AVTAB_ENABLED_OLD 0x80000000 #define AVTAB_ENABLED 0x8000 /* reserved for used in cond_avtab */ diff --git a/libsepol/include/sepol/policydb/policydb.h b/libsepol/include/sepol/policydb/policydb.h index 5da016b..26cec13 100644 --- a/libsepol/include/sepol/policydb/policydb.h +++ b/libsepol/include/sepol/policydb/policydb.h @@ -241,13 +241,18 @@ typedef struct class_perm_node { struct class_perm_node *next; } class_perm_node_t; +#define xperm_test(x, p) (1 & (p[x >> 5] >> (x & 0x1f))) +#define xperm_set(x, p) (p[x >> 5] |= (1 << (x & 0x1f))) +#define xperm_clear(x, p) (p[x >> 5] &= ~(1 << (x & 0x1f))) +#define EXTENDED_PERMS_LEN 8 + typedef struct av_extended_perms { #define AVRULE_XPERMS_IOCTLFUNCTION 0x01 #define AVRULE_XPERMS_IOCTLDRIVER 0x02 uint8_t specified; uint8_t driver; /* 256 bits of permissions */ - uint32_t perms[8]; + uint32_t perms[EXTENDED_PERMS_LEN]; } av_extended_perms_t; typedef struct avrule { @@ -266,8 +271,9 @@ typedef struct avrule { #define AVRULE_XPERMS_ALLOWED 0x0100 #define AVRULE_XPERMS_AUDITALLOW 0x0200 #define AVRULE_XPERMS_DONTAUDIT 0x0400 +#define AVRULE_XPERMS_NEVERALLOW 0x0800 #define AVRULE_XPERMS (AVRULE_XPERMS_ALLOWED | AVRULE_XPERMS_AUDITALLOW | \ - AVRULE_XPERMS_DONTAUDIT) + AVRULE_XPERMS_DONTAUDIT | AVRULE_XPERMS_NEVERALLOW) uint32_t specified; #define RULE_SELF 1 uint32_t flags; diff --git a/libsepol/include/sepol/policydb/util.h b/libsepol/include/sepol/policydb/util.h index cb97ccf..fa12661 100644 --- a/libsepol/include/sepol/policydb/util.h +++ b/libsepol/include/sepol/policydb/util.h @@ -32,6 +32,8 @@ extern int add_i_to_a(uint32_t i, uint32_t * cnt, uint32_t ** a); extern char *sepol_av_to_string(policydb_t * policydbp, uint32_t tclass, sepol_access_vector_t av); +char *sepol_extended_perms_to_string(avtab_extended_perms_t *xperms); + /* * The tokenize function may be used to * replace sscanf diff --git a/libsepol/src/assertion.c b/libsepol/src/assertion.c index d9afbde..5aec658 100644 --- a/libsepol/src/assertion.c +++ b/libsepol/src/assertion.c @@ -1,8 +1,8 @@ /* Authors: Joshua Brindle <jbrindle@xxxxxxxxxx> - * - * Assertion checker for avtab entries, taken from + * + * Assertion checker for avtab entries, taken from * checkpolicy.c by Stephen Smalley <sds@xxxxxxxxxxxxx> - * + * * Copyright (C) 2005 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or @@ -25,12 +25,14 @@ #include <sepol/policydb/expand.h> #include <sepol/policydb/util.h> +#include "private.h" #include "debug.h" struct avtab_match_args { sepol_handle_t *handle; policydb_t *p; avrule_t *avrule; + avtab_t *avtab; unsigned long errors; }; @@ -73,6 +75,125 @@ static int match_any_class_permissions(class_perm_node_t *cp, uint32_t class, ui return 1; } +static int extended_permissions_and(uint32_t *perms1, uint32_t *perms2) { + size_t i; + for (i = 0; i < EXTENDED_PERMS_LEN; i++) { + if (perms1[i] & perms2[i]) + return 1; + } + + return 0; +} + +static int check_extended_permissions(av_extended_perms_t *neverallow, avtab_extended_perms_t *allow) +{ + int rc = 0; + if ((neverallow->specified == AVRULE_XPERMS_IOCTLFUNCTION) + && (allow->specified == AVTAB_XPERMS_IOCTLFUNCTION)) { + if (neverallow->driver == allow->driver) + rc = extended_permissions_and(neverallow->perms, allow->perms); + } else if ((neverallow->specified == AVRULE_XPERMS_IOCTLFUNCTION) + && (allow->specified == AVTAB_XPERMS_IOCTLDRIVER)) { + rc = xperm_test(neverallow->driver, allow->perms); + } else if ((neverallow->specified == AVRULE_XPERMS_IOCTLDRIVER) + && (allow->specified == AVTAB_XPERMS_IOCTLFUNCTION)) { + rc = xperm_test(allow->driver, neverallow->perms); + } else if ((neverallow->specified == AVRULE_XPERMS_IOCTLDRIVER) + && (allow->specified == AVTAB_XPERMS_IOCTLDRIVER)) { + rc = extended_permissions_and(neverallow->perms, allow->perms); + } + + return rc; +} + +/* Compute which allowed extended permissions violate the neverallow rule */ +static void extended_permissions_violated(avtab_extended_perms_t *result, + av_extended_perms_t *neverallow, + avtab_extended_perms_t *allow) +{ + size_t i; + if ((neverallow->specified == AVRULE_XPERMS_IOCTLFUNCTION) + && (allow->specified == AVTAB_XPERMS_IOCTLFUNCTION)) { + result->specified = AVTAB_XPERMS_IOCTLFUNCTION; + result->driver = allow->driver; + for (i = 0; i < EXTENDED_PERMS_LEN; i++) + result->perms[i] = neverallow->perms[i] & allow->perms[i]; + } else if ((neverallow->specified == AVRULE_XPERMS_IOCTLFUNCTION) + && (allow->specified == AVTAB_XPERMS_IOCTLDRIVER)) { + result->specified = AVTAB_XPERMS_IOCTLFUNCTION; + result->driver = neverallow->driver; + memcpy(result->perms, neverallow->perms, sizeof(result->perms)); + } else if ((neverallow->specified == AVRULE_XPERMS_IOCTLDRIVER) + && (allow->specified == AVTAB_XPERMS_IOCTLFUNCTION)) { + result->specified = AVTAB_XPERMS_IOCTLFUNCTION; + result->driver = allow->driver; + memcpy(result->perms, allow->perms, sizeof(result->perms)); + } else if ((neverallow->specified == AVRULE_XPERMS_IOCTLDRIVER) + && (allow->specified == AVTAB_XPERMS_IOCTLDRIVER)) { + result->specified = AVTAB_XPERMS_IOCTLDRIVER; + for (i = 0; i < EXTENDED_PERMS_LEN; i++) + result->perms[i] = neverallow->perms[i] & allow->perms[i]; + } +} + +/* Same scenarios of interest as check_assertion_extended_permissions */ +static int report_assertion_extended_permissions(sepol_handle_t *handle, + policydb_t *p, const avrule_t *avrule, + unsigned int stype, unsigned int ttype, + const class_perm_node_t *curperm, uint32_t perms, + avtab_key_t *k, avtab_t *avtab) +{ + avtab_ptr_t node; + avtab_key_t tmp_key; + avtab_extended_perms_t *xperms; + avtab_extended_perms_t error; + int rc = 1; + int ret = 0; + + memcpy(&tmp_key, k, sizeof(avtab_key_t)); + tmp_key.specified = AVTAB_XPERMS_ALLOWED; + + for (node = avtab_search_node(avtab, &tmp_key); + node; + node = avtab_search_node_next(node, tmp_key.specified)) { + xperms = node->datum.xperms; + if ((xperms->specified != AVTAB_XPERMS_IOCTLFUNCTION) + && (xperms->specified != AVTAB_XPERMS_IOCTLDRIVER)) + continue; + + rc = check_extended_permissions(avrule->xperms, xperms); + /* failure on the extended permission check_extended_permissionss */ + if (rc) { + extended_permissions_violated(&error, avrule->xperms, xperms); + ERR(handle, "neverallowxperm on line %lu of %s (or line %lu of policy.conf) violated by\n" + "allowxperm %s %s:%s %s;", + avrule->source_line, avrule->source_filename, avrule->line, + p->p_type_val_to_name[stype], + p->p_type_val_to_name[ttype], + p->p_class_val_to_name[curperm->tclass - 1], + sepol_extended_perms_to_string(&error)); + + rc = 0; + ret++; + } + + } + + /* failure on the regular permissions */ + if (rc) { + ERR(handle, "neverallowxperm on line %lu of %s (or line %lu of policy.conf) violated by\n" + "allow %s %s:%s {%s };", + avrule->source_line, avrule->source_filename, avrule->line, + p->p_type_val_to_name[stype], + p->p_type_val_to_name[ttype], + p->p_class_val_to_name[curperm->tclass - 1], + sepol_av_to_string(p, curperm->tclass, perms)); + ret++; + + } + + return ret; +} static int report_assertion_avtab_matches(avtab_key_t *k, avtab_datum_t *d, void *args) { @@ -80,6 +201,7 @@ static int report_assertion_avtab_matches(avtab_key_t *k, avtab_datum_t *d, void struct avtab_match_args *a = (struct avtab_match_args *)args; sepol_handle_t *handle = a->handle; policydb_t *p = a->p; + avtab_t *avtab = a->avtab; avrule_t *avrule = a->avrule; class_perm_node_t *cp; uint32_t perms; @@ -122,6 +244,7 @@ static int report_assertion_avtab_matches(avtab_key_t *k, avtab_datum_t *d, void goto exit; for (cp = avrule->perms; cp; cp = cp->next) { + perms = cp->data & d->data; if ((cp->tclass != k->target_class) || !perms) { continue; @@ -133,12 +256,17 @@ static int report_assertion_avtab_matches(avtab_key_t *k, avtab_datum_t *d, void ebitmap_for_each_bit(&tgt_matches, tnode, j) { if (!ebitmap_node_get_bit(tnode, j)) continue; - a->errors++; - report_failure(handle, p, avrule, i, j, cp, perms); + + if (avrule->specified == AVRULE_XPERMS_NEVERALLOW) { + a->errors += report_assertion_extended_permissions(handle,p, avrule, + i, j, cp, perms, k, avtab); + } else { + a->errors++; + report_failure(handle, p, avrule, i, j, cp, perms); + } } } } - goto exit; oom: @@ -175,12 +303,57 @@ oom: return rc; } +/* + * If the ioctl permission is granted in check_assertion_avtab_match for the + * source/target/class matching the current avrule neverallow, a lookup is + * performed to determine if extended permissions exist for the source/target/class. + * + * Four scenarios of interest: + * 1. PASS - the ioctl permission is not granted for this source/target/class + * This case is handled in check_assertion_avtab_match + * 2. PASS - The ioctl permission is granted AND the extended permission + * is NOT granted + * 3. FAIL - The ioctl permission is granted AND no extended permissions + * exist + * 4. FAIL - The ioctl permission is granted AND the extended permission is + * granted + */ +static int check_assertion_extended_permissions(avrule_t *avrule, avtab_t *avtab, + avtab_key_t *k) +{ + avtab_ptr_t node; + avtab_key_t tmp_key; + avtab_extended_perms_t *xperms; + av_extended_perms_t *neverallow_xperms = avrule->xperms; + int rc = 1; + + memcpy(&tmp_key, k, sizeof(avtab_key_t)); + tmp_key.specified = AVTAB_XPERMS_ALLOWED; + + for (node = avtab_search_node(avtab, &tmp_key); + node; + node = avtab_search_node_next(node, tmp_key.specified)) { + xperms = node->datum.xperms; + if ((xperms->specified != AVTAB_XPERMS_IOCTLFUNCTION) + && (xperms->specified != AVTAB_XPERMS_IOCTLDRIVER)) + continue; + + rc = check_extended_permissions(neverallow_xperms, xperms); + if (rc) + break; + } + + return rc; +} + + static int check_assertion_avtab_match(avtab_key_t *k, avtab_datum_t *d, void *args) { int rc; struct avtab_match_args *a = (struct avtab_match_args *)args; policydb_t *p = a->p; avrule_t *avrule = a->avrule; + avtab_t *avtab = a->avtab; if (k->specified != AVTAB_ALLOWED) goto exit; @@ -212,6 +385,11 @@ static int check_assertion_avtab_match(avtab_key_t *k, avtab_datum_t *d, void *a if (rc == 0) goto exit; + if (avrule->specified == AVRULE_XPERMS_NEVERALLOW) { + rc = check_assertion_extended_permissions(avrule, avtab, k); + if (rc == 0) + goto exit; + } return 1; exit: @@ -231,10 +409,12 @@ int check_assertion(policydb_t *p, avrule_t *avrule) args.p = p; args.avrule = avrule; args.errors = 0; + args.avtab = &p->te_avtab; rc = avtab_map(&p->te_avtab, check_assertion_avtab_match, &args); if (rc == 0) { + args.avtab = &p->te_cond_avtab; rc = avtab_map(&p->te_cond_avtab, check_assertion_avtab_match, &args); } @@ -256,7 +436,7 @@ int check_assertions(sepol_handle_t * handle, policydb_t * p, } for (a = avrules; a != NULL; a = a->next) { - if (!(a->specified & AVRULE_NEVERALLOW)) + if (!(a->specified & (AVRULE_NEVERALLOW | AVRULE_XPERMS_NEVERALLOW))) continue; rc = check_assertion(p, a); if (rc) { diff --git a/libsepol/src/expand.c b/libsepol/src/expand.c index 7b99f40..9047c6d 100644 --- a/libsepol/src/expand.c +++ b/libsepol/src/expand.c @@ -1948,6 +1948,8 @@ static int convert_and_expand_rule(sepol_handle_t * handle, if (!do_neverallow && source_rule->specified & AVRULE_NEVERALLOW) return EXPAND_RULE_SUCCESS; + if (source_rule->specified & AVRULE_XPERMS_NEVERALLOW) + return EXPAND_RULE_SUCCESS; ebitmap_init(&stypes); ebitmap_init(&ttypes); @@ -2378,7 +2380,8 @@ int expand_rule(sepol_handle_t * handle, int retval; ebitmap_t stypes, ttypes; - if (source_rule->specified & AVRULE_NEVERALLOW) + if ((source_rule->specified & AVRULE_NEVERALLOW) + || (source_rule->specified & AVRULE_XPERMS_NEVERALLOW)) return 1; ebitmap_init(&stypes); @@ -2592,6 +2595,7 @@ static int copy_neverallow(policydb_t * dest_pol, uint32_t * typemap, ebitmap_t stypes, ttypes; avrule_t *avrule; class_perm_node_t *cur_perm, *new_perm, *tail_perm; + av_extended_perms_t *xperms = NULL; ebitmap_init(&stypes); ebitmap_init(&ttypes); @@ -2608,7 +2612,7 @@ static int copy_neverallow(policydb_t * dest_pol, uint32_t * typemap, return -1; avrule_init(avrule); - avrule->specified = AVRULE_NEVERALLOW; + avrule->specified = source_rule->specified; avrule->line = source_rule->line; avrule->flags = source_rule->flags; avrule->source_line = source_rule->source_line; @@ -2647,6 +2651,15 @@ static int copy_neverallow(policydb_t * dest_pol, uint32_t * typemap, cur_perm = cur_perm->next; } + /* copy over extended permissions */ + if (source_rule->xperms) { + xperms = calloc(1, sizeof(av_extended_perms_t)); + if (!xperms) + goto err; + memcpy(xperms, source_rule->xperms, sizeof(av_extended_perms_t)); + avrule->xperms = xperms; + } + /* just prepend the avrule to the first branch; it'll never be written to disk */ if (!dest_pol->global->branch_list->avrules) @@ -2672,6 +2685,7 @@ static int copy_neverallow(policydb_t * dest_pol, uint32_t * typemap, free(cur_perm); cur_perm = tail_perm; } + free(xperms); free(avrule); return -1; } @@ -2724,16 +2738,15 @@ static int copy_and_expand_avrule_block(expand_state_t * state) cur_avrule = decl->avrules; while (cur_avrule != NULL) { if (!(state->expand_neverallow) - && cur_avrule->specified & AVRULE_NEVERALLOW) { + && cur_avrule->specified & (AVRULE_NEVERALLOW | AVRULE_XPERMS_NEVERALLOW)) { /* copy this over directly so that assertions are checked later */ if (copy_neverallow (state->out, state->typemap, cur_avrule)) ERR(state->handle, "Error while copying neverallow."); } else { - if (cur_avrule->specified & AVRULE_NEVERALLOW) { + if (cur_avrule->specified & (AVRULE_NEVERALLOW | AVRULE_XPERMS_NEVERALLOW)) state->out->unsupported_format = 1; - } if (convert_and_expand_rule (state->handle, state->out, state->typemap, cur_avrule, &state->out->te_avtab, NULL, diff --git a/libsepol/src/util.c b/libsepol/src/util.c index 6e285d5..ff8f7f2 100644 --- a/libsepol/src/util.c +++ b/libsepol/src/util.c @@ -119,6 +119,78 @@ char *sepol_av_to_string(policydb_t * policydbp, uint32_t tclass, return avbuf; } +#define next_bit_in_range(i, p) ((i + 1 < sizeof(p)*8) && xperm_test((i + 1), p)) + +char *sepol_extended_perms_to_string(avtab_extended_perms_t *xperms) +{ + uint16_t value; + uint16_t low_bit; + uint16_t low_value; + unsigned int bit; + unsigned int in_range = 0; + static char xpermsbuf[2048]; + xpermsbuf[0] = '\0'; + char *p; + int len, xpermslen = 0; + p = xpermsbuf; + + if ((xperms->specified != AVTAB_XPERMS_IOCTLFUNCTION) + && (xperms->specified != AVTAB_XPERMS_IOCTLDRIVER)) + return NULL; + + len = snprintf(p, sizeof(xpermsbuf) - xpermslen, "ioctl { "); + p += len; + xpermslen += len; + + for (bit = 0; bit < sizeof(xperms->perms)*8; bit++) { + if (!xperm_test(bit, xperms->perms)) + continue; + + if (in_range && next_bit_in_range(bit, xperms->perms)) { + /* continue until high value found */ + continue; + } else if (next_bit_in_range(bit, xperms->perms)) { + /* low value */ + low_bit = bit; + in_range = 1; + continue; + } + + if (xperms->specified & AVTAB_XPERMS_IOCTLFUNCTION) { + value = xperms->driver<<8 | bit; + low_value = xperms->driver<<8 | low_bit; + if (in_range) { + len = snprintf(p, sizeof(xpermsbuf) - xpermslen, "0x%hx-0x%hx ", low_value, value); + } else { + len = snprintf(p, sizeof(xpermsbuf) - xpermslen, "0x%hx ", value); + } + } else if (xperms->specified & AVTAB_XPERMS_IOCTLDRIVER) { + value = bit << 8; + low_value = low_bit << 8; + if (in_range) { + len = snprintf(p, sizeof(xpermsbuf) - xpermslen, "0x%hx-0x%hx ", low_value, (uint16_t) (value|0xff)); + } else { + len = snprintf(p, sizeof(xpermsbuf) - xpermslen, "0x%hx-0x%hx ", value, (uint16_t) (value|0xff)); + } + + } + + if (len < 0 || (size_t) len >= (sizeof(xpermsbuf) - xpermslen)) + return NULL; + + p += len; + xpermslen += len; + if (in_range) + in_range = 0; + } + + len = snprintf(p, sizeof(xpermsbuf) - xpermslen, "}"); + if (len < 0 || (size_t) len >= (sizeof(xpermsbuf) - xpermslen)) + return NULL; + + return xpermsbuf; +} + /* * The tokenize and tokenize_str functions may be used to * replace sscanf to read tokens from buffers. -- 2.6.0.rc0.131.gf624c3d _______________________________________________ Selinux mailing list Selinux@xxxxxxxxxxxxx To unsubscribe, send email to Selinux-leave@xxxxxxxxxxxxx. To get help, send an email containing "help" to Selinux-request@xxxxxxxxxxxxx.