Ejemplo n.º 1
0
/* This is used to cache the default acl before a new object is created.
 * The biggest reason for this is to get an idea of how many blocks will
 * actually be required for the create operation if we must inherit an ACL.
 * An ACL write can add up to 3 object creations and an additional file write
 * so we'd prefer not to reserve that many blocks in the journal if we can.
 * It also has the advantage of not loading the ACL with a transaction open,
 * this may seem silly, but if the owner of the directory is doing the
 * creation, the ACL may not be loaded since the permissions wouldn't require
 * it.
 * We return the number of blocks required for the transaction.
 */
int reiserfs_cache_default_acl(struct inode *inode)
{
	struct posix_acl *acl;
	int nblocks = 0;

	if (IS_PRIVATE(inode))
		return 0;

	acl = reiserfs_get_acl(inode, ACL_TYPE_DEFAULT);

	if (acl && !IS_ERR(acl)) {
		int size = reiserfs_acl_size(acl->a_count);

		/* Other xattrs can be created during inode creation. We don't
		 * want to claim too many blocks, so we check to see if we
		 * we need to create the tree to the xattrs, and then we
		 * just want two files. */
		nblocks = reiserfs_xattr_jcreate_nblocks(inode);
		nblocks += JOURNAL_BLOCKS_PER_OBJECT(inode->i_sb);

		REISERFS_I(inode)->i_flags |= i_has_xattr_dir;

		/* We need to account for writes + bitmaps for two files */
		nblocks += reiserfs_xattr_nblocks(inode, size) * 4;
		posix_acl_release(acl);
	}

	return nblocks;
}
Ejemplo n.º 2
0
/* We need to start a transaction to maintain lock ordering */
int reiserfs_xattr_set(struct inode *inode, const char *name,
		       const void *buffer, size_t buffer_size, int flags)
{

	struct reiserfs_transaction_handle th;
	int error, error2;
	size_t jbegin_count = reiserfs_xattr_nblocks(inode, buffer_size);

	if (!(flags & XATTR_REPLACE))
		jbegin_count += reiserfs_xattr_jcreate_nblocks(inode);

	reiserfs_write_lock(inode->i_sb);
	error = journal_begin(&th, inode->i_sb, jbegin_count);
	if (error) {
		reiserfs_write_unlock(inode->i_sb);
		return error;
	}

	error = reiserfs_xattr_set_handle(&th, inode, name,
					  buffer, buffer_size, flags);

	error2 = journal_end(&th, inode->i_sb, jbegin_count);
	if (error == 0)
		error = error2;
	reiserfs_write_unlock(inode->i_sb);

	return error;
}
Ejemplo n.º 3
0
/* Initializes the security context for a new inode and returns the number
 * of blocks needed for the transaction. If successful, reiserfs_security
 * must be released using reiserfs_security_free when the caller is done. */
int reiserfs_security_init(struct inode *dir, struct inode *inode,
			   struct reiserfs_security_handle *sec)
{
	int blocks = 0;
	int error;

	sec->name = NULL;

	/* Don't add selinux attributes on xattrs - they'll never get used */
	if (IS_PRIVATE(dir))
		return 0;

	error = security_inode_init_security(inode, dir, &sec->name,
					     &sec->value, &sec->length);
	if (error) {
		if (error == -EOPNOTSUPP)
			error = 0;

		sec->name = NULL;
		sec->value = NULL;
		sec->length = 0;
		return error;
	}

	if (sec->length) {
		blocks = reiserfs_xattr_jcreate_nblocks(inode) +
			 reiserfs_xattr_nblocks(inode, sec->length);
		/* We don't want to count the directories twice if we have
		 * a default ACL. */
		REISERFS_I(inode)->i_flags |= i_has_xattr_dir;
	}
	return blocks;
}
int reiserfs_security_init(struct inode *dir, struct inode *inode,
			   const struct qstr *qstr,
			   struct reiserfs_security_handle *sec)
{
	int blocks = 0;
	int error;

	sec->name = NULL;

	
	if (IS_PRIVATE(dir))
		return 0;

	error = security_old_inode_init_security(inode, dir, qstr, &sec->name,
						 &sec->value, &sec->length);
	if (error) {
		if (error == -EOPNOTSUPP)
			error = 0;

		sec->name = NULL;
		sec->value = NULL;
		sec->length = 0;
		return error;
	}

