فهرست منبع

Merge branch 'master' of git://git.infradead.org/users/eparis/selinux into next

James Morris 14 سال پیش
والد
کامیت
aeda4ac3ef

+ 1 - 1
include/linux/flex_array.h

@@ -71,7 +71,7 @@ void *flex_array_get(struct flex_array *fa, unsigned int element_nr);
 int flex_array_shrink(struct flex_array *fa);
 
 #define flex_array_put_ptr(fa, nr, src, gfp) \
-	flex_array_put(fa, nr, &(void *)(src), gfp)
+	flex_array_put(fa, nr, (void *)&(src), gfp)
 
 void *flex_array_get_ptr(struct flex_array *fa, unsigned int element_nr);
 

+ 4 - 1
security/selinux/hooks.c

@@ -2525,7 +2525,10 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
 	sid = tsec->sid;
 	newsid = tsec->create_sid;
 
-	if (!newsid || !(sbsec->flags & SE_SBLABELSUPP)) {
+	if ((sbsec->flags & SE_SBINITIALIZED) &&
+	    (sbsec->behavior == SECURITY_FS_USE_MNTPOINT))
+		newsid = sbsec->mntpoint_sid;
+	else if (!newsid || !(sbsec->flags & SE_SBLABELSUPP)) {
 		rc = security_transition_sid(sid, dsec->sid,
 					     inode_mode_to_security_class(inode->i_mode),
 					     &newsid);

+ 2 - 0
security/selinux/nlmsgtab.c

@@ -65,6 +65,8 @@ static struct nlmsg_perm nlmsg_route_perms[] =
 	{ RTM_NEWADDRLABEL,	NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
 	{ RTM_DELADDRLABEL,	NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
 	{ RTM_GETADDRLABEL,	NETLINK_ROUTE_SOCKET__NLMSG_READ  },
+	{ RTM_GETDCB,		NETLINK_ROUTE_SOCKET__NLMSG_READ  },
+	{ RTM_SETDCB,		NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
 };
 
 static struct nlmsg_perm nlmsg_firewall_perms[] =

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 249 - 256
security/selinux/selinuxfs.c


+ 5 - 1
security/selinux/ss/conditional.c

@@ -193,6 +193,7 @@ int cond_index_bool(void *key, void *datum, void *datap)
 {
 	struct policydb *p;
 	struct cond_bool_datum *booldatum;
+	struct flex_array *fa;
 
 	booldatum = datum;
 	p = datap;
@@ -200,7 +201,10 @@ int cond_index_bool(void *key, void *datum, void *datap)
 	if (!booldatum->value || booldatum->value > p->p_bools.nprim)
 		return -EINVAL;
 
-	p->p_bool_val_to_name[booldatum->value - 1] = key;
+	fa = p->sym_val_to_name[SYM_BOOLS];
+	if (flex_array_put_ptr(fa, booldatum->value - 1, key,
+			       GFP_KERNEL | __GFP_ZERO))
+		BUG();
 	p->bool_val_to_struct[booldatum->value - 1] = booldatum;
 
 	return 0;

+ 13 - 12
security/selinux/ss/mls.c

@@ -45,7 +45,7 @@ int mls_compute_context_len(struct context *context)
 	len = 1; /* for the beginning ":" */
 	for (l = 0; l < 2; l++) {
 		int index_sens = context->range.level[l].sens;
-		len += strlen(policydb.p_sens_val_to_name[index_sens - 1]);
+		len += strlen(sym_name(&policydb, SYM_LEVELS, index_sens - 1));
 
 		/* categories */
 		head = -2;
@@ -55,17 +55,17 @@ int mls_compute_context_len(struct context *context)
 			if (i - prev > 1) {
 				/* one or more negative bits are skipped */
 				if (head != prev) {
-					nm = policydb.p_cat_val_to_name[prev];
+					nm = sym_name(&policydb, SYM_CATS, prev);
 					len += strlen(nm) + 1;
 				}
-				nm = policydb.p_cat_val_to_name[i];
+				nm = sym_name(&policydb, SYM_CATS, i);
 				len += strlen(nm) + 1;
 				head = i;
 			}
 			prev = i;
 		}
 		if (prev != head) {
-			nm = policydb.p_cat_val_to_name[prev];
+			nm = sym_name(&policydb, SYM_CATS, prev);
 			len += strlen(nm) + 1;
 		}
 		if (l == 0) {
@@ -102,8 +102,8 @@ void mls_sid_to_context(struct context *context,
 	scontextp++;
 
 	for (l = 0; l < 2; l++) {
-		strcpy(scontextp,
-		       policydb.p_sens_val_to_name[context->range.level[l].sens - 1]);
+		strcpy(scontextp, sym_name(&policydb, SYM_LEVELS,
+					   context->range.level[l].sens - 1));
 		scontextp += strlen(scontextp);
 
 		/* categories */
@@ -118,7 +118,7 @@ void mls_sid_to_context(struct context *context,
 						*scontextp++ = '.';
 					else
 						*scontextp++ = ',';
-					nm = policydb.p_cat_val_to_name[prev];
+					nm = sym_name(&policydb, SYM_CATS, prev);
 					strcpy(scontextp, nm);
 					scontextp += strlen(nm);
 				}
@@ -126,7 +126,7 @@ void mls_sid_to_context(struct context *context,
 					*scontextp++ = ':';
 				else
 					*scontextp++ = ',';
-				nm = policydb.p_cat_val_to_name[i];
+				nm = sym_name(&policydb, SYM_CATS, i);
 				strcpy(scontextp, nm);
 				scontextp += strlen(nm);
 				head = i;
@@ -139,7 +139,7 @@ void mls_sid_to_context(struct context *context,
 				*scontextp++ = '.';
 			else
 				*scontextp++ = ',';
-			nm = policydb.p_cat_val_to_name[prev];
+			nm = sym_name(&policydb, SYM_CATS, prev);
 			strcpy(scontextp, nm);
 			scontextp += strlen(nm);
 		}
@@ -166,7 +166,7 @@ int mls_level_isvalid(struct policydb *p, struct mls_level *l)
 	if (!l->sens || l->sens > p->p_levels.nprim)
 		return 0;
 	levdatum = hashtab_search(p->p_levels.table,
-				  p->p_sens_val_to_name[l->sens - 1]);
+				  sym_name(p, SYM_LEVELS, l->sens - 1));
 	if (!levdatum)
 		return 0;
 
@@ -482,7 +482,8 @@ int mls_convert_context(struct policydb *oldp,
 
 	for (l = 0; l < 2; l++) {
 		levdatum = hashtab_search(newp->p_levels.table,
-			oldp->p_sens_val_to_name[c->range.level[l].sens - 1]);
+					  sym_name(oldp, SYM_LEVELS,
+						   c->range.level[l].sens - 1));
 
 		if (!levdatum)
 			return -EINVAL;
@@ -493,7 +494,7 @@ int mls_convert_context(struct policydb *oldp,
 			int rc;
 
 			catdatum = hashtab_search(newp->p_cats.table,
-						  oldp->p_cat_val_to_name[i]);
+						  sym_name(oldp, SYM_CATS, i));
 			if (!catdatum)
 				return -EINVAL;
 			rc = ebitmap_set_bit(&bitmap, catdatum->value - 1, 1);

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 255 - 249
security/selinux/ss/policydb.c


+ 9 - 10
security/selinux/ss/policydb.h

@@ -203,21 +203,13 @@ struct policydb {
 #define p_cats symtab[SYM_CATS]
 
 	/* symbol names indexed by (value - 1) */
-	char **sym_val_to_name[SYM_NUM];
-#define p_common_val_to_name sym_val_to_name[SYM_COMMONS]
-#define p_class_val_to_name sym_val_to_name[SYM_CLASSES]
-#define p_role_val_to_name sym_val_to_name[SYM_ROLES]
-#define p_type_val_to_name sym_val_to_name[SYM_TYPES]
-#define p_user_val_to_name sym_val_to_name[SYM_USERS]
-#define p_bool_val_to_name sym_val_to_name[SYM_BOOLS]
-#define p_sens_val_to_name sym_val_to_name[SYM_LEVELS]
-#define p_cat_val_to_name sym_val_to_name[SYM_CATS]
+	struct flex_array *sym_val_to_name[SYM_NUM];
 
 	/* class, role, and user attributes indexed by (value - 1) */
 	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;
+	struct flex_array *type_val_to_struct_array;
 
 	/* type enforcement access vectors and transitions */
 	struct avtab te_avtab;
@@ -321,6 +313,13 @@ static inline int put_entry(void *buf, size_t bytes, int num, struct policy_file
 	return 0;
 }
 
+static inline char *sym_name(struct policydb *p, unsigned int sym_num, unsigned int element_nr)
+{
+	struct flex_array *fa = p->sym_val_to_name[sym_num];
+
+	return flex_array_get_ptr(fa, element_nr);
+}
+
 extern u16 string_to_security_class(struct policydb *p, const char *name);
 extern u32 string_to_av_perm(struct policydb *p, u16 tclass, const char *name);
 

+ 209 - 216
security/selinux/ss/services.c

@@ -464,7 +464,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 +530,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 +707,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 +807,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 +819,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 +827,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;
 	}
 
@@ -1005,9 +1012,9 @@ static int context_struct_to_string(struct context *context, char **scontext, u3
 	}
 
 	/* 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 +1030,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 +1194,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)
@@ -1235,27 +1239,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;
@@ -1319,18 +1322,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);
@@ -1569,22 +1572,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 +1619,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 +1641,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 +1651,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 +1698,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 +1718,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;
@@ -2012,7 +2012,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 +2021,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 +2037,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 +2050,7 @@ int security_node_sid(u16 domain,
 		break;
 
 	default:
+		rc = 0;
 		*out_sid = SECINITSID_NODE;
 		goto out;
 	}
@@ -2069,6 +2068,7 @@ int security_node_sid(u16 domain,
 		*out_sid = SECINITSID_NODE;
 	}
 
+	rc = 0;
 out:
 	read_unlock(&policy_rwlock);
 	return rc;
@@ -2113,24 +2113,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 +2145,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 +2157,7 @@ int security_get_user_sids(u32 fromsid,
 			}
 		}
 	}
-
+	rc = 0;
 out_unlock:
 	read_unlock(&policy_rwlock);
 	if (rc || !mynel) {
@@ -2168,9 +2165,9 @@ out_unlock:
 		goto out;
 	}
 
+	rc = -ENOMEM;
 	mysids2 = kcalloc(mynel, sizeof(*mysids2), GFP_KERNEL);
 	if (!mysids2) {
-		rc = -ENOMEM;
 		kfree(mysids);
 		goto out;
 	}
@@ -2211,7 +2208,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 +2216,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 +2224,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 +2235,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;
@@ -2285,8 +2278,7 @@ int security_fs_use(
 	if (c) {
 		*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;
@@ -2309,34 +2301,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,24 +2352,23 @@ 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),
@@ -2391,7 +2387,7 @@ int security_set_bools(int len, int *values)
 	}
 
 	seqno = ++latest_granting;
-
+	rc = 0;
 out:
 	write_unlock_irq(&policy_rwlock);
 	if (!rc) {
@@ -2405,16 +2401,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 +2459,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 +2470,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 +2497,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 +2543,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 +2563,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 +2612,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 +2624,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 +2651,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 +2673,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:
@@ -2796,36 +2791,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) {
@@ -3050,7 +3048,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 +3059,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 +3075,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 +3125,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;
 }

+ 37 - 2
security/selinux/ss/sidtab.c

@@ -147,6 +147,17 @@ out:
 	return rc;
 }
 
+static void sidtab_update_cache(struct sidtab *s, struct sidtab_node *n, int loc)
+{
+	BUG_ON(loc >= SIDTAB_CACHE_LEN);
+
+	while (loc > 0) {
+		s->cache[loc] = s->cache[loc - 1];
+		loc--;
+	}
+	s->cache[0] = n;
+}
+
 static inline u32 sidtab_search_context(struct sidtab *s,
 						  struct context *context)
 {
@@ -156,14 +167,33 @@ static inline u32 sidtab_search_context(struct sidtab *s,
 	for (i = 0; i < SIDTAB_SIZE; i++) {
 		cur = s->htable[i];
 		while (cur) {
-			if (context_cmp(&cur->context, context))
+			if (context_cmp(&cur->context, context)) {
+				sidtab_update_cache(s, cur, SIDTAB_CACHE_LEN - 1);
 				return cur->sid;
+			}
 			cur = cur->next;
 		}
 	}
 	return 0;
 }
 
+static inline u32 sidtab_search_cache(struct sidtab *s, struct context *context)
+{
+	int i;
+	struct sidtab_node *node;
+
+	for (i = 0; i < SIDTAB_CACHE_LEN; i++) {
+		node = s->cache[i];
+		if (unlikely(!node))
+			return 0;
+		if (context_cmp(&node->context, context)) {
+			sidtab_update_cache(s, node, i);
+			return node->sid;
+		}
+	}
+	return 0;
+}
+
 int sidtab_context_to_sid(struct sidtab *s,
 			  struct context *context,
 			  u32 *out_sid)
@@ -174,7 +204,9 @@ int sidtab_context_to_sid(struct sidtab *s,
 
 	*out_sid = SECSID_NULL;
 
-	sid = sidtab_search_context(s, context);
+	sid  = sidtab_search_cache(s, context);
+	if (!sid)
+		sid = sidtab_search_context(s, context);
 	if (!sid) {
 		spin_lock_irqsave(&s->lock, flags);
 		/* Rescan now that we hold the lock. */
@@ -259,12 +291,15 @@ void sidtab_destroy(struct sidtab *s)
 void sidtab_set(struct sidtab *dst, struct sidtab *src)
 {
 	unsigned long flags;
+	int i;
 
 	spin_lock_irqsave(&src->lock, flags);
 	dst->htable = src->htable;
 	dst->nel = src->nel;
 	dst->next_sid = src->next_sid;
 	dst->shutdown = 0;
+	for (i = 0; i < SIDTAB_CACHE_LEN; i++)
+		dst->cache[i] = NULL;
 	spin_unlock_irqrestore(&src->lock, flags);
 }
 

+ 2 - 0
security/selinux/ss/sidtab.h

@@ -26,6 +26,8 @@ struct sidtab {
 	unsigned int nel;	/* number of elements */
 	unsigned int next_sid;	/* next SID to allocate */
 	unsigned char shutdown;
+#define SIDTAB_CACHE_LEN	3
+	struct sidtab_node *cache[SIDTAB_CACHE_LEN];
 	spinlock_t lock;
 };
 

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است