RE: [PATCH 1/3] Thread/Child-Domain Assignment

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

 



Stephen Smalley wrote:
> On Fri, 2008-07-25 at 22:03 +0900, KaiGai Kohei wrote:
>> [1/3] thread-context-kernel.1.patch
>>   This patch enables to assign a thread a "weaker" hierarchical
>>   domain, only if the destinated domain is a child of the current
>>   domain. Hierachy relationships are defined in the policy version
>>   24. This patch also enables to read the new version of policy.
> 
> If you are going to take type hierarchy support into the
> kernel, then it seems like it should be completely taken into
> the kernel, i.e. the hierarchy checking should be applied by
> the kernel rather than by the toolchain.  That is what the
> Flask security server did for its extensible policy mechanism.
> 

If we are going to do this we also might as well implement the explicit
hierarchy support and get away from name based hierarchy.

> And I think both the neverallow checking and the type
> hierarchy checking needs to move away from needing to do a
> full expansion in order to check; it is just too expensive these days.
> 

Do you think it will be faster to do attribute based lookups? It will
certainly use significantly less memory.

>> 
>> 
>> Signed-off-by: KaiGai Kohei <kaigai@xxxxxxxxxxxxx>
>> ----
>>  security/selinux/hooks.c            |   11 +++++-
>>  security/selinux/include/security.h |    5 ++-
>>  security/selinux/ss/policydb.c      |   75
> ++++++++++++++++++++++++++++++++--
>>  security/selinux/ss/policydb.h      |    2 +
>>  security/selinux/ss/services.c      |   60
>>  ++++++++++++++++++++++++++++ 5 files changed, 146 insertions(+), 7
>> deletions(-) 
>> 
>> diff --git a/security/selinux/hooks.c
> b/security/selinux/hooks.c index
>> bc1c3ae..d4c1c5c 100644
>> --- a/security/selinux/hooks.c
>> +++ b/security/selinux/hooks.c
>> @@ -5181,7 +5181,12 @@ static int
> selinux_setprocattr(struct task_struct *p,
>>  		if (sid == 0)
>>  			return -EINVAL;
>> 
>> -		/* Only allow single threaded processes to change
context */ +		/*
>> +		 * SELinux allows to change context in the following
case only.
>> +		 *  - Single threaded processes.
>> +		 *  - Multi threaded processes intend to change its
context into
>> +		 *    lower or same domain in hierarchy relationship. +
*/
>>  		if (atomic_read(&p->mm->mm_users) != 1) {
>>  			struct task_struct *g, *t;
>>  			struct mm_struct *mm = p->mm;
>> @@ -5189,11 +5194,15 @@ static int
> selinux_setprocattr(struct task_struct *p,
>>  			do_each_thread(g, t) {
>>  				if (t->mm == mm && t != p) {
>>  					read_unlock(&tasklist_lock);
>> +
>> +					if
> (!security_check_hierarchy(tsec->sid, sid))
>> +						goto hierarchy_ok;
>>  					return -EPERM;
>>  				}
>>  			} while_each_thread(g, t);
>>  			read_unlock(&tasklist_lock);
>>  		}
>> +hierarchy_ok:
>> 
>>  		/* Check permissions for the transition. */
>>  		error = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS,
diff --git
>> a/security/selinux/include/security.h
>> b/security/selinux/include/security.h
>> index ad30ac4..97fa9bb 100644
>> --- a/security/selinux/include/security.h
>> +++ b/security/selinux/include/security.h
>> @@ -27,13 +27,14 @@
>>  #define POLICYDB_VERSION_RANGETRANS	21
>>  #define POLICYDB_VERSION_POLCAP		22
>>  #define POLICYDB_VERSION_PERMISSIVE	23
>> +#define POLICYDB_VERSION_HIERARCHY	24
>> 
>>  /* Range of policy versions we understand*/
>>  #define POLICYDB_VERSION_MIN   POLICYDB_VERSION_BASE
>>  #ifdef CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX
>>  #define POLICYDB_VERSION_MAX
> CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE
>>  #else
>> -#define POLICYDB_VERSION_MAX	POLICYDB_VERSION_PERMISSIVE
>> +#define POLICYDB_VERSION_MAX	POLICYDB_VERSION_HIERARCHY
#endif
>> 
>>  #define CONTEXT_MNT	0x01
>> @@ -118,6 +119,8 @@ int security_net_peersid_resolve(u32 nlbl_sid,
>>  				 u32 nlbl_type,
u32 xfrm_sid, u32 *peer_sid);
>> 
>> +int security_check_hierarchy(u32 old_sid, u32 new_sid); +
>>  int security_get_classes(char ***classes, int *nclasses);  int
>> security_get_permissions(char *class, char ***perms, int *nperms);
>> int security_get_reject_unknown(void);
>> diff --git a/security/selinux/ss/policydb.c
>> b/security/selinux/ss/policydb.c index 84f8cc7..e388f7a 100644
>> --- a/security/selinux/ss/policydb.c
>> +++ b/security/selinux/ss/policydb.c
>> @@ -116,7 +116,12 @@ static struct policydb_compat_info
>>  		policydb_compat[] = { .version	=
POLICYDB_VERSION_PERMISSIVE,
>>  		.sym_num	= SYM_NUM,
>>  		.ocon_num	= OCON_NUM,
>> -	}
>> +	},
>> +	{
>> +		.version	= POLICYDB_VERSION_HIERARCHY,
>> +		.sym_num	= SYM_NUM,
>> +		.ocon_num	= OCON_NUM,
>> +	},
>>  };
>> 
>>  static struct policydb_compat_info *policydb_lookup_compat(int
>> version) @@ -270,9 +275,12 @@ static int type_index(void
> *key, void *datum, void *datap)
>>  	p = datap;
>> 
>>  	if (typdatum->primary) {
>> -		if (!typdatum->value || typdatum->value >
p->p_types.nprim) +		if
>> (!typdatum->value +		    || typdatum->value >
p->p_types.nprim
>> +		    || typdatum->parent > p->p_types.nprim)
>>  			return -EINVAL;
>>  		p->p_type_val_to_name[typdatum->value - 1] = key;
>> +		p->type_val_to_struct[typdatum->value - 1] = typdatum;
}
>> 
>>  	return 0;
>> @@ -397,6 +405,46 @@ static void symtab_hash_eval(struct symtab *s) 
>> } #endif 
>> 
>> +static int type_hierarchy_sanity_checks(struct policydb *p) {
>> +	struct type_datum *type; +	struct ebitmap e;
>> +	int rc = 0, i;
>> +
>> +	if (p->policyvers < POLICYDB_VERSION_HIERARCHY)
>> +		return 0;
>> +
>> +	for (i = 0; i < p->p_types.nprim; i++) {
>> +		type = p->type_val_to_struct[i];
>> +
>> +		if (!type || !type->parent)
>> +			continue;
>> +
>> +		ebitmap_init(&e);
>> +		while (type) {
>> +			if (ebitmap_get_bit(&e, type->value - 1)) {
>> +				printk(KERN_ERR "Hierarchy type
> looped at %s\n",
>> +
> p->p_type_val_to_name[type->value - 1]);
>> +				rc = -EINVAL;
>> +				break;
>> +			}
>> +
>> +			rc = ebitmap_set_bit(&e, type->value - 1, 1);
>> +			if (rc)
>> +				break;
>> +
>> +			if (!type->parent)
>> +				break;
>> +
>> +			type = p->type_val_to_struct[type->parent - 1];
+		}
>> +		ebitmap_destroy(&e);
>> +		if (rc)
>> +			return rc;
>> +	}
>> +	return 0;
>> +}
>> +
>>  /*
>>   * Define the other val_to_name and val_to_struct arrays
>>   * in a policy database structure.
>> @@ -438,6 +486,14 @@ static int
> policydb_index_others(struct policydb *p)
>>  		goto out;
>>  	}
>> 
>> +	p->type_val_to_struct =
>> +		kzalloc(p->p_types.nprim *
> sizeof(*(p->type_val_to_struct)),
>> +			GFP_KERNEL);
>> +	if (!p->type_val_to_struct) {
>> +		rc = -ENOMEM;
>> +		goto out;
>> +	}
>> +
>>  	if (cond_init_bool_indexes(p)) {
>>  		rc = -ENOMEM;
>>  		goto out;
>> @@ -455,6 +511,7 @@ static int policydb_index_others(struct policydb
>>  	*p)  			goto out; }
>> 
>> +	rc = type_hierarchy_sanity_checks(p);
>>  out:
>>  	return rc;
>>  }
>> @@ -625,6 +682,7 @@ void policydb_destroy(struct policydb *p)
>>  	kfree(p->class_val_to_struct);
>>  	kfree(p->role_val_to_struct);
>>  	kfree(p->user_val_to_struct);
>> +	kfree(p->type_val_to_struct);
>> 
>>  	avtab_destroy(&p->te_avtab);
>> 
>> @@ -1236,8 +1294,8 @@ static int type_read(struct policydb *p,
>>  	struct hashtab *h, void *fp)  { char *key = NULL;
>>  	struct type_datum *typdatum;
>> -	int rc;
>> -	__le32 buf[3];
>> +	int to_read, rc;
>> +	__le32 buf[4];
>>  	u32 len;
>> 
>>  	typdatum = kzalloc(sizeof(*typdatum), GFP_KERNEL); @@ -1246,13
>> +1304,20 @@ static int type_read(struct policydb *p, struct hashtab
>>  	*h, void *fp)  		return rc; }
>> 
>> -	rc = next_entry(buf, fp, sizeof buf);
>> +	if (p->policyvers < POLICYDB_VERSION_HIERARCHY)
>> +		to_read = sizeof(u32) * 3;
>> +	else
>> +		to_read = sizeof(u32) * 4;
>> +
>> +	rc = next_entry(buf, fp, to_read);
>>  	if (rc < 0)
>>  		goto bad;
>> 
>>  	len = le32_to_cpu(buf[0]);
>>  	typdatum->value = le32_to_cpu(buf[1]);
>>  	typdatum->primary = le32_to_cpu(buf[2]);
>> +	if (p->policyvers >= POLICYDB_VERSION_HIERARCHY)
>> +		typdatum->parent = le32_to_cpu(buf[3]);
>> 
>>  	key = kmalloc(len + 1, GFP_KERNEL);
>>  	if (!key) {
>> diff --git a/security/selinux/ss/policydb.h
>> b/security/selinux/ss/policydb.h index 4253370..f3484d4 100644
>> --- a/security/selinux/ss/policydb.h
>> +++ b/security/selinux/ss/policydb.h
>> @@ -81,6 +81,7 @@ struct role_allow {
>>  /* Type attributes */
>>  struct type_datum {
>>  	u32 value;		/* internal type value */
>> +	u32 parent;		/* parent type, if hierarchy related */
>>  	unsigned char primary;	/* primary name? */
>>  };
>> 
>> @@ -209,6 +210,7 @@ struct policydb {
>>  	struct class_datum **class_val_to_struct;
>>  	struct role_datum **role_val_to_struct;
>>  	struct user_datum **user_val_to_struct;
>> +	struct type_datum **type_val_to_struct;
>> 
>>  	/* type enforcement access vectors and transitions */  	struct
>> avtab te_avtab; diff --git a/security/selinux/ss/services.c
>> b/security/selinux/ss/services.c index dcc2e1c..3ecd793 100644
>> --- a/security/selinux/ss/services.c
>> +++ b/security/selinux/ss/services.c
>> @@ -2160,6 +2160,66 @@ out_slowpath:
>>  	return rc;
>>  }
>> 
>> +/*
>> + * security_check_hierarchy
>> + *
>> + * It returns 0, if @old_sid is same or upper type of @new_sid in
>> +hierarchy + * relationship directly/indirectly. 1 means @old_sid is
>> not a child +type + * of @new_sid, and negative returns are error.
>> + */
>> +int security_check_hierarchy(u32 old_sid, u32 new_sid) {
>> +	struct context *old_context, *new_context;
>> +	struct type_datum *type;
>> +	int index;
>> +	int rc = -EINVAL;
>> +
>> +	read_lock(&policy_rwlock);
>> +
>> +	old_context = sidtab_search(&sidtab, old_sid);
>> +	if (!old_context) {
>> +		printk(KERN_ERR "SELinux: %s: unrecognized SID %u\n", +

>> __func__, old_sid); +		goto out;
>> +	}
>> +
>> +	new_context = sidtab_search(&sidtab, new_sid);
>> +	if (!new_context) {
>> +		printk(KERN_ERR "SELinux: %s: unrecognized SID %u\n", +

>> __func__, new_sid); +		goto out;
>> +	}
>> +
>> +	/* domain unchanged */
>> +	if (old_context->type == new_context->type) {
>> +		rc = 0;
>> +		goto out;
>> +	}
>> +
>> +	/* check domain hierarchy */
>> +	index = new_context->type;
>> +	while (true) {
>> +		type = policydb.type_val_to_struct[index - 1];
>> +		if (!type)
>> +			break;
>> +
>> +		/* No hierarchy relationship */
>> +		if (type->parent == 0) {
>> +			rc = 1;
>> +			break;
>> +		}
>> +		if (type->parent == old_context->type) {
>> +			rc = 0;
>> +			break;
>> +		}
>> +		index = type->parent;
>> +	}
>> +out:
>> +	read_unlock(&policy_rwlock);
>> +
>> +	return rc;
>> +}
>> +
>>  static int get_classes_callback(void *k, void *d, void *args)  {
>>  	struct class_datum *datum = d;



--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@xxxxxxxxxxxxx with
the words "unsubscribe selinux" without quotes as the message.

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

  Powered by Linux