예제 #1
0
파일: acl.c 프로젝트: Lyude/linux
int orangefs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
{
	int error;
	struct iattr iattr;
	int rc;

	if (type == ACL_TYPE_ACCESS && acl) {
		/*
		 * posix_acl_update_mode checks to see if the permissions
		 * described by the ACL can be encoded into the
		 * object's mode. If so, it sets "acl" to NULL
		 * and "mode" to the new desired value. It is up to
		 * us to propagate the new mode back to the server...
		 */
		error = posix_acl_update_mode(inode, &iattr.ia_mode, &acl);
		if (error) {
			gossip_err("%s: posix_acl_update_mode err: %d\n",
				   __func__,
				   error);
			return error;
		}

		if (acl) {
			rc = __orangefs_set_acl(inode, acl, type);
		} else {
			iattr.ia_valid = ATTR_MODE;
			rc = orangefs_inode_setattr(inode, &iattr);
		}

		return rc;

	} else {
		return -EINVAL;
	}
}
예제 #2
0
static int
xfs_xattr_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 = NULL;
	int error = 0;

	if (flags & XATTR_CREATE)
		return -EINVAL;
	if (type == ACL_TYPE_DEFAULT && !S_ISDIR(inode->i_mode))
		return value ? -EACCES : 0;
	if ((current_fsuid() != inode->i_uid) && !capable(CAP_FOWNER))
		return -EPERM;

	if (!value)
		goto set_acl;

	acl = posix_acl_from_xattr(&init_user_ns, value, size);
	if (!acl) {
		/*
		 * acl_set_file(3) may request that we set default ACLs with
		 * zero length -- defend (gracefully) against that here.
		 */
		goto out;
	}
	if (IS_ERR(acl)) {
		error = PTR_ERR(acl);
		goto out;
	}

	error = posix_acl_valid(acl);
	if (error)
		goto out_release;

	error = -EINVAL;
	if (acl->a_count > XFS_ACL_MAX_ENTRIES(XFS_M(inode->i_sb)))
		goto out_release;

	if (type == ACL_TYPE_ACCESS) {
		umode_t mode = inode->i_mode;
		struct posix_acl *old_acl = acl;
		error = posix_acl_update_mode(inode, &mode, &acl);
		if (!acl)
			posix_acl_release(old_acl);
		if (error)
			goto out_release;
		error = xfs_set_mode(inode, mode);
		if (error)
			goto out_release;
	}

 set_acl:
	error = xfs_set_acl(inode, type, acl);
 out_release:
	posix_acl_release(acl);
 out:
	return error;
}
예제 #3
0
파일: acl.c 프로젝트: acton393/linux
/*
 * Set the access or default ACL of an inode.
 */
int ocfs2_set_acl(handle_t *handle,
			 struct inode *inode,
			 struct buffer_head *di_bh,
			 int type,
			 struct posix_acl *acl,
			 struct ocfs2_alloc_context *meta_ac,
			 struct ocfs2_alloc_context *data_ac)
{
	int name_index;
	void *value = NULL;
	size_t size = 0;
	int ret;

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

	switch (type) {
	case ACL_TYPE_ACCESS:
		name_index = OCFS2_XATTR_INDEX_POSIX_ACL_ACCESS;
		if (acl) {
			umode_t mode;

			ret = posix_acl_update_mode(inode, &mode, &acl);
			if (ret)
				return ret;

			ret = ocfs2_acl_set_mode(inode, di_bh,
						 handle, mode);
			if (ret)
				return ret;
		}
		break;
	case ACL_TYPE_DEFAULT:
		name_index = OCFS2_XATTR_INDEX_POSIX_ACL_DEFAULT;
		if (!S_ISDIR(inode->i_mode))
			return acl ? -EACCES : 0;
		break;
	default:
		return -EINVAL;
	}

	if (acl) {
		value = ocfs2_acl_to_xattr(acl, &size);
		if (IS_ERR(value))
			return (int)PTR_ERR(value);
	}

	if (handle)
		ret = ocfs2_xattr_set_handle(handle, inode, di_bh, name_index,
					     "", value, size, 0,
					     meta_ac, data_ac);
	else
		ret = ocfs2_xattr_set(inode, name_index, "", value, size, 0);

	kfree(value);

