static int
set_nfsv4_acl_one(struct dentry *dentry, struct posix_acl *pacl, char *key)
{
	int len;
	size_t buflen;
	char *buf = NULL;
	int error = 0;

	buflen = posix_acl_xattr_size(pacl->a_count);
	buf = kmalloc(buflen, GFP_KERNEL);
	error = -ENOMEM;
	if (buf == NULL)
		goto out;

	len = posix_acl_to_xattr(pacl, buf, buflen);
	if (len < 0) {
		error = len;
		goto out;
	}

	error = vfs_setxattr(dentry, key, buf, len, 0);
out:
	kfree(buf);
	return error;
}
Beispiel #2
0
static int v9fs_set_acl(struct p9_fid *fid, int type, struct posix_acl *acl)
{
	int retval;
	char *name;
	size_t size;
	void *buffer;
	if (!acl)
		return 0;

	/* Set a setxattr request to server */
	size = posix_acl_xattr_size(acl->a_count);
	buffer = kmalloc(size, GFP_KERNEL);
	if (!buffer)
		return -ENOMEM;
	retval = posix_acl_to_xattr(&init_user_ns, acl, buffer, size);
	if (retval < 0)
		goto err_free_out;
	switch (type) {
	case ACL_TYPE_ACCESS:
		name = XATTR_NAME_POSIX_ACL_ACCESS;
		break;
	case ACL_TYPE_DEFAULT:
		name = XATTR_NAME_POSIX_ACL_DEFAULT;
		break;
	default:
		BUG();
	}
	retval = v9fs_fid_xattr_set(fid, name, buffer, size, 0);
err_free_out:
	kfree(buffer);
	return retval;
}
Beispiel #3
0
static int
set_nfsv4_acl_one(struct dentry *dentry, struct posix_acl *pacl, char *key)
{
	int len;
	size_t buflen;
	char *buf = NULL;
	int error = 0;
	struct inode *inode = dentry->d_inode;

	buflen = posix_acl_xattr_size(pacl->a_count);
	buf = kmalloc(buflen, GFP_KERNEL);
	error = -ENOMEM;
	if (buf == NULL)
		goto out;

	len = posix_acl_to_xattr(pacl, buf, buflen);
	if (len < 0) {
		error = len;
		goto out;
	}

	error = -EOPNOTSUPP;
	if (inode->i_op && inode->i_op->setxattr) {
		down(&inode->i_sem);
		security_inode_setxattr(dentry, key, buf, len, 0);
		error = inode->i_op->setxattr(dentry, key, buf, len, 0);
		if (!error)
			security_inode_post_setxattr(dentry, key, buf, len, 0);
		up(&inode->i_sem);
	}
out:
	kfree(buf);
	return error;
}
Beispiel #4
0
static int btrfs_set_acl(struct btrfs_trans_handle *trans,
			 struct inode *inode, struct posix_acl *acl, int type)
{
	int ret, size = 0;
	const char *name;
	char *value = NULL;
	mode_t mode;

	if (acl) {
		ret = posix_acl_valid(acl);
		if (ret < 0)
			return ret;
		ret = 0;
	}

	switch (type) {
	case ACL_TYPE_ACCESS:
		mode = inode->i_mode;
		name = POSIX_ACL_XATTR_ACCESS;
		if (acl) {
			ret = posix_acl_equiv_mode(acl, &mode);
			if (ret < 0)
				return ret;
			inode->i_mode = mode;
		}
		ret = 0;
		break;
	case ACL_TYPE_DEFAULT:
		if (!S_ISDIR(inode->i_mode))
			return acl ? -EINVAL : 0;
		name = POSIX_ACL_XATTR_DEFAULT;
		break;
	default:
		return -EINVAL;
	}

	if (acl) {
		size = posix_acl_xattr_size(acl->a_count);
		value = kmalloc(size, GFP_NOFS);
		if (!value) {
			ret = -ENOMEM;
			goto out;
		}

		ret = posix_acl_to_xattr(acl, value, size);
		if (ret < 0)
			goto out;
	}

	ret = __btrfs_setxattr(trans, inode, name, value, size, 0);
out:
	kfree(value);

	if (!ret)
		set_cached_acl(inode, type, acl);

