Commit 635a01da authored by Konstantin Andreev's avatar Konstantin Andreev Committed by Casey Schaufler
Browse files

smack: deduplicate "does access rule request transmutation"

parent e04c78d8
Loading
Loading
Loading
Loading
+32 −25
Original line number Diff line number Diff line
@@ -962,6 +962,24 @@ static int smack_inode_alloc_security(struct inode *inode)
	return 0;
}

/**
 * smk_rule_transmutes - does access rule for (subject,object) contain 't'?
 * @subject: a pointer to the subject's Smack label entry
 * @object: a pointer to the object's Smack label entry
 */
static bool
smk_rule_transmutes(struct smack_known *subject,
	      const struct smack_known *object)
{
	int may;

	rcu_read_lock();
	may = smk_access_entry(subject->smk_known, object->smk_known,
			       &subject->smk_rules);
	rcu_read_unlock();
	return (may > 0) && (may & MAY_TRANSMUTE);
}

/**
 * smack_inode_init_security - copy out the smack from an inode
 * @inode: the newly created inode
@@ -977,23 +995,19 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
				     struct xattr *xattrs, int *xattr_count)
{
	struct task_smack *tsp = smack_cred(current_cred());
	struct inode_smack *issp = smack_inode(inode);
	struct smack_known *skp = smk_of_task(tsp);
	struct smack_known *isp = smk_of_inode(inode);
	struct inode_smack * const issp = smack_inode(inode);
	struct smack_known *dsp = smk_of_inode(dir);
	struct xattr *xattr = lsm_get_xattr_slot(xattrs, xattr_count);
	int may;
	bool trans_cred;
	bool trans_rule;

	/*
	 * If equal, transmuting already occurred in
	 * smack_dentry_create_files_as(). No need to check again.
	 */
	if (tsp->smk_task != tsp->smk_transmuted) {
		rcu_read_lock();
		may = smk_access_entry(skp->smk_known, dsp->smk_known,
				       &skp->smk_rules);
		rcu_read_unlock();
	}
	trans_cred = (tsp->smk_task == tsp->smk_transmuted);
	if (!trans_cred)
		trans_rule = smk_rule_transmutes(smk_of_task(tsp), dsp);

	/*
	 * In addition to having smk_task equal to smk_transmuted,
@@ -1001,9 +1015,7 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
	 * requests transmutation then by all means transmute.
	 * Mark the inode as changed.
	 */
	if ((tsp->smk_task == tsp->smk_transmuted) ||
	    (may > 0 && ((may & MAY_TRANSMUTE) != 0) &&
	     smk_inode_transmutable(dir))) {
	if (trans_cred || (trans_rule && smk_inode_transmutable(dir))) {
		struct xattr *xattr_transmute;

		/*
@@ -1012,8 +1024,8 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
		 * inode label was already set correctly in
		 * smack_inode_alloc_security().
		 */
		if (tsp->smk_task != tsp->smk_transmuted)
			isp = issp->smk_inode = dsp;
		if (!trans_cred)
			issp->smk_inode = dsp;

		issp->smk_flags |= SMK_INODE_TRANSMUTE;
		xattr_transmute = lsm_get_xattr_slot(xattrs,
@@ -1033,11 +1045,13 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
	issp->smk_flags |= SMK_INODE_INSTANT;

	if (xattr) {
		xattr->value = kstrdup(isp->smk_known, GFP_NOFS);
		const char *inode_label = issp->smk_inode->smk_known;

		xattr->value = kstrdup(inode_label, GFP_NOFS);
		if (!xattr->value)
			return -ENOMEM;

		xattr->value_len = strlen(isp->smk_known);
		xattr->value_len = strlen(inode_label);
		xattr->name = XATTR_SMACK_SUFFIX;
	}

@@ -4915,7 +4929,6 @@ static int smack_dentry_create_files_as(struct dentry *dentry, int mode,
	struct task_smack *otsp = smack_cred(old);
	struct task_smack *ntsp = smack_cred(new);
	struct inode_smack *isp;
	int may;

	/*
	 * Use the process credential unless all of
@@ -4929,18 +4942,12 @@ static int smack_dentry_create_files_as(struct dentry *dentry, int mode,
	isp = smack_inode(d_inode(dentry->d_parent));

	if (isp->smk_flags & SMK_INODE_TRANSMUTE) {
		rcu_read_lock();
		may = smk_access_entry(otsp->smk_task->smk_known,
				       isp->smk_inode->smk_known,
				       &otsp->smk_task->smk_rules);
		rcu_read_unlock();

		/*
		 * If the directory is transmuting and the rule
		 * providing access is transmuting use the containing
		 * directory label instead of the process label.
		 */
		if (may > 0 && (may & MAY_TRANSMUTE)) {
		if (smk_rule_transmutes(otsp->smk_task, isp->smk_inode)) {
			ntsp->smk_task = isp->smk_inode;
			ntsp->smk_transmuted = ntsp->smk_task;
		}