fs: add generic xattr_acl handlers
With the ->set_acl inode operation we can implement the Posix ACL xattr handlers in generic code instead of duplicating them all over the tree. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Jan Kara <jack@suse.cz> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
		
					parent
					
						
							
								893d46e443
							
						
					
				
			
			
				commit
				
					
						2aeccbe957
					
				
			
		
					 2 changed files with 105 additions and 0 deletions
				
			
		
							
								
								
									
										102
									
								
								fs/posix_acl.c
									
										
									
									
									
								
							
							
						
						
									
										102
									
								
								fs/posix_acl.c
									
										
									
									
									
								
							|  | @ -17,6 +17,7 @@ | |||
| #include <linux/sched.h> | ||||
| #include <linux/posix_acl.h> | ||||
| #include <linux/posix_acl_xattr.h> | ||||
| #include <linux/xattr.h> | ||||
| #include <linux/export.h> | ||||
| #include <linux/user_namespace.h> | ||||
| 
 | ||||
|  | @ -611,3 +612,104 @@ posix_acl_to_xattr(struct user_namespace *user_ns, const struct posix_acl *acl, | |||
| 	return real_size; | ||||
| } | ||||
| EXPORT_SYMBOL (posix_acl_to_xattr); | ||||
| 
 | ||||
| static int | ||||
| posix_acl_xattr_get(struct dentry *dentry, const char *name, | ||||
| 		void *value, size_t size, int type) | ||||
| { | ||||
| 	struct posix_acl *acl; | ||||
| 	int error; | ||||
| 
 | ||||
| 	if (!IS_POSIXACL(dentry->d_inode)) | ||||
| 		return -EOPNOTSUPP; | ||||
| 	if (S_ISLNK(dentry->d_inode->i_mode)) | ||||
| 		return -EOPNOTSUPP; | ||||
| 
 | ||||
| 	acl = get_acl(dentry->d_inode, type); | ||||
| 	if (IS_ERR(acl)) | ||||
| 		return PTR_ERR(acl); | ||||
| 	if (acl == NULL) | ||||
| 		return -ENODATA; | ||||
| 
 | ||||
| 	error = posix_acl_to_xattr(&init_user_ns, acl, value, size); | ||||
| 	posix_acl_release(acl); | ||||
| 
 | ||||
| 	return error; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| posix_acl_xattr_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 ret; | ||||
| 
 | ||||
| 	if (!IS_POSIXACL(inode)) | ||||
| 		return -EOPNOTSUPP; | ||||
| 	if (!inode->i_op->set_acl) | ||||
| 		return -EOPNOTSUPP; | ||||
| 
 | ||||
| 	if (type == ACL_TYPE_DEFAULT && !S_ISDIR(inode->i_mode)) | ||||
| 		return value ? -EACCES : 0; | ||||
| 	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); | ||||
| 
 | ||||
| 		if (acl) { | ||||
| 			ret = posix_acl_valid(acl); | ||||
| 			if (ret) | ||||
| 				goto out; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	ret = inode->i_op->set_acl(inode, acl, type); | ||||
| out: | ||||
| 	posix_acl_release(acl); | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| static size_t | ||||
| posix_acl_xattr_list(struct dentry *dentry, char *list, size_t list_size, | ||||
| 		const char *name, size_t name_len, int type) | ||||
| { | ||||
| 	const char *xname; | ||||
| 	size_t size; | ||||
| 
 | ||||
| 	if (!IS_POSIXACL(dentry->d_inode)) | ||||
| 		return -EOPNOTSUPP; | ||||
| 	if (S_ISLNK(dentry->d_inode->i_mode)) | ||||
| 		return -EOPNOTSUPP; | ||||
| 
 | ||||
| 	if (type == ACL_TYPE_ACCESS) | ||||
| 		xname = POSIX_ACL_XATTR_ACCESS; | ||||
| 	else | ||||
| 		xname = POSIX_ACL_XATTR_DEFAULT; | ||||
| 
 | ||||
| 	size = strlen(xname) + 1; | ||||
| 	if (list && size <= list_size) | ||||
| 		memcpy(list, xname, size); | ||||
| 	return size; | ||||
| } | ||||
| 
 | ||||
| const struct xattr_handler posix_acl_access_xattr_handler = { | ||||
| 	.prefix = POSIX_ACL_XATTR_ACCESS, | ||||
| 	.flags = ACL_TYPE_ACCESS, | ||||
| 	.list = posix_acl_xattr_list, | ||||
| 	.get = posix_acl_xattr_get, | ||||
| 	.set = posix_acl_xattr_set, | ||||
| }; | ||||
| EXPORT_SYMBOL_GPL(posix_acl_access_xattr_handler); | ||||
| 
 | ||||
| const struct xattr_handler posix_acl_default_xattr_handler = { | ||||
| 	.prefix = POSIX_ACL_XATTR_DEFAULT, | ||||
| 	.flags = ACL_TYPE_DEFAULT, | ||||
| 	.list = posix_acl_xattr_list, | ||||
| 	.get = posix_acl_xattr_get, | ||||
| 	.set = posix_acl_xattr_set, | ||||
| }; | ||||
| EXPORT_SYMBOL_GPL(posix_acl_default_xattr_handler); | ||||
|  |  | |||
|  | @ -69,4 +69,7 @@ struct posix_acl *posix_acl_from_xattr(struct user_namespace *user_ns, | |||
| int posix_acl_to_xattr(struct user_namespace *user_ns, | ||||
| 		       const struct posix_acl *acl, void *buffer, size_t size); | ||||
| 
 | ||||
| extern const struct xattr_handler posix_acl_access_xattr_handler; | ||||
| extern const struct xattr_handler posix_acl_default_xattr_handler; | ||||
| 
 | ||||
| #endif	/* _POSIX_ACL_XATTR_H */ | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Christoph Hellwig
				Christoph Hellwig