	return ret;
}
Beispiel #5
0
static int __btrfs_set_acl(struct btrfs_trans_handle *trans,
			 struct inode *inode, struct posix_acl *acl, int type)
{
	int ret, size = 0;
	const char *name;
	char *value = NULL;

	switch (type) {
	case ACL_TYPE_ACCESS:
		name = XATTR_NAME_POSIX_ACL_ACCESS;
		break;
	case ACL_TYPE_DEFAULT:
		if (!S_ISDIR(inode->i_mode))
			return acl ? -EINVAL : 0;
		name = XATTR_NAME_POSIX_ACL_DEFAULT;
		break;
	default:
		return -EINVAL;
	}

	if (acl) {
		unsigned int nofs_flag;

		size = posix_acl_xattr_size(acl->a_count);
		/*
		 * We're holding a transaction handle, so use a NOFS memory
		 * allocation context to avoid deadlock if reclaim happens.
		 */
		nofs_flag = memalloc_nofs_save();
		value = kmalloc(size, GFP_KERNEL);
		memalloc_nofs_restore(nofs_flag);
		if (!value) {
			ret = -ENOMEM;
			goto out;
		}

		ret = posix_acl_to_xattr(&init_user_ns, acl, value, size);
		if (ret < 0)
			goto out;
	}

	if (trans)
		ret = btrfs_setxattr(trans, inode, name, value, size, 0);
	else
		ret = btrfs_setxattr_trans(inode, name, value, size, 0);

out:
	kfree(value);

	if (!ret)
		set_cached_acl(inode, type, acl);

