diff options
Diffstat (limited to 'fs/9p/acl.c')
| -rw-r--r-- | fs/9p/acl.c | 129 | 
1 files changed, 59 insertions, 70 deletions
diff --git a/fs/9p/acl.c b/fs/9p/acl.c index 12d602351db..8482f2d1160 100644 --- a/fs/9p/acl.c +++ b/fs/9p/acl.c @@ -21,14 +21,15 @@  #include <linux/posix_acl_xattr.h>  #include "xattr.h"  #include "acl.h" -#include "v9fs_vfs.h"  #include "v9fs.h" +#include "v9fs_vfs.h" +#include "fid.h"  static struct posix_acl *__v9fs_get_acl(struct p9_fid *fid, char *name)  {  	ssize_t size;  	void *value = NULL; -	struct posix_acl *acl = NULL;; +	struct posix_acl *acl = NULL;  	size = v9fs_fid_xattr_get(fid, name, NULL, 0);  	if (size > 0) { @@ -37,7 +38,7 @@ static struct posix_acl *__v9fs_get_acl(struct p9_fid *fid, char *name)  			return ERR_PTR(-ENOMEM);  		size = v9fs_fid_xattr_get(fid, name, value, size);  		if (size > 0) { -			acl = posix_acl_from_xattr(value, size); +			acl = posix_acl_from_xattr(&init_user_ns, value, size);  			if (IS_ERR(acl))  				goto err_out;  		} @@ -59,7 +60,8 @@ int v9fs_get_acl(struct inode *inode, struct p9_fid *fid)  	struct v9fs_session_info *v9ses;  	v9ses = v9fs_inode2v9ses(inode); -	if ((v9ses->flags & V9FS_ACCESS_MASK) != V9FS_ACCESS_CLIENT) { +	if (((v9ses->flags & V9FS_ACCESS_MASK) != V9FS_ACCESS_CLIENT) || +			((v9ses->flags & V9FS_ACL_MASK) != V9FS_POSIX_ACL)) {  		set_cached_acl(inode, ACL_TYPE_DEFAULT, NULL);  		set_cached_acl(inode, ACL_TYPE_ACCESS, NULL);  		return 0; @@ -71,11 +73,15 @@ int v9fs_get_acl(struct inode *inode, struct p9_fid *fid)  	if (!IS_ERR(dacl) && !IS_ERR(pacl)) {  		set_cached_acl(inode, ACL_TYPE_DEFAULT, dacl);  		set_cached_acl(inode, ACL_TYPE_ACCESS, pacl); -		posix_acl_release(dacl); -		posix_acl_release(pacl);  	} else  		retval = -EIO; +	if (!IS_ERR(dacl)) +		posix_acl_release(dacl); + +	if (!IS_ERR(pacl)) +		posix_acl_release(pacl); +  	return retval;  } @@ -91,46 +97,38 @@ static struct posix_acl *v9fs_get_cached_acl(struct inode *inode, int type)  	return acl;  } -int v9fs_check_acl(struct inode *inode, int mask) +struct posix_acl *v9fs_iop_get_acl(struct inode *inode, int type)  { -	struct posix_acl *acl;  	struct v9fs_session_info *v9ses;  	v9ses = v9fs_inode2v9ses(inode); -	if ((v9ses->flags & V9FS_ACCESS_MASK) != V9FS_ACCESS_CLIENT) { +	if (((v9ses->flags & V9FS_ACCESS_MASK) != V9FS_ACCESS_CLIENT) || +			((v9ses->flags & V9FS_ACL_MASK) != V9FS_POSIX_ACL)) {  		/* -		 * On access = client mode get the acl +		 * On access = client  and acl = on mode get the acl  		 * values from the server  		 */ -		return 0; +		return NULL;  	} -	acl = v9fs_get_cached_acl(inode, ACL_TYPE_ACCESS); +	return v9fs_get_cached_acl(inode, type); -	if (IS_ERR(acl)) -		return PTR_ERR(acl); -	if (acl) { -		int error = posix_acl_permission(inode, acl, mask); -		posix_acl_release(acl); -		return error; -	} -	return -EAGAIN;  } -static int v9fs_set_acl(struct dentry *dentry, int type, struct posix_acl *acl) +static int v9fs_set_acl(struct p9_fid *fid, int type, struct posix_acl *acl)  {  	int retval;  	char *name;  	size_t size;  	void *buffer; -	struct inode *inode = dentry->d_inode; +	if (!acl) +		return 0; -	set_cached_acl(inode, type, acl);  	/* 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); +	retval = posix_acl_to_xattr(&init_user_ns, acl, buffer, size);  	if (retval < 0)  		goto err_free_out;  	switch (type) { @@ -143,51 +141,53 @@ static int v9fs_set_acl(struct dentry *dentry, int type, struct posix_acl *acl)  	default:  		BUG();  	} -	retval = v9fs_xattr_set(dentry, name, buffer, size, 0); +	retval = v9fs_fid_xattr_set(fid, name, buffer, size, 0);  err_free_out:  	kfree(buffer);  	return retval;  } -int v9fs_acl_chmod(struct dentry *dentry) +int v9fs_acl_chmod(struct inode *inode, struct p9_fid *fid)  {  	int retval = 0; -	struct posix_acl *acl, *clone; -	struct inode *inode = dentry->d_inode; +	struct posix_acl *acl;  	if (S_ISLNK(inode->i_mode))  		return -EOPNOTSUPP;  	acl = v9fs_get_cached_acl(inode, ACL_TYPE_ACCESS);  	if (acl) { -		clone = posix_acl_clone(acl, GFP_KERNEL); +		retval = __posix_acl_chmod(&acl, GFP_KERNEL, inode->i_mode); +		if (retval) +			return retval; +		set_cached_acl(inode, ACL_TYPE_ACCESS, acl); +		retval = v9fs_set_acl(fid, ACL_TYPE_ACCESS, acl);  		posix_acl_release(acl); -		if (!clone) -			return -ENOMEM; -		retval = posix_acl_chmod_masq(clone, inode->i_mode); -		if (!retval) -			retval = v9fs_set_acl(dentry, ACL_TYPE_ACCESS, clone); -		posix_acl_release(clone);  	}  	return retval;  } -int v9fs_set_create_acl(struct dentry *dentry, -			struct posix_acl *dpacl, struct posix_acl *pacl) +int v9fs_set_create_acl(struct inode *inode, struct p9_fid *fid, +			struct posix_acl *dacl, struct posix_acl *acl)  { -	if (dpacl) -		v9fs_set_acl(dentry, ACL_TYPE_DEFAULT, dpacl); -	if (pacl) -		v9fs_set_acl(dentry, ACL_TYPE_ACCESS, pacl); -	posix_acl_release(dpacl); -	posix_acl_release(pacl); +	set_cached_acl(inode, ACL_TYPE_DEFAULT, dacl); +	set_cached_acl(inode, ACL_TYPE_ACCESS, acl); +	v9fs_set_acl(fid, ACL_TYPE_DEFAULT, dacl); +	v9fs_set_acl(fid, ACL_TYPE_ACCESS, acl);  	return 0;  } -int v9fs_acl_mode(struct inode *dir, mode_t *modep, +void v9fs_put_acl(struct posix_acl *dacl, +		  struct posix_acl *acl) +{ +	posix_acl_release(dacl); +	posix_acl_release(acl); +} + +int v9fs_acl_mode(struct inode *dir, umode_t *modep,  		  struct posix_acl **dpacl, struct posix_acl **pacl)  {  	int retval = 0; -	mode_t mode = *modep; +	umode_t mode = *modep;  	struct posix_acl *acl = NULL;  	if (!S_ISLNK(mode)) { @@ -198,29 +198,18 @@ int v9fs_acl_mode(struct inode *dir, mode_t *modep,  			mode &= ~current_umask();  	}  	if (acl) { -		struct posix_acl *clone; -  		if (S_ISDIR(mode)) -			*dpacl = acl; -		clone = posix_acl_clone(acl, GFP_NOFS); -		retval = -ENOMEM; -		if (!clone) -			goto cleanup; - -		retval = posix_acl_create_masq(clone, &mode); -		if (retval < 0) { -			posix_acl_release(clone); -			goto cleanup; -		} +			*dpacl = posix_acl_dup(acl); +		retval = __posix_acl_create(&acl, GFP_NOFS, &mode); +		if (retval < 0) +			return retval;  		if (retval > 0) -			*pacl = clone; +			*pacl = acl; +		else +			posix_acl_release(acl);  	}  	*modep  = mode;  	return 0; -cleanup: -	posix_acl_release(acl); -	return retval; -  }  static int v9fs_remote_get_acl(struct dentry *dentry, const char *name, @@ -251,7 +240,7 @@ static int v9fs_xattr_get_acl(struct dentry *dentry, const char *name,  	if (strcmp(name, "") != 0)  		return -EINVAL; -	v9ses = v9fs_inode2v9ses(dentry->d_inode); +	v9ses = v9fs_dentry2v9ses(dentry);  	/*  	 * We allow set/get/list of acl when access=client is not specified  	 */ @@ -263,7 +252,7 @@ static int v9fs_xattr_get_acl(struct dentry *dentry, const char *name,  		return PTR_ERR(acl);  	if (acl == NULL)  		return -ENODATA; -	error = posix_acl_to_xattr(acl, buffer, size); +	error = posix_acl_to_xattr(&init_user_ns, acl, buffer, size);  	posix_acl_release(acl);  	return error; @@ -301,7 +290,7 @@ static int v9fs_xattr_set_acl(struct dentry *dentry, const char *name,  	if (strcmp(name, "") != 0)  		return -EINVAL; -	v9ses = v9fs_inode2v9ses(dentry->d_inode); +	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 @@ -312,11 +301,11 @@ static int v9fs_xattr_set_acl(struct dentry *dentry, const char *name,  	if (S_ISLNK(inode->i_mode))  		return -EOPNOTSUPP; -	if (!is_owner_or_cap(inode)) +	if (!inode_owner_or_capable(inode))  		return -EPERM;  	if (value) {  		/* update the cached acl value */ -		acl = posix_acl_from_xattr(value, size); +		acl = posix_acl_from_xattr(&init_user_ns, value, size);  		if (IS_ERR(acl))  			return PTR_ERR(acl);  		else if (acl) { @@ -331,7 +320,7 @@ static int v9fs_xattr_set_acl(struct dentry *dentry, const char *name,  	case ACL_TYPE_ACCESS:  		name = POSIX_ACL_XATTR_ACCESS;  		if (acl) { -			mode_t mode = inode->i_mode; +			umode_t mode = inode->i_mode;  			retval = posix_acl_equiv_mode(acl, &mode);  			if (retval < 0)  				goto err_out; @@ -362,7 +351,7 @@ static int v9fs_xattr_set_acl(struct dentry *dentry, const char *name,  	case ACL_TYPE_DEFAULT:  		name = POSIX_ACL_XATTR_DEFAULT;  		if (!S_ISDIR(inode->i_mode)) { -			retval = -EINVAL; +			retval = acl ? -EINVAL : 0;  			goto err_out;  		}  		break;  | 