	return ret;
}
예제 #4
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;
}
예제 #5
0
파일: acl.c 프로젝트: avagin/linux
int btrfs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
{
	int ret;
	umode_t old_mode = inode->i_mode;

	if (type == ACL_TYPE_ACCESS && acl) {
		ret = posix_acl_update_mode(inode, &inode->i_mode, &acl);
		if (ret)
			return ret;
	}
	ret = __btrfs_set_acl(NULL, inode, acl, type);
	if (ret)
		inode->i_mode = old_mode;
	return ret;
}
예제 #6
0
파일: acl.c 프로젝트: AshishNamdev/linux
/*
 * 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;
}
예제 #7
0
파일: acl.c 프로젝트: mkrufky/linux
static int __f2fs_set_acl(struct inode *inode, int type,
			struct posix_acl *acl, struct page *ipage)
{
	int name_index;
	void *value = NULL;
	size_t size = 0;
	int error;
	umode_t mode = inode->i_mode;

	switch (type) {
	case ACL_TYPE_ACCESS:
		name_index = F2FS_XATTR_INDEX_POSIX_ACL_ACCESS;
		if (acl && !ipage) {
			error = posix_acl_update_mode(inode, &mode, &acl);
			if (error)
				return error;
			set_acl_inode(inode, mode);
		}
		break;

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

	default:
		return -EINVAL;
	}

	if (acl) {
		value = f2fs_acl_to_disk(F2FS_I_SB(inode), acl, &size);
		if (IS_ERR(value)) {
			clear_inode_flag(inode, FI_ACL_MODE);
			return PTR_ERR(value);
		}
	}

	error = f2fs_setxattr(inode, name_index, "", value, size, ipage, 0);

	kfree(value);
	if (!error)
		set_cached_acl(inode, type, acl);

	clear_inode_flag(inode, FI_ACL_MODE);
	return error;
}
예제 #8
0
/*
 * inode->i_mutex: down
 */
static int
ext2_set_acl(struct inode *inode, int type, struct posix_acl *acl)
{
	int name_index;
	void *value = NULL;
	size_t size = 0;
	int error;

	if (S_ISLNK(inode->i_mode))
		return -EOPNOTSUPP;
	if (!test_opt(inode->i_sb, POSIX_ACL))
		return 0;

	switch(type) {
		case ACL_TYPE_ACCESS:
			name_index = EXT2_XATTR_INDEX_POSIX_ACL_ACCESS;
			if (acl) {
				error = posix_acl_update_mode(inode, &inode->i_mode, &acl);
				if (error)
					return error;
				inode->i_ctime = CURRENT_TIME_SEC;
				mark_inode_dirty(inode);
			}
			break;

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

		default:
			return -EINVAL;
	}
 	if (acl) {
		value = ext2_acl_to_disk(acl, &size);
		if (IS_ERR(value))
			return (int)PTR_ERR(value);
	}

	error = ext2_xattr_set(inode, name_index, "", value, size, 0);

	kfree(value);
	if (!error)
		set_cached_acl(inode, type, acl);
	return error;
}
예제 #9
0
파일: acl.c 프로젝트: acton393/linux
/*
 * Set the access or default ACL of an inode.
 *
 * inode->i_mutex: down unless called from ext4_new_inode
 */
static int
__ext4_set_acl(handle_t *handle, struct inode *inode, int type,
	     struct posix_acl *acl)
{
	int name_index;
	void *value = NULL;
	size_t size = 0;
	int error;

	switch (type) {
	case ACL_TYPE_ACCESS:
		name_index = EXT4_XATTR_INDEX_POSIX_ACL_ACCESS;
		if (acl) {
			error = posix_acl_update_mode(inode, &inode->i_mode, &acl);
			if (error)
				return error;
			inode->i_ctime = ext4_current_time(inode);
			ext4_mark_inode_dirty(handle, inode);
		}
		break;

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

	default:
		return -EINVAL;
	}
	if (acl) {
		value = ext4_acl_to_disk(acl, &size);
		if (IS_ERR(value))
			return (int)PTR_ERR(value);
	}

	error = ext4_xattr_set_handle(handle, inode, name_index, "",
				      value, size, 0);

	kfree(value);
	if (!error)
		set_cached_acl(inode, type, acl);

