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/sched.h> | ||||||
| #include <linux/posix_acl.h> | #include <linux/posix_acl.h> | ||||||
| #include <linux/posix_acl_xattr.h> | #include <linux/posix_acl_xattr.h> | ||||||
|  | #include <linux/xattr.h> | ||||||
| #include <linux/export.h> | #include <linux/export.h> | ||||||
| #include <linux/user_namespace.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; | 	return real_size; | ||||||
| } | } | ||||||
| EXPORT_SYMBOL (posix_acl_to_xattr); | 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, | int posix_acl_to_xattr(struct user_namespace *user_ns, | ||||||
| 		       const struct posix_acl *acl, void *buffer, size_t size); | 		       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 */ | #endif	/* _POSIX_ACL_XATTR_H */ | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Christoph Hellwig
				Christoph Hellwig