	return ret;
}
Beispiel #6
0
Datei: acl.c Projekt: Lyude/linux
static int __orangefs_set_acl(struct inode *inode, struct posix_acl *acl,
			      int type)
{
	int error = 0;
	void *value = NULL;
	size_t size = 0;
	const char *name = NULL;

	switch (type) {
	case ACL_TYPE_ACCESS:
		name = XATTR_NAME_POSIX_ACL_ACCESS;
		break;
	case ACL_TYPE_DEFAULT:
		name = XATTR_NAME_POSIX_ACL_DEFAULT;
		break;
	default:
		gossip_err("%s: invalid type %d!\n", __func__, type);
		return -EINVAL;
	}

	gossip_debug(GOSSIP_ACL_DEBUG,
		     "%s: inode %pU, key %s type %d\n",
		     __func__, get_khandle_from_ino(inode),
		     name,
		     type);

	if (acl) {
		size = posix_acl_xattr_size(acl->a_count);
		value = kmalloc(size, GFP_KERNEL);
		if (!value)
			return -ENOMEM;

		error = posix_acl_to_xattr(&init_user_ns, acl, value, size);
		if (error < 0)
			goto out;
	}

	gossip_debug(GOSSIP_ACL_DEBUG,
		     "%s: name %s, value %p, size %zd, acl %p\n",
		     __func__, name, value, size, acl);
	/*
	 * Go ahead and set the extended attribute now. NOTE: Suppose acl
	 * was NULL, then value will be NULL and size will be 0 and that
	 * will xlate to a removexattr. However, we don't want removexattr
	 * complain if attributes does not exist.
	 */
	error = orangefs_inode_setxattr(inode, name, value, size, 0);

out:
	kfree(value);
	if (!error)
		set_cached_acl(inode, type, acl);
	return error;
}
Beispiel #7
0
int hfsplus_set_posix_acl(struct inode *inode, struct posix_acl *acl,
		int type)
{
	int err;
	char *xattr_name;
	size_t size = 0;
	char *value = NULL;

	hfs_dbg(ACL_MOD, "[%s]: ino %lu\n", __func__, inode->i_ino);

	switch (type) {
	case ACL_TYPE_ACCESS:
		xattr_name = POSIX_ACL_XATTR_ACCESS;
		if (acl) {
			err = posix_acl_update_mode(inode, &inode->i_mode, &acl);
			if (err)
				return err;
		}
		err = 0;
		break;

	case ACL_TYPE_DEFAULT:
		xattr_name = POSIX_ACL_XATTR_DEFAULT;
		if (!S_ISDIR(inode->i_mode))
			return acl ? -EACCES : 0;
		break;

	default:
		return -EINVAL;
	}

	if (acl) {
		size = posix_acl_xattr_size(acl->a_count);
		if (unlikely(size > HFSPLUS_MAX_INLINE_DATA_SIZE))
			return -ENOMEM;
		value = (char *)hfsplus_alloc_attr_entry();
		if (unlikely(!value))
			return -ENOMEM;
		err = posix_acl_to_xattr(&init_user_ns, acl, value, size);
		if (unlikely(err < 0))
			goto end_set_acl;
	}

	err = __hfsplus_setxattr(inode, xattr_name, value, size, 0);

end_set_acl:
	hfsplus_destroy_attr_entry((hfsplus_attr_entry *)value);

	if (!err)
		set_cached_acl(inode, type, acl);

	return err;
}
Beispiel #8
0
int fuse_set_acl(struct inode *inode, struct posix_acl *acl, int type)
{
	struct fuse_conn *fc = get_fuse_conn(inode);
	const char *name;
	int ret;

	if (!fc->posix_acl || fc->no_setxattr)
		return -EOPNOTSUPP;

	if (type == ACL_TYPE_ACCESS)
		name = XATTR_NAME_POSIX_ACL_ACCESS;
	else if (type == ACL_TYPE_DEFAULT)
		name = XATTR_NAME_POSIX_ACL_DEFAULT;
	else
		return -EINVAL;

	if (acl) {
		/*
		 * Fuse userspace is responsible for updating access
		 * permissions in the inode, if needed. fuse_setxattr
		 * invalidates the inode attributes, which will force
		 * them to be refreshed the next time they are used,
		 * and it also updates i_ctime.
		 */
		size_t size = posix_acl_xattr_size(acl->a_count);
		void *value;

		if (size > PAGE_SIZE)
			return -E2BIG;

		value = kmalloc(size, GFP_KERNEL);
		if (!value)
			return -ENOMEM;

		ret = posix_acl_to_xattr(&init_user_ns, acl, value, size);
		if (ret < 0) {
			kfree(value);
			return ret;
		}

		ret = fuse_setxattr(inode, name, value, size, 0);
		kfree(value);
	} else {
		ret = fuse_removexattr(inode, name);
	}
	forget_all_cached_acls(inode);
	fuse_invalidate_attr(inode);

	return ret;
}
Beispiel #9
0
int
xfs_acl_vget(
	xfs_vnode_t		*vp,
	void		*acl,
	size_t		size,
	int		kind)
{
	int			error;
	xfs_acl_t		*xfs_acl = NULL;
	posix_acl_xattr_header	*ext_acl = acl;
	int			flags = 0;

	VN_HOLD(vp);
	if(size) {
		if (!(_ACL_ALLOC(xfs_acl))) {
			error = ENOMEM;
			goto out;
		}
		memset(xfs_acl, 0, sizeof(xfs_acl_t));
	} else
		flags = ATTR_KERNOVAL;

	xfs_acl_get_attr(vp, xfs_acl, kind, flags, &error);
	if (error)
		goto out;

	if (!size) {
		error = -posix_acl_xattr_size(XFS_ACL_MAX_ENTRIES);
	} else {
		if (xfs_acl_invalid(xfs_acl)) {
			error = EINVAL;
			goto out;
		}
		if (kind == _ACL_TYPE_ACCESS) {
			xfs_vattr_t	va;

			va.va_mask = XFS_AT_MODE;
			XVOP_GETATTR(vp, &va, 0, sys_cred, error);
			if (error)
				goto out;
			xfs_acl_sync_mode(va.va_mode, xfs_acl);
		}
		error = -posix_acl_xfs_to_xattr(xfs_acl, ext_acl, size);
	}
out:
	VN_RELE(vp);
	if(xfs_acl)
		_ACL_FREE(xfs_acl);
	return -error;
}
Beispiel #10
0
/*
 * Needs to be called with fs_mutex held
 */
static int __btrfs_set_acl(struct btrfs_trans_handle *trans,
			 struct inode *inode, struct posix_acl *acl, int type)
{
	int ret, size = 0;
	const char *name;
	char *value = NULL;