	return error;
}
예제 #10
0
파일: acl.c 프로젝트: AshishNamdev/linux
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;
}
예제 #11
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;
}
예제 #12
0
int jffs2_set_acl(struct inode *inode, struct posix_acl *acl, int type)
{
	int rc, xprefix;

	switch (type) {
	case ACL_TYPE_ACCESS:
		xprefix = JFFS2_XPREFIX_ACL_ACCESS;
		if (acl) {
			umode_t mode;

			rc = posix_acl_update_mode(inode, &mode, &acl);
			if (rc)
				return rc;
			if (inode->i_mode != mode) {
				struct iattr attr;

				attr.ia_valid = ATTR_MODE | ATTR_CTIME;
				attr.ia_mode = mode;
				attr.ia_ctime = CURRENT_TIME_SEC;
				rc = jffs2_do_setattr(inode, &attr);
				if (rc < 0)
					return rc;
			}
		}
		break;
	case ACL_TYPE_DEFAULT:
		xprefix = JFFS2_XPREFIX_ACL_DEFAULT;
		if (!S_ISDIR(inode->i_mode))
			return acl ? -EACCES : 0;
		break;
	default:
		return -EINVAL;
	}
	rc = __jffs2_set_acl(inode, xprefix, acl);
	if (!rc)
		set_cached_acl(inode, type, acl);
	return rc;
}
예제 #13
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;
}
예제 #14
0
파일: acl.c 프로젝트: acton393/linux
static int v9fs_xattr_set_acl(const struct xattr_handler *handler,
			      struct dentry *dentry, struct inode *inode,
			      const char *name, const void *value,
			      size_t size, int flags)
{
	int retval;
	struct posix_acl *acl;
	struct v9fs_session_info *v9ses;

	v9ses = v9fs_dentry2v9ses(dentry);
	/*
	 * set the attribute on the remote. Without even looking at the
	 * xattr value. We leave it to the server to validate
	 */
	if ((v9ses->flags & V9FS_ACCESS_MASK) != V9FS_ACCESS_CLIENT)
		return v9fs_xattr_set(dentry, handler->name, value, size,
				      flags);

	if (S_ISLNK(inode->i_mode))
		return -EOPNOTSUPP;
	if (!inode_owner_or_capable(inode))
		return -EPERM;
	if (value) {
		/* update the cached acl value */
		acl = posix_acl_from_xattr(&init_user_ns, value, size);
		if (IS_ERR(acl))
			return PTR_ERR(acl);
		else if (acl) {
			retval = posix_acl_valid(inode->i_sb->s_user_ns, acl);
			if (retval)
				goto err_out;
		}
	} else
		acl = NULL;

	switch (handler->flags) {
	case ACL_TYPE_ACCESS:
		if (acl) {
			struct iattr iattr;

			retval = posix_acl_update_mode(inode, &iattr.ia_mode, &acl);
			if (retval)
				goto err_out;
			if (!acl) {
				/*
				 * ACL can be represented
				 * by the mode bits. So don't
				 * update ACL.
				 */
				value = NULL;
				size = 0;
			}
			iattr.ia_valid = ATTR_MODE;
			/* FIXME should we update ctime ?
			 * What is the following setxattr update the
			 * mode ?
			 */
			v9fs_vfs_setattr_dotl(dentry, &iattr);
		}
		break;
	case ACL_TYPE_DEFAULT:
		if (!S_ISDIR(inode->i_mode)) {
			retval = acl ? -EINVAL : 0;
			goto err_out;
		}
		break;
	default:
		BUG();
	}
	retval = v9fs_xattr_set(dentry, handler->name, value, size, flags);
	if (!retval)
		set_cached_acl(inode, handler->flags, acl);
err_out:
	posix_acl_release(acl);
	return retval;
}
예제 #15
0
파일: acl.c 프로젝트: AshishNamdev/linux
int orangefs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
{
	struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
	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;
		if (acl) {
			umode_t mode;

			error = posix_acl_update_mode(inode, &mode, &acl);
			if (error) {
				gossip_err("%s: posix_acl_update_mode err: %d\n",
					   __func__,
					   error);
				return error;
			}

			if (inode->i_mode != mode)
				SetModeFlag(orangefs_inode);
			inode->i_mode = mode;
			mark_inode_dirty_sync(inode);
		}
		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;
}