Re: [PATCH] Add neverallow support for ioctl extended permissions

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 09/21/2015 04:10 PM, Stephen Smalley wrote:
> On 09/18/2015 03:57 PM, Jeff Vander Stoep wrote:
>> 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>
> 
> Acked-by:  Stephen Smalley <sds@xxxxxxxxxxxxx>

Thanks, applied.

> 
>> ---
>>  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.
>>
> 
> _______________________________________________
> 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.
> 

_______________________________________________
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.



[Index of Archives]     [Selinux Refpolicy]     [Linux SGX]     [Fedora Users]     [Fedora Desktop]     [Yosemite Photos]     [Yosemite Camping]     [Yosemite Campsites]     [KDE Users]     [Gnome Users]

  Powered by Linux