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

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

 



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>

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



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

  Powered by Linux