diff options
Diffstat (limited to 'fs/gfs2/acl.c')
| -rw-r--r-- | fs/gfs2/acl.c | 297 | 
1 files changed, 35 insertions, 262 deletions
diff --git a/fs/gfs2/acl.c b/fs/gfs2/acl.c index 48171f4c943..3088e2a38e3 100644 --- a/fs/gfs2/acl.c +++ b/fs/gfs2/acl.c @@ -38,8 +38,9 @@ static const char *gfs2_acl_name(int type)  	return NULL;  } -static struct posix_acl *gfs2_acl_get(struct gfs2_inode *ip, int type) +struct posix_acl *gfs2_get_acl(struct inode *inode, int type)  { +	struct gfs2_inode *ip = GFS2_I(inode);  	struct posix_acl *acl;  	const char *name;  	char *data; @@ -48,10 +49,6 @@ static struct posix_acl *gfs2_acl_get(struct gfs2_inode *ip, int type)  	if (!ip->i_eattr)  		return NULL; -	acl = get_cached_acl(&ip->i_inode, type); -	if (acl != ACL_NOT_CACHED) -		return acl; -  	name = gfs2_acl_name(type);  	if (name == NULL)  		return ERR_PTR(-EINVAL); @@ -62,54 +59,12 @@ static struct posix_acl *gfs2_acl_get(struct gfs2_inode *ip, int type)  	if (len == 0)  		return NULL; -	acl = posix_acl_from_xattr(data, len); +	acl = posix_acl_from_xattr(&init_user_ns, data, len);  	kfree(data);  	return acl;  } -/** - * gfs2_check_acl - Check an ACL to see if we're allowed to do something - * @inode: the file we want to do something to - * @mask: what we want to do - * - * Returns: errno - */ - -int gfs2_check_acl(struct inode *inode, int mask) -{ -	struct posix_acl *acl; -	int error; - -	acl = gfs2_acl_get(GFS2_I(inode), ACL_TYPE_ACCESS); -	if (IS_ERR(acl)) -		return PTR_ERR(acl); - -	if (acl) { -		error = posix_acl_permission(inode, acl, mask); -		posix_acl_release(acl); -		return error; -	} - -	return -EAGAIN; -} - -static int gfs2_set_mode(struct inode *inode, mode_t mode) -{ -	int error = 0; - -	if (mode != inode->i_mode) { -		struct iattr iattr; - -		iattr.ia_valid = ATTR_MODE; -		iattr.ia_mode = mode; - -		error = gfs2_setattr_simple(GFS2_I(inode), &iattr); -	} - -	return error; -} - -static int gfs2_acl_set(struct inode *inode, int type, struct posix_acl *acl) +int gfs2_set_acl(struct inode *inode, struct posix_acl *acl, int type)  {  	int error;  	int len; @@ -117,232 +72,50 @@ static int gfs2_acl_set(struct inode *inode, int type, struct posix_acl *acl)  	const char *name = gfs2_acl_name(type);  	BUG_ON(name == NULL); -	len = posix_acl_to_xattr(acl, NULL, 0); -	if (len == 0) -		return 0; -	data = kmalloc(len, GFP_NOFS); -	if (data == NULL) -		return -ENOMEM; -	error = posix_acl_to_xattr(acl, data, len); -	if (error < 0) -		goto out; -	error = __gfs2_xattr_set(inode, name, data, len, 0, GFS2_EATYPE_SYS); -	if (!error) -		set_cached_acl(inode, type, acl); -out: -	kfree(data); -	return error; -} - -int gfs2_acl_create(struct gfs2_inode *dip, struct inode *inode) -{ -	struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode); -	struct posix_acl *acl, *clone; -	mode_t mode = inode->i_mode; -	int error = 0; -	if (!sdp->sd_args.ar_posix_acl) -		return 0; -	if (S_ISLNK(inode->i_mode)) -		return 0; +	if (acl->a_count > GFS2_ACL_MAX_ENTRIES(GFS2_SB(inode))) +		return -E2BIG; -	acl = gfs2_acl_get(dip, ACL_TYPE_DEFAULT); -	if (IS_ERR(acl)) -		return PTR_ERR(acl); -	if (!acl) { -		mode &= ~current_umask(); -		if (mode != inode->i_mode) -			error = gfs2_set_mode(inode, mode); -		return error; -	} - -	if (S_ISDIR(inode->i_mode)) { -		error = gfs2_acl_set(inode, ACL_TYPE_DEFAULT, acl); -		if (error) -			goto out; -	} - -	clone = posix_acl_clone(acl, GFP_NOFS); -	error = -ENOMEM; -	if (!clone) -		goto out; -	posix_acl_release(acl); -	acl = clone; - -	error = posix_acl_create_masq(acl, &mode); -	if (error < 0) -		goto out; -	if (error == 0) -		goto munge; - -	error = gfs2_acl_set(inode, ACL_TYPE_ACCESS, acl); -	if (error) -		goto out; -munge: -	error = gfs2_set_mode(inode, mode); -out: -	posix_acl_release(acl); -	return error; -} +	if (type == ACL_TYPE_ACCESS) { +		umode_t mode = inode->i_mode; -int gfs2_acl_chmod(struct gfs2_inode *ip, struct iattr *attr) -{ -	struct posix_acl *acl, *clone; -	char *data; -	unsigned int len; -	int error; +		error = posix_acl_equiv_mode(acl, &mode); +		if (error < 0) +			return error; -	acl = gfs2_acl_get(ip, ACL_TYPE_ACCESS); -	if (IS_ERR(acl)) -		return PTR_ERR(acl); -	if (!acl) -		return gfs2_setattr_simple(ip, attr); +		if (error == 0) +			acl = NULL; -	clone = posix_acl_clone(acl, GFP_NOFS); -	error = -ENOMEM; -	if (!clone) -		goto out; -	posix_acl_release(acl); -	acl = clone; +		if (mode != inode->i_mode) { +			inode->i_mode = mode; +			mark_inode_dirty(inode); +		} +	} -	error = posix_acl_chmod_masq(acl, attr->ia_mode); -	if (!error) { -		len = posix_acl_to_xattr(acl, NULL, 0); +	if (acl) { +		len = posix_acl_to_xattr(&init_user_ns, acl, NULL, 0); +		if (len == 0) +			return 0;  		data = kmalloc(len, GFP_NOFS); -		error = -ENOMEM;  		if (data == NULL) +			return -ENOMEM; +		error = posix_acl_to_xattr(&init_user_ns, acl, data, len); +		if (error < 0)  			goto out; -		posix_acl_to_xattr(acl, data, len); -		error = gfs2_xattr_acl_chmod(ip, attr, data); -		kfree(data); -		set_cached_acl(&ip->i_inode, ACL_TYPE_ACCESS, acl); +	} else { +		data = NULL; +		len = 0;  	} -out: -	posix_acl_release(acl); -	return error; -} - -static int gfs2_acl_type(const char *name) -{ -	if (strcmp(name, GFS2_POSIX_ACL_ACCESS) == 0) -		return ACL_TYPE_ACCESS; -	if (strcmp(name, GFS2_POSIX_ACL_DEFAULT) == 0) -		return ACL_TYPE_DEFAULT; -	return -EINVAL; -} - -static int gfs2_xattr_system_get(struct dentry *dentry, const char *name, -				 void *buffer, size_t size, int xtype) -{ -	struct inode *inode = dentry->d_inode; -	struct gfs2_sbd *sdp = GFS2_SB(inode); -	struct posix_acl *acl; -	int type; -	int error; - -	if (!sdp->sd_args.ar_posix_acl) -		return -EOPNOTSUPP; - -	type = gfs2_acl_type(name); -	if (type < 0) -		return type; - -	acl = gfs2_acl_get(GFS2_I(inode), type); -	if (IS_ERR(acl)) -		return PTR_ERR(acl); -	if (acl == NULL) -		return -ENODATA; - -	error = posix_acl_to_xattr(acl, buffer, size); -	posix_acl_release(acl); - -	return error; -} - -static int gfs2_xattr_system_set(struct dentry *dentry, const char *name, -				 const void *value, size_t size, int flags, -				 int xtype) -{ -	struct inode *inode = dentry->d_inode; -	struct gfs2_sbd *sdp = GFS2_SB(inode); -	struct posix_acl *acl = NULL; -	int error = 0, type; - -	if (!sdp->sd_args.ar_posix_acl) -		return -EOPNOTSUPP; - -	type = gfs2_acl_type(name); -	if (type < 0) -		return type; -	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 (S_ISLNK(inode->i_mode)) -		return -EOPNOTSUPP; - -	if (!value) -		goto set_acl; - -	acl = posix_acl_from_xattr(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); +	error = __gfs2_xattr_set(inode, name, data, len, 0, GFS2_EATYPE_SYS);  	if (error) -		goto out_release; - -	error = -EINVAL; -	if (acl->a_count > GFS2_ACL_MAX_ENTRIES) -		goto out_release; - -	if (type == ACL_TYPE_ACCESS) { -		mode_t mode = inode->i_mode; -		error = posix_acl_equiv_mode(acl, &mode); - -		if (error <= 0) { -			posix_acl_release(acl); -			acl = NULL; - -			if (error < 0) -				return error; -		} - -		error = gfs2_set_mode(inode, mode); -		if (error) -			goto out_release; -	} +		goto out; -set_acl: -	error = __gfs2_xattr_set(inode, name, value, size, 0, GFS2_EATYPE_SYS); -	if (!error) { -		if (acl) -			set_cached_acl(inode, type, acl); -		else -			forget_cached_acl(inode, type); -	} -out_release: -	posix_acl_release(acl); +	if (acl) +		set_cached_acl(inode, type, acl); +	else +		forget_cached_acl(inode, type);  out: +	kfree(data);  	return error;  } - -const struct xattr_handler gfs2_xattr_system_handler = { -	.prefix = XATTR_SYSTEM_PREFIX, -	.flags  = GFS2_EATYPE_SYS, -	.get    = gfs2_xattr_system_get, -	.set    = gfs2_xattr_system_set, -}; -  | 
