diff options
Diffstat (limited to 'security/selinux/ss/services.c')
| -rw-r--r-- | security/selinux/ss/services.c | 698 | 
1 files changed, 385 insertions, 313 deletions
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 223c1ff6ef2..4bca49414a4 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -13,7 +13,7 @@   *   *	Added conditional policy language extensions   * - * Updated: Hewlett-Packard <paul.moore@hp.com> + * Updated: Hewlett-Packard <paul@paul-moore.com>   *   *      Added support for NetLabel   *      Added support for the policy capability bitmap @@ -70,10 +70,9 @@  #include "ebitmap.h"  #include "audit.h" -extern void selnl_notify_policyload(u32 seqno); -  int selinux_policycap_netpeer;  int selinux_policycap_openperm; +int selinux_policycap_alwaysnetwork;  static DEFINE_RWLOCK(policy_rwlock); @@ -201,6 +200,21 @@ static u16 unmap_class(u16 tclass)  	return tclass;  } +/* + * Get kernel value for class from its policy value + */ +static u16 map_class(u16 pol_value) +{ +	u16 i; + +	for (i = 1; i < current_mapping_size; i++) { +		if (current_mapping[i].value == pol_value) +			return i; +	} + +	return SECCLASS_NULL; +} +  static void map_decision(u16 tclass, struct av_decision *avd,  			 int allow_unknown)  { @@ -464,7 +478,7 @@ static void security_dump_masked_av(struct context *scontext,  	if (!permissions)  		return; -	tclass_name = policydb.p_class_val_to_name[tclass - 1]; +	tclass_name = sym_name(&policydb, SYM_CLASSES, tclass - 1);  	tclass_dat = policydb.class_val_to_struct[tclass - 1];  	common_dat = tclass_dat->comdatum; @@ -530,12 +544,18 @@ static void type_attribute_bounds_av(struct context *scontext,  	struct context lo_scontext;  	struct context lo_tcontext;  	struct av_decision lo_avd; -	struct type_datum *source -		= policydb.type_val_to_struct[scontext->type - 1]; -	struct type_datum *target -		= policydb.type_val_to_struct[tcontext->type - 1]; +	struct type_datum *source; +	struct type_datum *target;  	u32 masked = 0; +	source = flex_array_get_ptr(policydb.type_val_to_struct_array, +				    scontext->type - 1); +	BUG_ON(!source); + +	target = flex_array_get_ptr(policydb.type_val_to_struct_array, +				    tcontext->type - 1); +	BUG_ON(!target); +  	if (source->bounds) {  		memset(&lo_avd, 0, sizeof(lo_avd)); @@ -701,16 +721,16 @@ static int security_validtrans_handle_fail(struct context *ocontext,  	char *o = NULL, *n = NULL, *t = NULL;  	u32 olen, nlen, tlen; -	if (context_struct_to_string(ocontext, &o, &olen) < 0) +	if (context_struct_to_string(ocontext, &o, &olen))  		goto out; -	if (context_struct_to_string(ncontext, &n, &nlen) < 0) +	if (context_struct_to_string(ncontext, &n, &nlen))  		goto out; -	if (context_struct_to_string(tcontext, &t, &tlen) < 0) +	if (context_struct_to_string(tcontext, &t, &tlen))  		goto out;  	audit_log(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR,  		  "security_validate_transition:  denied for"  		  " oldcontext=%s newcontext=%s taskcontext=%s tclass=%s", -		  o, n, t, policydb.p_class_val_to_name[tclass-1]); +		  o, n, t, sym_name(&policydb, SYM_CLASSES, tclass-1));  out:  	kfree(o);  	kfree(n); @@ -801,10 +821,11 @@ int security_bounded_transition(u32 old_sid, u32 new_sid)  	struct context *old_context, *new_context;  	struct type_datum *type;  	int index; -	int rc = -EINVAL; +	int rc;  	read_lock(&policy_rwlock); +	rc = -EINVAL;  	old_context = sidtab_search(&sidtab, old_sid);  	if (!old_context) {  		printk(KERN_ERR "SELinux: %s: unrecognized SID %u\n", @@ -812,6 +833,7 @@ int security_bounded_transition(u32 old_sid, u32 new_sid)  		goto out;  	} +	rc = -EINVAL;  	new_context = sidtab_search(&sidtab, new_sid);  	if (!new_context) {  		printk(KERN_ERR "SELinux: %s: unrecognized SID %u\n", @@ -819,28 +841,27 @@ int security_bounded_transition(u32 old_sid, u32 new_sid)  		goto out;  	} +	rc = 0;  	/* type/domain unchanged */ -	if (old_context->type == new_context->type) { -		rc = 0; +	if (old_context->type == new_context->type)  		goto out; -	}  	index = new_context->type;  	while (true) { -		type = policydb.type_val_to_struct[index - 1]; +		type = flex_array_get_ptr(policydb.type_val_to_struct_array, +					  index - 1);  		BUG_ON(!type);  		/* not bounded anymore */ -		if (!type->bounds) { -			rc = -EPERM; +		rc = -EPERM; +		if (!type->bounds)  			break; -		}  		/* @newsid is bounded by @oldsid */ -		if (type->bounds == old_context->type) { -			rc = 0; +		rc = 0; +		if (type->bounds == old_context->type)  			break; -		} +  		index = type->bounds;  	} @@ -998,16 +1019,18 @@ static int context_struct_to_string(struct context *context, char **scontext, u3  	if (context->len) {  		*scontext_len = context->len; -		*scontext = kstrdup(context->str, GFP_ATOMIC); -		if (!(*scontext)) -			return -ENOMEM; +		if (scontext) { +			*scontext = kstrdup(context->str, GFP_ATOMIC); +			if (!(*scontext)) +				return -ENOMEM; +		}  		return 0;  	}  	/* Compute the size of the context. */ -	*scontext_len += strlen(policydb.p_user_val_to_name[context->user - 1]) + 1; -	*scontext_len += strlen(policydb.p_role_val_to_name[context->role - 1]) + 1; -	*scontext_len += strlen(policydb.p_type_val_to_name[context->type - 1]) + 1; +	*scontext_len += strlen(sym_name(&policydb, SYM_USERS, context->user - 1)) + 1; +	*scontext_len += strlen(sym_name(&policydb, SYM_ROLES, context->role - 1)) + 1; +	*scontext_len += strlen(sym_name(&policydb, SYM_TYPES, context->type - 1)) + 1;  	*scontext_len += mls_compute_context_len(context);  	if (!scontext) @@ -1023,12 +1046,12 @@ static int context_struct_to_string(struct context *context, char **scontext, u3  	 * Copy the user name, role name and type name into the context.  	 */  	sprintf(scontextp, "%s:%s:%s", -		policydb.p_user_val_to_name[context->user - 1], -		policydb.p_role_val_to_name[context->role - 1], -		policydb.p_type_val_to_name[context->type - 1]); -	scontextp += strlen(policydb.p_user_val_to_name[context->user - 1]) + -		     1 + strlen(policydb.p_role_val_to_name[context->role - 1]) + -		     1 + strlen(policydb.p_type_val_to_name[context->type - 1]); +		sym_name(&policydb, SYM_USERS, context->user - 1), +		sym_name(&policydb, SYM_ROLES, context->role - 1), +		sym_name(&policydb, SYM_TYPES, context->type - 1)); +	scontextp += strlen(sym_name(&policydb, SYM_USERS, context->user - 1)) + +		     1 + strlen(sym_name(&policydb, SYM_ROLES, context->role - 1)) + +		     1 + strlen(sym_name(&policydb, SYM_TYPES, context->type - 1));  	mls_sid_to_context(context, &scontextp); @@ -1187,16 +1210,13 @@ static int string_to_context_struct(struct policydb *pol,  	if (rc)  		goto out; -	if ((p - scontext) < scontext_len) { -		rc = -EINVAL; +	rc = -EINVAL; +	if ((p - scontext) < scontext_len)  		goto out; -	}  	/* Check the validity of the new context. */ -	if (!policydb_context_isvalid(pol, ctx)) { -		rc = -EINVAL; +	if (!policydb_context_isvalid(pol, ctx))  		goto out; -	}  	rc = 0;  out:  	if (rc) @@ -1212,6 +1232,10 @@ static int security_context_to_sid_core(const char *scontext, u32 scontext_len,  	struct context context;  	int rc = 0; +	/* An empty security context is never valid. */ +	if (!scontext_len) +		return -EINVAL; +  	if (!ss_initialized) {  		int i; @@ -1235,27 +1259,26 @@ static int security_context_to_sid_core(const char *scontext, u32 scontext_len,  	if (force) {  		/* Save another copy for storing in uninterpreted form */ +		rc = -ENOMEM;  		str = kstrdup(scontext2, gfp_flags); -		if (!str) { -			kfree(scontext2); -			return -ENOMEM; -		} +		if (!str) +			goto out;  	}  	read_lock(&policy_rwlock); -	rc = string_to_context_struct(&policydb, &sidtab, -				      scontext2, scontext_len, -				      &context, def_sid); +	rc = string_to_context_struct(&policydb, &sidtab, scontext2, +				      scontext_len, &context, def_sid);  	if (rc == -EINVAL && force) {  		context.str = str;  		context.len = scontext_len;  		str = NULL;  	} else if (rc) -		goto out; +		goto out_unlock;  	rc = sidtab_context_to_sid(&sidtab, &context, sid);  	context_destroy(&context); -out: +out_unlock:  	read_unlock(&policy_rwlock); +out:  	kfree(scontext2);  	kfree(str);  	return rc; @@ -1266,16 +1289,18 @@ out:   * @scontext: security context   * @scontext_len: length in bytes   * @sid: security identifier, SID + * @gfp: context for the allocation   *   * Obtains a SID associated with the security context that   * has the string representation specified by @scontext.   * Returns -%EINVAL if the context is invalid, -%ENOMEM if insufficient   * memory is available, or 0 on success.   */ -int security_context_to_sid(const char *scontext, u32 scontext_len, u32 *sid) +int security_context_to_sid(const char *scontext, u32 scontext_len, u32 *sid, +			    gfp_t gfp)  {  	return security_context_to_sid_core(scontext, scontext_len, -					    sid, SECSID_NULL, GFP_KERNEL, 0); +					    sid, SECSID_NULL, gfp, 0);  }  /** @@ -1319,18 +1344,18 @@ static int compute_sid_handle_invalid_context(  	char *s = NULL, *t = NULL, *n = NULL;  	u32 slen, tlen, nlen; -	if (context_struct_to_string(scontext, &s, &slen) < 0) +	if (context_struct_to_string(scontext, &s, &slen))  		goto out; -	if (context_struct_to_string(tcontext, &t, &tlen) < 0) +	if (context_struct_to_string(tcontext, &t, &tlen))  		goto out; -	if (context_struct_to_string(newcontext, &n, &nlen) < 0) +	if (context_struct_to_string(newcontext, &n, &nlen))  		goto out;  	audit_log(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR,  		  "security_compute_sid:  invalid context %s"  		  " for scontext=%s"  		  " tcontext=%s"  		  " tclass=%s", -		  n, s, t, policydb.p_class_val_to_name[tclass-1]); +		  n, s, t, sym_name(&policydb, SYM_CLASSES, tclass-1));  out:  	kfree(s);  	kfree(t); @@ -1340,13 +1365,40 @@ out:  	return -EACCES;  } +static void filename_compute_type(struct policydb *p, struct context *newcontext, +				  u32 stype, u32 ttype, u16 tclass, +				  const char *objname) +{ +	struct filename_trans ft; +	struct filename_trans_datum *otype; + +	/* +	 * Most filename trans rules are going to live in specific directories +	 * like /dev or /var/run.  This bitmap will quickly skip rule searches +	 * if the ttype does not contain any rules. +	 */ +	if (!ebitmap_get_bit(&p->filename_trans_ttypes, ttype)) +		return; + +	ft.stype = stype; +	ft.ttype = ttype; +	ft.tclass = tclass; +	ft.name = objname; + +	otype = hashtab_search(p->filename_trans, &ft); +	if (otype) +		newcontext->type = otype->otype; +} +  static int security_compute_sid(u32 ssid,  				u32 tsid,  				u16 orig_tclass,  				u32 specified, +				const char *objname,  				u32 *out_sid,  				bool kern)  { +	struct class_datum *cladatum = NULL;  	struct context *scontext = NULL, *tcontext = NULL, newcontext;  	struct role_trans *roletr = NULL;  	struct avtab_key avkey; @@ -1354,6 +1406,7 @@ static int security_compute_sid(u32 ssid,  	struct avtab_node *node;  	u16 tclass;  	int rc = 0; +	bool sock;  	if (!ss_initialized) {  		switch (orig_tclass) { @@ -1371,10 +1424,13 @@ static int security_compute_sid(u32 ssid,  	read_lock(&policy_rwlock); -	if (kern) +	if (kern) {  		tclass = unmap_class(orig_tclass); -	else +		sock = security_is_socket_class(orig_tclass); +	} else {  		tclass = orig_tclass; +		sock = security_is_socket_class(map_class(tclass)); +	}  	scontext = sidtab_search(&sidtab, ssid);  	if (!scontext) { @@ -1391,12 +1447,20 @@ static int security_compute_sid(u32 ssid,  		goto out_unlock;  	} +	if (tclass && tclass <= policydb.p_classes.nprim) +		cladatum = policydb.class_val_to_struct[tclass - 1]; +  	/* Set the user identity. */  	switch (specified) {  	case AVTAB_TRANSITION:  	case AVTAB_CHANGE: -		/* Use the process user identity. */ -		newcontext.user = scontext->user; +		if (cladatum && cladatum->default_user == DEFAULT_TARGET) { +			newcontext.user = tcontext->user; +		} else { +			/* notice this gets both DEFAULT_SOURCE and unset */ +			/* Use the process user identity. */ +			newcontext.user = scontext->user; +		}  		break;  	case AVTAB_MEMBER:  		/* Use the related object owner. */ @@ -1404,16 +1468,31 @@ static int security_compute_sid(u32 ssid,  		break;  	} -	/* Set the role and type to default values. */ -	if (tclass == policydb.process_class) { -		/* Use the current role and type of process. */ +	/* Set the role to default values. */ +	if (cladatum && cladatum->default_role == DEFAULT_SOURCE) {  		newcontext.role = scontext->role; -		newcontext.type = scontext->type; +	} else if (cladatum && cladatum->default_role == DEFAULT_TARGET) { +		newcontext.role = tcontext->role;  	} else { -		/* Use the well-defined object role. */ -		newcontext.role = OBJECT_R_VAL; -		/* Use the type of the related object. */ +		if ((tclass == policydb.process_class) || (sock == true)) +			newcontext.role = scontext->role; +		else +			newcontext.role = OBJECT_R_VAL; +	} + +	/* Set the type to default values. */ +	if (cladatum && cladatum->default_type == DEFAULT_SOURCE) { +		newcontext.type = scontext->type; +	} else if (cladatum && cladatum->default_type == DEFAULT_TARGET) {  		newcontext.type = tcontext->type; +	} else { +		if ((tclass == policydb.process_class) || (sock == true)) { +			/* Use the type of process. */ +			newcontext.type = scontext->type; +		} else { +			/* Use the type of the related object. */ +			newcontext.type = tcontext->type; +		}  	}  	/* Look for a type transition/member/change rule. */ @@ -1439,25 +1518,29 @@ static int security_compute_sid(u32 ssid,  		newcontext.type = avdatum->data;  	} +	/* if we have a objname this is a file trans check so check those rules */ +	if (objname) +		filename_compute_type(&policydb, &newcontext, scontext->type, +				      tcontext->type, tclass, objname); +  	/* Check for class-specific changes. */ -	if  (tclass == policydb.process_class) { -		if (specified & AVTAB_TRANSITION) { -			/* Look for a role transition rule. */ -			for (roletr = policydb.role_tr; roletr; -			     roletr = roletr->next) { -				if (roletr->role == scontext->role && -				    roletr->type == tcontext->type) { -					/* Use the role transition rule. */ -					newcontext.role = roletr->new_role; -					break; -				} +	if (specified & AVTAB_TRANSITION) { +		/* Look for a role transition rule. */ +		for (roletr = policydb.role_tr; roletr; roletr = roletr->next) { +			if ((roletr->role == scontext->role) && +			    (roletr->type == tcontext->type) && +			    (roletr->tclass == tclass)) { +				/* Use the role transition rule. */ +				newcontext.role = roletr->new_role; +				break;  			}  		}  	}  	/* Set the MLS attributes.  	   This is done last because it may allocate memory. */ -	rc = mls_compute_sid(scontext, tcontext, tclass, specified, &newcontext); +	rc = mls_compute_sid(scontext, tcontext, tclass, specified, +			     &newcontext, sock);  	if (rc)  		goto out_unlock; @@ -1492,22 +1575,18 @@ out:   * if insufficient memory is available, or %0 if the new SID was   * computed successfully.   */ -int security_transition_sid(u32 ssid, -			    u32 tsid, -			    u16 tclass, -			    u32 *out_sid) +int security_transition_sid(u32 ssid, u32 tsid, u16 tclass, +			    const struct qstr *qstr, u32 *out_sid)  {  	return security_compute_sid(ssid, tsid, tclass, AVTAB_TRANSITION, -				    out_sid, true); +				    qstr ? qstr->name : NULL, out_sid, true);  } -int security_transition_sid_user(u32 ssid, -				 u32 tsid, -				 u16 tclass, -				 u32 *out_sid) +int security_transition_sid_user(u32 ssid, u32 tsid, u16 tclass, +				 const char *objname, u32 *out_sid)  {  	return security_compute_sid(ssid, tsid, tclass, AVTAB_TRANSITION, -				    out_sid, false); +				    objname, out_sid, false);  }  /** @@ -1528,8 +1607,8 @@ int security_member_sid(u32 ssid,  			u16 tclass,  			u32 *out_sid)  { -	return security_compute_sid(ssid, tsid, tclass, AVTAB_MEMBER, out_sid, -				    false); +	return security_compute_sid(ssid, tsid, tclass, AVTAB_MEMBER, NULL, +				    out_sid, false);  }  /** @@ -1550,8 +1629,8 @@ int security_change_sid(u32 ssid,  			u16 tclass,  			u32 *out_sid)  { -	return security_compute_sid(ssid, tsid, tclass, AVTAB_CHANGE, out_sid, -				    false); +	return security_compute_sid(ssid, tsid, tclass, AVTAB_CHANGE, NULL, +				    out_sid, false);  }  /* Clone the SID into the new SID table. */ @@ -1569,22 +1648,17 @@ static int clone_sid(u32 sid,  static inline int convert_context_handle_invalid_context(struct context *context)  { -	int rc = 0; +	char *s; +	u32 len; -	if (selinux_enforcing) { -		rc = -EINVAL; -	} else { -		char *s; -		u32 len; - -		if (!context_struct_to_string(context, &s, &len)) { -			printk(KERN_WARNING -		       "SELinux:  Context %s would be invalid if enforcing\n", -			       s); -			kfree(s); -		} +	if (selinux_enforcing) +		return -EINVAL; + +	if (!context_struct_to_string(context, &s, &len)) { +		printk(KERN_WARNING "SELinux:  Context %s would be invalid if enforcing\n", s); +		kfree(s);  	} -	return rc; +	return 0;  }  struct convert_context_args { @@ -1621,17 +1695,17 @@ static int convert_context(u32 key,  	if (c->str) {  		struct context ctx; + +		rc = -ENOMEM;  		s = kstrdup(c->str, GFP_KERNEL); -		if (!s) { -			rc = -ENOMEM; +		if (!s)  			goto out; -		} +  		rc = string_to_context_struct(args->newp, NULL, s,  					      c->len, &ctx, SECSID_NULL);  		kfree(s);  		if (!rc) { -			printk(KERN_INFO -		       "SELinux:  Context %s became valid (mapped).\n", +			printk(KERN_INFO "SELinux:  Context %s became valid (mapped).\n",  			       c->str);  			/* Replace string with mapped representation. */  			kfree(c->str); @@ -1643,8 +1717,7 @@ static int convert_context(u32 key,  			goto out;  		} else {  			/* Other error condition, e.g. ENOMEM. */ -			printk(KERN_ERR -		       "SELinux:   Unable to map context %s, rc = %d.\n", +			printk(KERN_ERR "SELinux:   Unable to map context %s, rc = %d.\n",  			       c->str, -rc);  			goto out;  		} @@ -1654,25 +1727,26 @@ static int convert_context(u32 key,  	if (rc)  		goto out; -	rc = -EINVAL; -  	/* Convert the user. */ +	rc = -EINVAL;  	usrdatum = hashtab_search(args->newp->p_users.table, -				  args->oldp->p_user_val_to_name[c->user - 1]); +				  sym_name(args->oldp, SYM_USERS, c->user - 1));  	if (!usrdatum)  		goto bad;  	c->user = usrdatum->value;  	/* Convert the role. */ +	rc = -EINVAL;  	role = hashtab_search(args->newp->p_roles.table, -			      args->oldp->p_role_val_to_name[c->role - 1]); +			      sym_name(args->oldp, SYM_ROLES, c->role - 1));  	if (!role)  		goto bad;  	c->role = role->value;  	/* Convert the type. */ +	rc = -EINVAL;  	typdatum = hashtab_search(args->newp->p_types.table, -				  args->oldp->p_type_val_to_name[c->type - 1]); +				  sym_name(args->oldp, SYM_TYPES, c->type - 1));  	if (!typdatum)  		goto bad;  	c->type = typdatum->value; @@ -1700,6 +1774,7 @@ static int convert_context(u32 key,  		oc = args->newp->ocontexts[OCON_ISID];  		while (oc && oc->sid[0] != SECINITSID_UNLABELED)  			oc = oc->next; +		rc = -EINVAL;  		if (!oc) {  			printk(KERN_ERR "SELinux:  unable to look up"  				" the initial SIDs list\n"); @@ -1719,19 +1794,20 @@ static int convert_context(u32 key,  	}  	context_destroy(&oldc); +  	rc = 0;  out:  	return rc;  bad:  	/* Map old representation to string and save it. */ -	if (context_struct_to_string(&oldc, &s, &len)) -		return -ENOMEM; +	rc = context_struct_to_string(&oldc, &s, &len); +	if (rc) +		return rc;  	context_destroy(&oldc);  	context_destroy(c);  	c->str = s;  	c->len = len; -	printk(KERN_INFO -	       "SELinux:  Context %s became invalid (unmapped).\n", +	printk(KERN_INFO "SELinux:  Context %s became invalid (unmapped).\n",  	       c->str);  	rc = 0;  	goto out; @@ -1743,9 +1819,10 @@ static void security_load_policycaps(void)  						  POLICYDB_CAPABILITY_NETPEER);  	selinux_policycap_openperm = ebitmap_get_bit(&policydb.policycaps,  						  POLICYDB_CAPABILITY_OPENPERM); +	selinux_policycap_alwaysnetwork = ebitmap_get_bit(&policydb.policycaps, +						  POLICYDB_CAPABILITY_ALWAYSNETWORK);  } -extern void selinux_complete_init(void);  static int security_preserve_bools(struct policydb *p);  /** @@ -1760,7 +1837,7 @@ static int security_preserve_bools(struct policydb *p);   */  int security_load_policy(void *data, size_t len)  { -	struct policydb oldpolicydb, newpolicydb; +	struct policydb *oldpolicydb, *newpolicydb;  	struct sidtab oldsidtab, newsidtab;  	struct selinux_mapping *oldmap, *map = NULL;  	struct convert_context_args args; @@ -1769,12 +1846,19 @@ int security_load_policy(void *data, size_t len)  	int rc = 0;  	struct policy_file file = { data, len }, *fp = &file; +	oldpolicydb = kzalloc(2 * sizeof(*oldpolicydb), GFP_KERNEL); +	if (!oldpolicydb) { +		rc = -ENOMEM; +		goto out; +	} +	newpolicydb = oldpolicydb + 1; +  	if (!ss_initialized) {  		avtab_cache_init();  		rc = policydb_read(&policydb, fp);  		if (rc) {  			avtab_cache_destroy(); -			return rc; +			goto out;  		}  		policydb.len = len; @@ -1784,14 +1868,14 @@ int security_load_policy(void *data, size_t len)  		if (rc) {  			policydb_destroy(&policydb);  			avtab_cache_destroy(); -			return rc; +			goto out;  		}  		rc = policydb_load_isids(&policydb, &sidtab);  		if (rc) {  			policydb_destroy(&policydb);  			avtab_cache_destroy(); -			return rc; +			goto out;  		}  		security_load_policycaps(); @@ -1803,36 +1887,36 @@ int security_load_policy(void *data, size_t len)  		selinux_status_update_policyload(seqno);  		selinux_netlbl_cache_invalidate();  		selinux_xfrm_notify_policyload(); -		return 0; +		goto out;  	}  #if 0  	sidtab_hash_eval(&sidtab, "sids");  #endif -	rc = policydb_read(&newpolicydb, fp); +	rc = policydb_read(newpolicydb, fp);  	if (rc) -		return rc; +		goto out; -	newpolicydb.len = len; +	newpolicydb->len = len;  	/* If switching between different policy types, log MLS status */ -	if (policydb.mls_enabled && !newpolicydb.mls_enabled) +	if (policydb.mls_enabled && !newpolicydb->mls_enabled)  		printk(KERN_INFO "SELinux: Disabling MLS support...\n"); -	else if (!policydb.mls_enabled && newpolicydb.mls_enabled) +	else if (!policydb.mls_enabled && newpolicydb->mls_enabled)  		printk(KERN_INFO "SELinux: Enabling MLS support...\n"); -	rc = policydb_load_isids(&newpolicydb, &newsidtab); +	rc = policydb_load_isids(newpolicydb, &newsidtab);  	if (rc) {  		printk(KERN_ERR "SELinux:  unable to load the initial SIDs\n"); -		policydb_destroy(&newpolicydb); -		return rc; +		policydb_destroy(newpolicydb); +		goto out;  	} -	rc = selinux_set_mapping(&newpolicydb, secclass_map, &map, &map_size); +	rc = selinux_set_mapping(newpolicydb, secclass_map, &map, &map_size);  	if (rc)  		goto err; -	rc = security_preserve_bools(&newpolicydb); +	rc = security_preserve_bools(newpolicydb);  	if (rc) {  		printk(KERN_ERR "SELinux:  unable to preserve booleans\n");  		goto err; @@ -1850,7 +1934,7 @@ int security_load_policy(void *data, size_t len)  	 * in the new SID table.  	 */  	args.oldp = &policydb; -	args.newp = &newpolicydb; +	args.newp = newpolicydb;  	rc = sidtab_map(&newsidtab, convert_context, &args);  	if (rc) {  		printk(KERN_ERR "SELinux:  unable to convert the internal" @@ -1860,12 +1944,12 @@ int security_load_policy(void *data, size_t len)  	}  	/* Save the old policydb and SID table to free later. */ -	memcpy(&oldpolicydb, &policydb, sizeof policydb); +	memcpy(oldpolicydb, &policydb, sizeof(policydb));  	sidtab_set(&oldsidtab, &sidtab);  	/* Install the new policydb and SID table. */  	write_lock_irq(&policy_rwlock); -	memcpy(&policydb, &newpolicydb, sizeof policydb); +	memcpy(&policydb, newpolicydb, sizeof(policydb));  	sidtab_set(&sidtab, &newsidtab);  	security_load_policycaps();  	oldmap = current_mapping; @@ -1875,7 +1959,7 @@ int security_load_policy(void *data, size_t len)  	write_unlock_irq(&policy_rwlock);  	/* Free the old policydb and SID table. */ -	policydb_destroy(&oldpolicydb); +	policydb_destroy(oldpolicydb);  	sidtab_destroy(&oldsidtab);  	kfree(oldmap); @@ -1885,14 +1969,17 @@ int security_load_policy(void *data, size_t len)  	selinux_netlbl_cache_invalidate();  	selinux_xfrm_notify_policyload(); -	return 0; +	rc = 0; +	goto out;  err:  	kfree(map);  	sidtab_destroy(&newsidtab); -	policydb_destroy(&newpolicydb); -	return rc; +	policydb_destroy(newpolicydb); +out: +	kfree(oldpolicydb); +	return rc;  }  size_t security_policydb_len(void) @@ -2012,7 +2099,7 @@ int security_node_sid(u16 domain,  		      u32 addrlen,  		      u32 *out_sid)  { -	int rc = 0; +	int rc;  	struct ocontext *c;  	read_lock(&policy_rwlock); @@ -2021,10 +2108,9 @@ int security_node_sid(u16 domain,  	case AF_INET: {  		u32 addr; -		if (addrlen != sizeof(u32)) { -			rc = -EINVAL; +		rc = -EINVAL; +		if (addrlen != sizeof(u32))  			goto out; -		}  		addr = *((u32 *)addrp); @@ -2038,10 +2124,9 @@ int security_node_sid(u16 domain,  	}  	case AF_INET6: -		if (addrlen != sizeof(u64) * 2) { -			rc = -EINVAL; +		rc = -EINVAL; +		if (addrlen != sizeof(u64) * 2)  			goto out; -		}  		c = policydb.ocontexts[OCON_NODE6];  		while (c) {  			if (match_ipv6_addrmask(addrp, c->u.node6.addr, @@ -2052,6 +2137,7 @@ int security_node_sid(u16 domain,  		break;  	default: +		rc = 0;  		*out_sid = SECINITSID_NODE;  		goto out;  	} @@ -2069,6 +2155,7 @@ int security_node_sid(u16 domain,  		*out_sid = SECINITSID_NODE;  	} +	rc = 0;  out:  	read_unlock(&policy_rwlock);  	return rc; @@ -2113,24 +2200,22 @@ int security_get_user_sids(u32 fromsid,  	context_init(&usercon); +	rc = -EINVAL;  	fromcon = sidtab_search(&sidtab, fromsid); -	if (!fromcon) { -		rc = -EINVAL; +	if (!fromcon)  		goto out_unlock; -	} +	rc = -EINVAL;  	user = hashtab_search(policydb.p_users.table, username); -	if (!user) { -		rc = -EINVAL; +	if (!user)  		goto out_unlock; -	} +  	usercon.user = user->value; +	rc = -ENOMEM;  	mysids = kcalloc(maxnel, sizeof(*mysids), GFP_ATOMIC); -	if (!mysids) { -		rc = -ENOMEM; +	if (!mysids)  		goto out_unlock; -	}  	ebitmap_for_each_positive_bit(&user->roles, rnode, i) {  		role = policydb.role_val_to_struct[i]; @@ -2147,12 +2232,11 @@ int security_get_user_sids(u32 fromsid,  			if (mynel < maxnel) {  				mysids[mynel++] = sid;  			} else { +				rc = -ENOMEM;  				maxnel += SIDS_NEL;  				mysids2 = kcalloc(maxnel, sizeof(*mysids2), GFP_ATOMIC); -				if (!mysids2) { -					rc = -ENOMEM; +				if (!mysids2)  					goto out_unlock; -				}  				memcpy(mysids2, mysids, mynel * sizeof(*mysids2));  				kfree(mysids);  				mysids = mysids2; @@ -2160,7 +2244,7 @@ int security_get_user_sids(u32 fromsid,  			}  		}  	} - +	rc = 0;  out_unlock:  	read_unlock(&policy_rwlock);  	if (rc || !mynel) { @@ -2168,17 +2252,18 @@ out_unlock:  		goto out;  	} +	rc = -ENOMEM;  	mysids2 = kcalloc(mynel, sizeof(*mysids2), GFP_KERNEL);  	if (!mysids2) { -		rc = -ENOMEM;  		kfree(mysids);  		goto out;  	}  	for (i = 0, j = 0; i < mynel; i++) { +		struct av_decision dummy_avd;  		rc = avc_has_perm_noaudit(fromsid, mysids[i],  					  SECCLASS_PROCESS, /* kernel value */  					  PROCESS__TRANSITION, AVC_STRICT, -					  NULL); +					  &dummy_avd);  		if (!rc)  			mysids2[j++] = mysids[i];  		cond_resched(); @@ -2211,7 +2296,7 @@ int security_genfs_sid(const char *fstype,  	u16 sclass;  	struct genfs *genfs;  	struct ocontext *c; -	int rc = 0, cmp = 0; +	int rc, cmp = 0;  	while (path[0] == '/' && path[1] == '/')  		path++; @@ -2219,6 +2304,7 @@ int security_genfs_sid(const char *fstype,  	read_lock(&policy_rwlock);  	sclass = unmap_class(orig_sclass); +	*sid = SECINITSID_UNLABELED;  	for (genfs = policydb.genfs; genfs; genfs = genfs->next) {  		cmp = strcmp(fstype, genfs->fstype); @@ -2226,11 +2312,9 @@ int security_genfs_sid(const char *fstype,  			break;  	} -	if (!genfs || cmp) { -		*sid = SECINITSID_UNLABELED; -		rc = -ENOENT; +	rc = -ENOENT; +	if (!genfs || cmp)  		goto out; -	}  	for (c = genfs->head; c; c = c->next) {  		len = strlen(c->u.name); @@ -2239,21 +2323,18 @@ int security_genfs_sid(const char *fstype,  			break;  	} -	if (!c) { -		*sid = SECINITSID_UNLABELED; -		rc = -ENOENT; +	rc = -ENOENT; +	if (!c)  		goto out; -	}  	if (!c->sid[0]) { -		rc = sidtab_context_to_sid(&sidtab, -					   &c->context[0], -					   &c->sid[0]); +		rc = sidtab_context_to_sid(&sidtab, &c->context[0], &c->sid[0]);  		if (rc)  			goto out;  	}  	*sid = c->sid[0]; +	rc = 0;  out:  	read_unlock(&policy_rwlock);  	return rc; @@ -2261,17 +2342,14 @@ out:  /**   * security_fs_use - Determine how to handle labeling for a filesystem. - * @fstype: filesystem type - * @behavior: labeling behavior - * @sid: SID for filesystem (superblock) + * @sb: superblock in question   */ -int security_fs_use( -	const char *fstype, -	unsigned int *behavior, -	u32 *sid) +int security_fs_use(struct super_block *sb)  {  	int rc = 0;  	struct ocontext *c; +	struct superblock_security_struct *sbsec = sb->s_security; +	const char *fstype = sb->s_type->name;  	read_lock(&policy_rwlock); @@ -2283,22 +2361,21 @@ int security_fs_use(  	}  	if (c) { -		*behavior = c->v.behavior; +		sbsec->behavior = c->v.behavior;  		if (!c->sid[0]) { -			rc = sidtab_context_to_sid(&sidtab, -						   &c->context[0], +			rc = sidtab_context_to_sid(&sidtab, &c->context[0],  						   &c->sid[0]);  			if (rc)  				goto out;  		} -		*sid = c->sid[0]; +		sbsec->sid = c->sid[0];  	} else { -		rc = security_genfs_sid(fstype, "/", SECCLASS_DIR, sid); +		rc = security_genfs_sid(fstype, "/", SECCLASS_DIR, &sbsec->sid);  		if (rc) { -			*behavior = SECURITY_FS_USE_NONE; +			sbsec->behavior = SECURITY_FS_USE_NONE;  			rc = 0;  		} else { -			*behavior = SECURITY_FS_USE_GENFS; +			sbsec->behavior = SECURITY_FS_USE_GENFS;  		}  	} @@ -2309,34 +2386,39 @@ out:  int security_get_bools(int *len, char ***names, int **values)  { -	int i, rc = -ENOMEM; +	int i, rc;  	read_lock(&policy_rwlock);  	*names = NULL;  	*values = NULL; +	rc = 0;  	*len = policydb.p_bools.nprim; -	if (!*len) { -		rc = 0; +	if (!*len)  		goto out; -	} -       *names = kcalloc(*len, sizeof(char *), GFP_ATOMIC); +	rc = -ENOMEM; +	*names = kcalloc(*len, sizeof(char *), GFP_ATOMIC);  	if (!*names)  		goto err; -       *values = kcalloc(*len, sizeof(int), GFP_ATOMIC); +	rc = -ENOMEM; +	*values = kcalloc(*len, sizeof(int), GFP_ATOMIC);  	if (!*values)  		goto err;  	for (i = 0; i < *len; i++) {  		size_t name_len; +  		(*values)[i] = policydb.bool_val_to_struct[i]->state; -		name_len = strlen(policydb.p_bool_val_to_name[i]) + 1; -	       (*names)[i] = kmalloc(sizeof(char) * name_len, GFP_ATOMIC); +		name_len = strlen(sym_name(&policydb, SYM_BOOLS, i)) + 1; + +		rc = -ENOMEM; +		(*names)[i] = kmalloc(sizeof(char) * name_len, GFP_ATOMIC);  		if (!(*names)[i])  			goto err; -		strncpy((*names)[i], policydb.p_bool_val_to_name[i], name_len); + +		strncpy((*names)[i], sym_name(&policydb, SYM_BOOLS, i), name_len);  		(*names)[i][name_len - 1] = 0;  	}  	rc = 0; @@ -2355,27 +2437,26 @@ err:  int security_set_bools(int len, int *values)  { -	int i, rc = 0; +	int i, rc;  	int lenp, seqno = 0;  	struct cond_node *cur;  	write_lock_irq(&policy_rwlock); +	rc = -EFAULT;  	lenp = policydb.p_bools.nprim; -	if (len != lenp) { -		rc = -EFAULT; +	if (len != lenp)  		goto out; -	}  	for (i = 0; i < len; i++) {  		if (!!values[i] != policydb.bool_val_to_struct[i]->state) {  			audit_log(current->audit_context, GFP_ATOMIC,  				AUDIT_MAC_CONFIG_CHANGE,  				"bool=%s val=%d old_val=%d auid=%u ses=%u", -				policydb.p_bool_val_to_name[i], +				sym_name(&policydb, SYM_BOOLS, i),  				!!values[i],  				policydb.bool_val_to_struct[i]->state, -				audit_get_loginuid(current), +				from_kuid(&init_user_ns, audit_get_loginuid(current)),  				audit_get_sessionid(current));  		}  		if (values[i]) @@ -2391,7 +2472,7 @@ int security_set_bools(int len, int *values)  	}  	seqno = ++latest_granting; - +	rc = 0;  out:  	write_unlock_irq(&policy_rwlock);  	if (!rc) { @@ -2405,16 +2486,15 @@ out:  int security_get_bool_value(int bool)  { -	int rc = 0; +	int rc;  	int len;  	read_lock(&policy_rwlock); +	rc = -EFAULT;  	len = policydb.p_bools.nprim; -	if (bool >= len) { -		rc = -EFAULT; +	if (bool >= len)  		goto out; -	}  	rc = policydb.bool_val_to_struct[bool]->state;  out: @@ -2464,8 +2544,9 @@ int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid)  	struct context newcon;  	char *s;  	u32 len; -	int rc = 0; +	int rc; +	rc = 0;  	if (!ss_initialized || !policydb.mls_enabled) {  		*new_sid = sid;  		goto out; @@ -2474,19 +2555,20 @@ int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid)  	context_init(&newcon);  	read_lock(&policy_rwlock); + +	rc = -EINVAL;  	context1 = sidtab_search(&sidtab, sid);  	if (!context1) {  		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",  			__func__, sid); -		rc = -EINVAL;  		goto out_unlock;  	} +	rc = -EINVAL;  	context2 = sidtab_search(&sidtab, mls_sid);  	if (!context2) {  		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",  			__func__, mls_sid); -		rc = -EINVAL;  		goto out_unlock;  	} @@ -2500,20 +2582,17 @@ int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid)  	/* Check the validity of the new context. */  	if (!policydb_context_isvalid(&policydb, &newcon)) {  		rc = convert_context_handle_invalid_context(&newcon); -		if (rc) -			goto bad; +		if (rc) { +			if (!context_struct_to_string(&newcon, &s, &len)) { +				audit_log(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR, +					  "security_sid_mls_copy: invalid context %s", s); +				kfree(s); +			} +			goto out_unlock; +		}  	}  	rc = sidtab_context_to_sid(&sidtab, &newcon, new_sid); -	goto out_unlock; - -bad: -	if (!context_struct_to_string(&newcon, &s, &len)) { -		audit_log(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR, -			  "security_sid_mls_copy: invalid context %s", s); -		kfree(s); -	} -  out_unlock:  	read_unlock(&policy_rwlock);  	context_destroy(&newcon); @@ -2549,6 +2628,8 @@ int security_net_peersid_resolve(u32 nlbl_sid, u32 nlbl_type,  	struct context *nlbl_ctx;  	struct context *xfrm_ctx; +	*peer_sid = SECSID_NULL; +  	/* handle the common (which also happens to be the set of easy) cases  	 * right away, these two if statements catch everything involving a  	 * single or absent peer SID/label */ @@ -2567,40 +2648,37 @@ int security_net_peersid_resolve(u32 nlbl_sid, u32 nlbl_type,  	/* we don't need to check ss_initialized here since the only way both  	 * nlbl_sid and xfrm_sid are not equal to SECSID_NULL would be if the  	 * security server was initialized and ss_initialized was true */ -	if (!policydb.mls_enabled) { -		*peer_sid = SECSID_NULL; +	if (!policydb.mls_enabled)  		return 0; -	}  	read_lock(&policy_rwlock); +	rc = -EINVAL;  	nlbl_ctx = sidtab_search(&sidtab, nlbl_sid);  	if (!nlbl_ctx) {  		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",  		       __func__, nlbl_sid); -		rc = -EINVAL; -		goto out_slowpath; +		goto out;  	} +	rc = -EINVAL;  	xfrm_ctx = sidtab_search(&sidtab, xfrm_sid);  	if (!xfrm_ctx) {  		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",  		       __func__, xfrm_sid); -		rc = -EINVAL; -		goto out_slowpath; +		goto out;  	}  	rc = (mls_context_cmp(nlbl_ctx, xfrm_ctx) ? 0 : -EACCES); +	if (rc) +		goto out; -out_slowpath: +	/* at present NetLabel SIDs/labels really only carry MLS +	 * information so if the MLS portion of the NetLabel SID +	 * matches the MLS portion of the labeled XFRM SID/label +	 * then pass along the XFRM SID as it is the most +	 * expressive */ +	*peer_sid = xfrm_sid; +out:  	read_unlock(&policy_rwlock); -	if (rc == 0) -		/* at present NetLabel SIDs/labels really only carry MLS -		 * information so if the MLS portion of the NetLabel SID -		 * matches the MLS portion of the labeled XFRM SID/label -		 * then pass along the XFRM SID as it is the most -		 * expressive */ -		*peer_sid = xfrm_sid; -	else -		*peer_sid = SECSID_NULL;  	return rc;  } @@ -2619,10 +2697,11 @@ static int get_classes_callback(void *k, void *d, void *args)  int security_get_classes(char ***classes, int *nclasses)  { -	int rc = -ENOMEM; +	int rc;  	read_lock(&policy_rwlock); +	rc = -ENOMEM;  	*nclasses = policydb.p_classes.nprim;  	*classes = kcalloc(*nclasses, sizeof(**classes), GFP_ATOMIC);  	if (!*classes) @@ -2630,7 +2709,7 @@ int security_get_classes(char ***classes, int *nclasses)  	rc = hashtab_map(policydb.p_classes.table, get_classes_callback,  			*classes); -	if (rc < 0) { +	if (rc) {  		int i;  		for (i = 0; i < *nclasses; i++)  			kfree((*classes)[i]); @@ -2657,19 +2736,20 @@ static int get_permissions_callback(void *k, void *d, void *args)  int security_get_permissions(char *class, char ***perms, int *nperms)  { -	int rc = -ENOMEM, i; +	int rc, i;  	struct class_datum *match;  	read_lock(&policy_rwlock); +	rc = -EINVAL;  	match = hashtab_search(policydb.p_classes.table, class);  	if (!match) {  		printk(KERN_ERR "SELinux: %s:  unrecognized class %s\n",  			__func__, class); -		rc = -EINVAL;  		goto out;  	} +	rc = -ENOMEM;  	*nperms = match->permissions.nprim;  	*perms = kcalloc(*nperms, sizeof(**perms), GFP_ATOMIC);  	if (!*perms) @@ -2678,13 +2758,13 @@ int security_get_permissions(char *class, char ***perms, int *nperms)  	if (match->comdatum) {  		rc = hashtab_map(match->comdatum->permissions.table,  				get_permissions_callback, *perms); -		if (rc < 0) +		if (rc)  			goto err;  	}  	rc = hashtab_map(match->permissions.table, get_permissions_callback,  			*perms); -	if (rc < 0) +	if (rc)  		goto err;  out: @@ -2774,7 +2854,7 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule)  	case AUDIT_SUBJ_CLR:  	case AUDIT_OBJ_LEV_LOW:  	case AUDIT_OBJ_LEV_HIGH: -		/* we do not allow a range, indicated by the presense of '-' */ +		/* we do not allow a range, indicated by the presence of '-' */  		if (strchr(rulestr, '-'))  			return -EINVAL;  		break; @@ -2796,36 +2876,39 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule)  	switch (field) {  	case AUDIT_SUBJ_USER:  	case AUDIT_OBJ_USER: +		rc = -EINVAL;  		userdatum = hashtab_search(policydb.p_users.table, rulestr);  		if (!userdatum) -			rc = -EINVAL; -		else -			tmprule->au_ctxt.user = userdatum->value; +			goto out; +		tmprule->au_ctxt.user = userdatum->value;  		break;  	case AUDIT_SUBJ_ROLE:  	case AUDIT_OBJ_ROLE: +		rc = -EINVAL;  		roledatum = hashtab_search(policydb.p_roles.table, rulestr);  		if (!roledatum) -			rc = -EINVAL; -		else -			tmprule->au_ctxt.role = roledatum->value; +			goto out; +		tmprule->au_ctxt.role = roledatum->value;  		break;  	case AUDIT_SUBJ_TYPE:  	case AUDIT_OBJ_TYPE: +		rc = -EINVAL;  		typedatum = hashtab_search(policydb.p_types.table, rulestr);  		if (!typedatum) -			rc = -EINVAL; -		else -			tmprule->au_ctxt.type = typedatum->value; +			goto out; +		tmprule->au_ctxt.type = typedatum->value;  		break;  	case AUDIT_SUBJ_SEN:  	case AUDIT_SUBJ_CLR:  	case AUDIT_OBJ_LEV_LOW:  	case AUDIT_OBJ_LEV_HIGH:  		rc = mls_from_string(rulestr, &tmprule->au_ctxt, GFP_ATOMIC); +		if (rc) +			goto out;  		break;  	} - +	rc = 0; +out:  	read_unlock(&policy_rwlock);  	if (rc) { @@ -2871,25 +2954,21 @@ int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule,  	struct selinux_audit_rule *rule = vrule;  	int match = 0; -	if (!rule) { -		audit_log(actx, GFP_ATOMIC, AUDIT_SELINUX_ERR, -			  "selinux_audit_rule_match: missing rule\n"); +	if (unlikely(!rule)) { +		WARN_ONCE(1, "selinux_audit_rule_match: missing rule\n");  		return -ENOENT;  	}  	read_lock(&policy_rwlock);  	if (rule->au_seqno < latest_granting) { -		audit_log(actx, GFP_ATOMIC, AUDIT_SELINUX_ERR, -			  "selinux_audit_rule_match: stale rule\n");  		match = -ESTALE;  		goto out;  	}  	ctxt = sidtab_search(&sidtab, sid); -	if (!ctxt) { -		audit_log(actx, GFP_ATOMIC, AUDIT_SELINUX_ERR, -			  "selinux_audit_rule_match: unrecognized SID %d\n", +	if (unlikely(!ctxt)) { +		WARN_ONCE(1, "selinux_audit_rule_match: unrecognized SID %d\n",  			  sid);  		match = -ENOENT;  		goto out; @@ -2977,8 +3056,7 @@ out:  static int (*aurule_callback)(void) = audit_update_lsm_rules; -static int aurule_avc_callback(u32 event, u32 ssid, u32 tsid, -			       u16 class, u32 perms, u32 *retained) +static int aurule_avc_callback(u32 event)  {  	int err = 0; @@ -2991,8 +3069,7 @@ static int __init aurule_init(void)  {  	int err; -	err = avc_add_callback(aurule_avc_callback, AVC_CALLBACK_RESET, -			       SECSID_NULL, SECSID_NULL, SECCLASS_NULL, 0); +	err = avc_add_callback(aurule_avc_callback, AVC_CALLBACK_RESET);  	if (err)  		panic("avc_add_callback() failed, error %d\n", err); @@ -3040,7 +3117,7 @@ static void security_netlbl_cache_add(struct netlbl_lsm_secattr *secattr,   * Description:   * Convert the given NetLabel security attributes in @secattr into a   * SELinux SID.  If the @secattr field does not contain a full SELinux - * SID/context then use SECINITSID_NETMSG as the foundation.  If possibile the + * SID/context then use SECINITSID_NETMSG as the foundation.  If possible the   * 'cache' field of @secattr is set and the CACHE flag is set; this is to   * allow the @secattr to be used by NetLabel to cache the secattr to SID   * conversion for future lookups.  Returns zero on success, negative values on @@ -3050,7 +3127,7 @@ static void security_netlbl_cache_add(struct netlbl_lsm_secattr *secattr,  int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,  				   u32 *sid)  { -	int rc = -EIDRM; +	int rc;  	struct context *ctx;  	struct context ctx_new; @@ -3061,16 +3138,15 @@ int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,  	read_lock(&policy_rwlock); -	if (secattr->flags & NETLBL_SECATTR_CACHE) { +	if (secattr->flags & NETLBL_SECATTR_CACHE)  		*sid = *(u32 *)secattr->cache->data; -		rc = 0; -	} else if (secattr->flags & NETLBL_SECATTR_SECID) { +	else if (secattr->flags & NETLBL_SECATTR_SECID)  		*sid = secattr->attr.secid; -		rc = 0; -	} else if (secattr->flags & NETLBL_SECATTR_MLS_LVL) { +	else if (secattr->flags & NETLBL_SECATTR_MLS_LVL) { +		rc = -EIDRM;  		ctx = sidtab_search(&sidtab, SECINITSID_NETMSG);  		if (ctx == NULL) -			goto netlbl_secattr_to_sid_return; +			goto out;  		context_init(&ctx_new);  		ctx_new.user = ctx->user; @@ -3078,34 +3154,35 @@ int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,  		ctx_new.type = ctx->type;  		mls_import_netlbl_lvl(&ctx_new, secattr);  		if (secattr->flags & NETLBL_SECATTR_MLS_CAT) { -			if (ebitmap_netlbl_import(&ctx_new.range.level[0].cat, -						  secattr->attr.mls.cat) != 0) -				goto netlbl_secattr_to_sid_return; +			rc = ebitmap_netlbl_import(&ctx_new.range.level[0].cat, +						   secattr->attr.mls.cat); +			if (rc) +				goto out;  			memcpy(&ctx_new.range.level[1].cat,  			       &ctx_new.range.level[0].cat,  			       sizeof(ctx_new.range.level[0].cat));  		} -		if (mls_context_isvalid(&policydb, &ctx_new) != 1) -			goto netlbl_secattr_to_sid_return_cleanup; +		rc = -EIDRM; +		if (!mls_context_isvalid(&policydb, &ctx_new)) +			goto out_free;  		rc = sidtab_context_to_sid(&sidtab, &ctx_new, sid); -		if (rc != 0) -			goto netlbl_secattr_to_sid_return_cleanup; +		if (rc) +			goto out_free;  		security_netlbl_cache_add(secattr, *sid);  		ebitmap_destroy(&ctx_new.range.level[0].cat); -	} else { +	} else  		*sid = SECSID_NULL; -		rc = 0; -	} -netlbl_secattr_to_sid_return:  	read_unlock(&policy_rwlock); -	return rc; -netlbl_secattr_to_sid_return_cleanup: +	return 0; +out_free:  	ebitmap_destroy(&ctx_new.range.level[0].cat); -	goto netlbl_secattr_to_sid_return; +out: +	read_unlock(&policy_rwlock); +	return rc;  }  /** @@ -3127,28 +3204,23 @@ int security_netlbl_sid_to_secattr(u32 sid, struct netlbl_lsm_secattr *secattr)  		return 0;  	read_lock(&policy_rwlock); + +	rc = -ENOENT;  	ctx = sidtab_search(&sidtab, sid); -	if (ctx == NULL) { -		rc = -ENOENT; -		goto netlbl_sid_to_secattr_failure; -	} -	secattr->domain = kstrdup(policydb.p_type_val_to_name[ctx->type - 1], +	if (ctx == NULL) +		goto out; + +	rc = -ENOMEM; +	secattr->domain = kstrdup(sym_name(&policydb, SYM_TYPES, ctx->type - 1),  				  GFP_ATOMIC); -	if (secattr->domain == NULL) { -		rc = -ENOMEM; -		goto netlbl_sid_to_secattr_failure; -	} +	if (secattr->domain == NULL) +		goto out; +  	secattr->attr.secid = sid;  	secattr->flags |= NETLBL_SECATTR_DOMAIN_CPY | NETLBL_SECATTR_SECID;  	mls_export_netlbl_lvl(ctx, secattr);  	rc = mls_export_netlbl_cat(ctx, secattr); -	if (rc != 0) -		goto netlbl_sid_to_secattr_failure; -	read_unlock(&policy_rwlock); - -	return 0; - -netlbl_sid_to_secattr_failure: +out:  	read_unlock(&policy_rwlock);  	return rc;  } @@ -3160,7 +3232,7 @@ netlbl_sid_to_secattr_failure:   * @len: length of data in bytes   *   */ -int security_read_policy(void **data, ssize_t *len) +int security_read_policy(void **data, size_t *len)  {  	int rc;  	struct policy_file fp;  | 