	switch (type) {
	case ACL_TYPE_ACCESS:
		name = XATTR_NAME_POSIX_ACL_ACCESS;
		if (acl) {
			ret = posix_acl_update_mode(inode, &inode->i_mode, &acl);
			if (ret)
				return ret;
		}
		ret = 0;
		break;
	case ACL_TYPE_DEFAULT:
		if (!S_ISDIR(inode->i_mode))
			return acl ? -EINVAL : 0;
		name = XATTR_NAME_POSIX_ACL_DEFAULT;
		break;
	default:
		return -EINVAL;
	}

	if (acl) {
		size = posix_acl_xattr_size(acl->a_count);
		value = kmalloc(size, GFP_KERNEL);
		if (!value) {
			ret = -ENOMEM;
			goto out;
		}

		ret = posix_acl_to_xattr(&init_user_ns, acl, value, size);
		if (ret < 0)
			goto out;
	}

	ret = __btrfs_setxattr(trans, inode, name, value, size, 0);
out:
	kfree(value);

	if (!ret)
		set_cached_acl(inode, type, acl);

	return ret;
}
Beispiel #11
0
static int jfs_set_acl(tid_t tid, struct inode *inode, int type,
		       struct posix_acl *acl)
{
	char *ea_name;
	struct jfs_inode_info *ji = JFS_IP(inode);
	struct posix_acl **p_acl;
	int rc;
	int size = 0;
	char *value = NULL;

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

	switch(type) {
		case ACL_TYPE_ACCESS:
			ea_name = POSIX_ACL_XATTR_ACCESS;
			p_acl = &ji->i_acl;
			break;
		case ACL_TYPE_DEFAULT:
			ea_name = POSIX_ACL_XATTR_DEFAULT;
			p_acl = &ji->i_default_acl;
			if (!S_ISDIR(inode->i_mode))
				return acl ? -EACCES : 0;
			break;
		default:
			return -EINVAL;
	}
	if (acl) {
		size = posix_acl_xattr_size(acl->a_count);
		value = kmalloc(size, GFP_KERNEL);
		if (!value)
			return -ENOMEM;
		rc = posix_acl_to_xattr(acl, value, size);
		if (rc < 0)
			goto out;
	}
	rc = __jfs_setxattr(tid, inode, ea_name, value, size, 0);
out:
	kfree(value);

	if (!rc) {
		if (*p_acl && (*p_acl != JFS_ACL_NOT_CACHED))
			posix_acl_release(*p_acl);
		*p_acl = posix_acl_dup(acl);
	}
	return rc;
}
Beispiel #12
0
static int __jfs_set_acl(tid_t tid, struct inode *inode, int type,
		       struct posix_acl *acl)
{
	char *ea_name;
	int rc;
	int size = 0;
	char *value = NULL;

	switch (type) {
	case ACL_TYPE_ACCESS:
		ea_name = XATTR_NAME_POSIX_ACL_ACCESS;
		if (acl) {
			rc = posix_acl_update_mode(inode, &inode->i_mode, &acl);
			if (rc)
				return rc;
			inode->i_ctime = current_time(inode);
			mark_inode_dirty(inode);
		}
		break;
	case ACL_TYPE_DEFAULT:
		ea_name = XATTR_NAME_POSIX_ACL_DEFAULT;
		break;
	default:
		return -EINVAL;
	}

	if (acl) {
		size = posix_acl_xattr_size(acl->a_count);
		value = kmalloc(size, GFP_KERNEL);
		if (!value)
			return -ENOMEM;
		rc = posix_acl_to_xattr(&init_user_ns, acl, value, size);
		if (rc < 0)
			goto out;
	}
	rc = __jfs_setxattr(tid, inode, ea_name, value, size, 0);
out:
	kfree(value);

	if (!rc)
		set_cached_acl(inode, type, acl);

	return rc;
}
Beispiel #13
0
/*
 * Convert from in-memory XFS to extended attribute representation.
 */