	if (sec->length && reiserfs_xattrs_initialized(inode->i_sb)) {
		blocks = reiserfs_xattr_jcreate_nblocks(inode) +
			 reiserfs_xattr_nblocks(inode, sec->length);
		REISERFS_I(inode)->i_flags |= i_has_xattr_dir;
	}
	return blocks;
}
Ejemplo n.º 5
0
static int
posix_acl_set(struct dentry *dentry, const char *name, const void *value,
		size_t size, int flags, int type)
{
	struct inode *inode = dentry->d_inode;
	struct posix_acl *acl;
	int error, error2;
	struct reiserfs_transaction_handle th;
	size_t jcreate_blocks;
	if (!reiserfs_posixacl(inode->i_sb))
		return -EOPNOTSUPP;
	if (!inode_owner_or_capable(inode))
		return -EPERM;

	if (value) {
		acl = posix_acl_from_xattr(&init_user_ns, value, size);
		if (IS_ERR(acl)) {
			return PTR_ERR(acl);
		} else if (acl) {
			error = posix_acl_valid(acl);
			if (error)
				goto release_and_out;
		}
	} else
		acl = NULL;

	/* Pessimism: We can't assume that anything from the xattr root up
	 * has been created. */

	jcreate_blocks = reiserfs_xattr_jcreate_nblocks(inode) +
			 reiserfs_xattr_nblocks(inode, size) * 2;

	reiserfs_write_lock(inode->i_sb);
	error = journal_begin(&th, inode->i_sb, jcreate_blocks);
	if (error == 0) {
		error = reiserfs_set_acl(&th, inode, type, acl);
		error2 = journal_end(&th, inode->i_sb, jcreate_blocks);
		if (error2)
			error = error2;
	}
	reiserfs_write_unlock(inode->i_sb);

      release_and_out:
	posix_acl_release(acl);
	return error;
}
Ejemplo n.º 6
0
int reiserfs_acl_chmod(struct inode *inode)
{
	struct posix_acl *acl, *clone;
	int error;

	if (S_ISLNK(inode->i_mode))
		return -EOPNOTSUPP;

	if (get_inode_sd_version(inode) == STAT_DATA_V1 ||
	    !reiserfs_posixacl(inode->i_sb)) {
		return 0;
	}

	reiserfs_write_unlock(inode->i_sb);
	acl = reiserfs_get_acl(inode, ACL_TYPE_ACCESS);
	reiserfs_write_lock(inode->i_sb);
	if (!acl)
		return 0;
	if (IS_ERR(acl))
		return PTR_ERR(acl);
	clone = posix_acl_clone(acl, GFP_NOFS);
	posix_acl_release(acl);
	if (!clone)
		return -ENOMEM;
	error = posix_acl_chmod_masq(clone, inode->i_mode);
	if (!error) {
		struct reiserfs_transaction_handle th;
		size_t size = reiserfs_xattr_nblocks(inode,
					     reiserfs_acl_size(clone->a_count));
		int depth;

		depth = reiserfs_write_lock_once(inode->i_sb);
		error = journal_begin(&th, inode->i_sb, size * 2);
		if (!error) {
			int error2;
			error = reiserfs_set_acl(&th, inode, ACL_TYPE_ACCESS,
						 clone);
			error2 = journal_end(&th, inode->i_sb, size * 2);
			if (error2)
				error = error2;
		}
		reiserfs_write_unlock_once(inode->i_sb, depth);
	}
	posix_acl_release(clone);
	return error;
}
Ejemplo n.º 7
0
int
reiserfs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
{
	int error, error2;
	struct reiserfs_transaction_handle th;
	size_t jcreate_blocks;
	int size = acl ? posix_acl_xattr_size(acl->a_count) : 0;
	int update_mode = 0;
	umode_t mode = inode->i_mode;

	/*
	 * Pessimism: We can't assume that anything from the xattr root up
	 * has been created.
	 */

	jcreate_blocks = reiserfs_xattr_jcreate_nblocks(inode) +
			 reiserfs_xattr_nblocks(inode, size) * 2;

	reiserfs_write_lock(inode->i_sb);
	error = journal_begin(&th, inode->i_sb, jcreate_blocks);
	reiserfs_write_unlock(inode->i_sb);
	if (error == 0) {
		if (type == ACL_TYPE_ACCESS && acl) {
			error = posix_acl_update_mode(inode, &mode, &acl);
			if (error)
				goto unlock;
			update_mode = 1;
		}
		error = __reiserfs_set_acl(&th, inode, type, acl);
		if (!error && update_mode)
			inode->i_mode = mode;
unlock:
		reiserfs_write_lock(inode->i_sb);
		error2 = journal_end(&th);
		reiserfs_write_unlock(inode->i_sb);
		if (error2)
			error = error2;
	}

	return error;
}