STATIC int
posix_acl_xfs_to_xattr(
	xfs_acl_t		*src,
	posix_acl_xattr_header	*dest,
	size_t			size)
{
	int			n;
	size_t			new_size = posix_acl_xattr_size(src->acl_cnt);
	posix_acl_xattr_entry	*dest_entry;
	xfs_acl_entry_t		*src_entry;

	if (size < new_size)
		return -ERANGE;

	/* Need to sort src XFS ACL by <ae_tag,ae_id> */
	xfs_sort(src->acl_entry, src->acl_cnt, sizeof(src->acl_entry[0]),
		 xfs_acl_entry_compare);

	dest->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
	dest_entry = &dest->a_entries[0];
	src_entry = &src->acl_entry[0];
	for (n = 0; n < src->acl_cnt; n++, dest_entry++, src_entry++) {
		dest_entry->e_perm = cpu_to_le16(src_entry->ae_perm);
		if (_ACL_PERM_INVALID(src_entry->ae_perm))
			return -EINVAL;
		dest_entry->e_tag  = cpu_to_le16(src_entry->ae_tag);
		switch (src_entry->ae_tag) {
		case ACL_USER:
		case ACL_GROUP:
			dest_entry->e_id = cpu_to_le32(src_entry->ae_id);
				break;
		case ACL_USER_OBJ:
		case ACL_GROUP_OBJ:
		case ACL_MASK:
		case ACL_OTHER:
			dest_entry->e_id = cpu_to_le32(ACL_UNDEFINED_ID);
			break;
		default:
			return -EINVAL;
		}
	}
	return new_size;
}
Beispiel #14
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;
}
Beispiel #15
0
static int jfs_set_acl(tid_t tid, struct inode *inode, int type,
		       struct posix_acl *acl)
{
	char *ea_name;
	int rc;
	int size = 0;
	char *value = NULL;

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

	switch(type) {
		case ACL_TYPE_ACCESS:
			ea_name = POSIX_ACL_XATTR_ACCESS;
			break;
		case ACL_TYPE_DEFAULT:
			ea_name = POSIX_ACL_XATTR_DEFAULT;
			if (!S_ISDIR(inode->i_mode))
				return acl ? -EACCES : 0;
			break;
		default:
			return -EINVAL;
	}
	if (acl) {
		size = posix_acl_xattr_size(acl->a_count);
		value = kmalloc(size, GFP_KERNEL);
		if (!value)
			return -ENOMEM;
		rc = posix_acl_to_xattr(acl, value, size);
		if (rc < 0)
			goto out;
	}
	rc = __jfs_setxattr(tid, inode, ea_name, value, size, 0);
out:
	kfree(value);

	if (!rc)
		set_cached_acl(inode, type, acl);

	return rc;
}
Beispiel #16
0
/*
 * Convert from in-memory to extended attribute representation.
 */
int
posix_acl_to_xattr(const struct posix_acl *acl, void *buffer, size_t size)
{
	posix_acl_xattr_header *ext_acl = (posix_acl_xattr_header *)buffer;
	posix_acl_xattr_entry *ext_entry = ext_acl->a_entries;
	int real_size, n;

	real_size = posix_acl_xattr_size(acl->a_count);
	if (!buffer)
		return real_size;
	if (real_size > size)
		return -ERANGE;
	
	ext_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);

	for (n=0; n < acl->a_count; n++, ext_entry++) {
		ext_entry->e_tag  = cpu_to_le16(acl->a_entries[n].e_tag);
		ext_entry->e_perm = cpu_to_le16(acl->a_entries[n].e_perm);
		ext_entry->e_id   = cpu_to_le32(acl->a_entries[n].e_id);
	}
	return real_size;
}
Beispiel #17
0
static int v9fs_set_acl(struct dentry *dentry, int type, struct posix_acl *acl)
{
	int retval;
	char *name;
	size_t size;
	void *buffer;
	struct inode *inode = dentry->d_inode;

	set_cached_acl(inode, type, acl);

	if (!acl)
		return 0;

	/* Set a setxattr request to server */
	size = posix_acl_xattr_size(acl->a_count);
	buffer = kmalloc(size, GFP_KERNEL);
	if (!buffer)
		return -ENOMEM;
	retval = posix_acl_to_xattr(acl, buffer, size);
	if (retval < 0)
		goto err_free_out;
	switch (type) {
	case ACL_TYPE_ACCESS:
		name = POSIX_ACL_XATTR_ACCESS;
		break;
	case ACL_TYPE_DEFAULT:
		name = POSIX_ACL_XATTR_DEFAULT;
		break;
	default:
		BUG();
	}
	retval = v9fs_xattr_set(dentry, name, buffer, size, 0);
err_free_out:
	kfree(buffer);
	return retval;
}
Beispiel #18
0
/*
 * Convert from in-memory to extended attribute representation.
 */
int
posix_acl_to_xattr(struct user_namespace *user_ns, const struct posix_acl *acl,
		   void *buffer, size_t size)
{
	posix_acl_xattr_header *ext_acl = (posix_acl_xattr_header *)buffer;
	posix_acl_xattr_entry *ext_entry = ext_acl->a_entries;
	int real_size, n;

	real_size = posix_acl_xattr_size(acl->a_count);
	if (!buffer)
		return real_size;
	if (real_size > size)
		return -ERANGE;
	
	ext_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);

	for (n=0; n < acl->a_count; n++, ext_entry++) {
		const struct posix_acl_entry *acl_e = &acl->a_entries[n];
		ext_entry->e_tag  = cpu_to_le16(acl_e->e_tag);
		ext_entry->e_perm = cpu_to_le16(acl_e->e_perm);
		switch(acl_e->e_tag) {
		case ACL_USER:
			ext_entry->e_id =
				cpu_to_le32(from_kuid(user_ns, acl_e->e_uid));
			break;
		case ACL_GROUP:
			ext_entry->e_id =
				cpu_to_le32(from_kgid(user_ns, acl_e->e_gid));
			break;
		default:
			ext_entry->e_id = cpu_to_le32(ACL_UNDEFINED_ID);
			break;
		}
	}
	return real_size;
}
Beispiel #19
0
int ceph_set_acl(struct inode *inode, struct posix_acl *acl, int type)
{
    int ret = 0, size = 0;
    const char *name = NULL;
    char *value = NULL;
    struct iattr newattrs;
    umode_t new_mode = inode->i_mode, old_mode = inode->i_mode;

    switch (type) {
    case ACL_TYPE_ACCESS:
        name = XATTR_NAME_POSIX_ACL_ACCESS;
        if (acl) {
            ret = posix_acl_update_mode(inode, &new_mode, &acl);
            if (ret)
                goto out;
        }
        break;
    case ACL_TYPE_DEFAULT:
        if (!S_ISDIR(inode->i_mode)) {
            ret = acl ? -EINVAL : 0;
            goto out;
        }
        name = XATTR_NAME_POSIX_ACL_DEFAULT;
        break;
    default:
        ret = -EINVAL;
        goto out;
    }

    if (acl) {
        size = posix_acl_xattr_size(acl->a_count);
        value = kmalloc(size, GFP_NOFS);
        if (!value) {
            ret = -ENOMEM;
            goto out;
        }

        ret = posix_acl_to_xattr(&init_user_ns, acl, value, size);
        if (ret < 0)
            goto out_free;
    }

    if (new_mode != old_mode) {
        newattrs.ia_mode = new_mode;
        newattrs.ia_valid = ATTR_MODE;
        ret = __ceph_setattr(inode, &newattrs);
        if (ret)
            goto out_free;
    }

    ret = __ceph_setxattr(inode, name, value, size, 0);
    if (ret) {
        if (new_mode != old_mode) {
            newattrs.ia_mode = old_mode;
            newattrs.ia_valid = ATTR_MODE;
            __ceph_setattr(inode, &newattrs);
        }
        goto out_free;
    }

    ceph_set_cached_acl(inode, type, acl);

out_free:
    kfree(value);
out:
    return ret;
}
Beispiel #20
0
int ceph_pre_init_acls(struct inode *dir, umode_t *mode,
                       struct ceph_acls_info *info)
{
    struct posix_acl *acl, *default_acl;
    size_t val_size1 = 0, val_size2 = 0;
    struct ceph_pagelist *pagelist = NULL;
    void *tmp_buf = NULL;
    int err;

    err = posix_acl_create(dir, mode, &default_acl, &acl);
    if (err)
        return err;

    if (acl) {
        int ret = posix_acl_equiv_mode(acl, mode);
        if (ret < 0)
            goto out_err;
        if (ret == 0) {
            posix_acl_release(acl);
            acl = NULL;
        }
    }

    if (!default_acl && !acl)
        return 0;

    if (acl)
        val_size1 = posix_acl_xattr_size(acl->a_count);
    if (default_acl)
        val_size2 = posix_acl_xattr_size(default_acl->a_count);

    err = -ENOMEM;
    tmp_buf = kmalloc(max(val_size1, val_size2), GFP_KERNEL);
    if (!tmp_buf)
        goto out_err;
    pagelist = kmalloc(sizeof(struct ceph_pagelist), GFP_KERNEL);
    if (!pagelist)
        goto out_err;
    ceph_pagelist_init(pagelist);

    err = ceph_pagelist_reserve(pagelist, PAGE_SIZE);
    if (err)
        goto out_err;

    ceph_pagelist_encode_32(pagelist, acl && default_acl ? 2 : 1);

    if (acl) {
        size_t len = strlen(XATTR_NAME_POSIX_ACL_ACCESS);
        err = ceph_pagelist_reserve(pagelist, len + val_size1 + 8);
        if (err)
            goto out_err;
        ceph_pagelist_encode_string(pagelist, XATTR_NAME_POSIX_ACL_ACCESS,
                                    len);
        err = posix_acl_to_xattr(&init_user_ns, acl,
                                 tmp_buf, val_size1);
        if (err < 0)
            goto out_err;
        ceph_pagelist_encode_32(pagelist, val_size1);
        ceph_pagelist_append(pagelist, tmp_buf, val_size1);
    }
    if (default_acl) {
        size_t len = strlen(XATTR_NAME_POSIX_ACL_DEFAULT);
        err = ceph_pagelist_reserve(pagelist, len + val_size2 + 8);
        if (err)
            goto out_err;
        err = ceph_pagelist_encode_string(pagelist,
                                          XATTR_NAME_POSIX_ACL_DEFAULT, len);
        err = posix_acl_to_xattr(&init_user_ns, default_acl,
                                 tmp_buf, val_size2);
        if (err < 0)
            goto out_err;
        ceph_pagelist_encode_32(pagelist, val_size2);
        ceph_pagelist_append(pagelist, tmp_buf, val_size2);
    }

    kfree(tmp_buf);

    info->acl = acl;
    info->default_acl = default_acl;
    info->pagelist = pagelist;
    return 0;

out_err:
    posix_acl_release(acl);
    posix_acl_release(default_acl);
    kfree(tmp_buf);
    if (pagelist)
        ceph_pagelist_release(pagelist);
    return err;
}
Beispiel #21
0
int
zpl_set_acl(struct inode *ip, int type, struct posix_acl *acl)
{
	struct super_block *sb = ITOZSB(ip)->z_sb;
	char *name, *value = NULL;
	int error = 0;
	size_t size = 0;

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

	switch(type) {
	case ACL_TYPE_ACCESS:
		name = POSIX_ACL_XATTR_ACCESS;
		if (acl) {
			zpl_equivmode_t mode = ip->i_mode;
			error = posix_acl_equiv_mode(acl, &mode);
			if (error < 0) {
				return (error);
			} else {
				/*
				 * The mode bits will have been set by
				 * ->zfs_setattr()->zfs_acl_chmod_setattr()
				 * using the ZFS ACL conversion.  If they
				 * differ from the Posix ACL conversion dirty
				 * the inode to write the Posix mode bits.
				 */
				if (ip->i_mode != mode) {
					ip->i_mode = mode;
					ip->i_ctime = current_fs_time(sb);
					mark_inode_dirty(ip);
				}

				if (error == 0)
					acl = NULL;
			}
		}
		break;

	case ACL_TYPE_DEFAULT:
		name = POSIX_ACL_XATTR_DEFAULT;
		if (!S_ISDIR(ip->i_mode))
			return (acl ? -EACCES : 0);
		break;

	default:
		return (-EINVAL);
	}

	if (acl) {
		size = posix_acl_xattr_size(acl->a_count);
		value = kmem_alloc(size, KM_SLEEP);

		error = zpl_acl_to_xattr(acl, value, size);
		if (error < 0) {
			kmem_free(value, size);
			return (error);
		}
	}

	error = zpl_xattr_set(ip, name, value, size, 0);
	if (value)
		kmem_free(value, size);

	if (!error) {
		if (acl)
			zpl_set_cached_acl(ip, type, acl);
		else
			zpl_forget_cached_acl(ip, type);
	}

	return (error);
}