mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	VFS: Factor out part of vfs_setxattr so it can be called from the SELinux hook for inode_setsecctx.
This factors out the part of the vfs_setxattr function that performs the setting of the xattr and its notification. This is needed so the SELinux implementation of inode_setsecctx can handle the setting of the xattr while maintaining the proper separation of layers. Signed-off-by: David P. Quigley <dpquigl@tycho.nsa.gov> Acked-by: Serge Hallyn <serue@us.ibm.com> Signed-off-by: James Morris <jmorris@namei.org>
This commit is contained in:
		
							parent
							
								
									733e5e4b4e
								
							
						
					
					
						commit
						b1ab7e4b2a
					
				
					 2 changed files with 43 additions and 13 deletions
				
			
		
							
								
								
									
										55
									
								
								fs/xattr.c
									
									
									
									
									
								
							
							
						
						
									
										55
									
								
								fs/xattr.c
									
									
									
									
									
								
							| 
						 | 
					@ -66,22 +66,28 @@ xattr_permission(struct inode *inode, const char *name, int mask)
 | 
				
			||||||
	return inode_permission(inode, mask);
 | 
						return inode_permission(inode, mask);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int
 | 
					/**
 | 
				
			||||||
vfs_setxattr(struct dentry *dentry, const char *name, const void *value,
 | 
					 *  __vfs_setxattr_noperm - perform setxattr operation without performing
 | 
				
			||||||
		size_t size, int flags)
 | 
					 *  permission checks.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *  @dentry - object to perform setxattr on
 | 
				
			||||||
 | 
					 *  @name - xattr name to set
 | 
				
			||||||
 | 
					 *  @value - value to set @name to
 | 
				
			||||||
 | 
					 *  @size - size of @value
 | 
				
			||||||
 | 
					 *  @flags - flags to pass into filesystem operations
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *  returns the result of the internal setxattr or setsecurity operations.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *  This function requires the caller to lock the inode's i_mutex before it
 | 
				
			||||||
 | 
					 *  is executed. It also assumes that the caller will make the appropriate
 | 
				
			||||||
 | 
					 *  permission checks.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int __vfs_setxattr_noperm(struct dentry *dentry, const char *name,
 | 
				
			||||||
 | 
							const void *value, size_t size, int flags)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct inode *inode = dentry->d_inode;
 | 
						struct inode *inode = dentry->d_inode;
 | 
				
			||||||
	int error;
 | 
						int error = -EOPNOTSUPP;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	error = xattr_permission(inode, name, MAY_WRITE);
 | 
					 | 
				
			||||||
	if (error)
 | 
					 | 
				
			||||||
		return error;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	mutex_lock(&inode->i_mutex);
 | 
					 | 
				
			||||||
	error = security_inode_setxattr(dentry, name, value, size, flags);
 | 
					 | 
				
			||||||
	if (error)
 | 
					 | 
				
			||||||
		goto out;
 | 
					 | 
				
			||||||
	error = -EOPNOTSUPP;
 | 
					 | 
				
			||||||
	if (inode->i_op->setxattr) {
 | 
						if (inode->i_op->setxattr) {
 | 
				
			||||||
		error = inode->i_op->setxattr(dentry, name, value, size, flags);
 | 
							error = inode->i_op->setxattr(dentry, name, value, size, flags);
 | 
				
			||||||
		if (!error) {
 | 
							if (!error) {
 | 
				
			||||||
| 
						 | 
					@ -97,6 +103,29 @@ vfs_setxattr(struct dentry *dentry, const char *name, const void *value,
 | 
				
			||||||
		if (!error)
 | 
							if (!error)
 | 
				
			||||||
			fsnotify_xattr(dentry);
 | 
								fsnotify_xattr(dentry);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return error;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int
 | 
				
			||||||
 | 
					vfs_setxattr(struct dentry *dentry, const char *name, const void *value,
 | 
				
			||||||
 | 
							size_t size, int flags)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct inode *inode = dentry->d_inode;
 | 
				
			||||||
 | 
						int error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						error = xattr_permission(inode, name, MAY_WRITE);
 | 
				
			||||||
 | 
						if (error)
 | 
				
			||||||
 | 
							return error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mutex_lock(&inode->i_mutex);
 | 
				
			||||||
 | 
						error = security_inode_setxattr(dentry, name, value, size, flags);
 | 
				
			||||||
 | 
						if (error)
 | 
				
			||||||
 | 
							goto out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						error = __vfs_setxattr_noperm(dentry, name, value, size, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
out:
 | 
					out:
 | 
				
			||||||
	mutex_unlock(&inode->i_mutex);
 | 
						mutex_unlock(&inode->i_mutex);
 | 
				
			||||||
	return error;
 | 
						return error;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -49,6 +49,7 @@ struct xattr_handler {
 | 
				
			||||||
ssize_t xattr_getsecurity(struct inode *, const char *, void *, size_t);
 | 
					ssize_t xattr_getsecurity(struct inode *, const char *, void *, size_t);
 | 
				
			||||||
ssize_t vfs_getxattr(struct dentry *, const char *, void *, size_t);
 | 
					ssize_t vfs_getxattr(struct dentry *, const char *, void *, size_t);
 | 
				
			||||||
ssize_t vfs_listxattr(struct dentry *d, char *list, size_t size);
 | 
					ssize_t vfs_listxattr(struct dentry *d, char *list, size_t size);
 | 
				
			||||||
 | 
					int __vfs_setxattr_noperm(struct dentry *, const char *, const void *, size_t, int);
 | 
				
			||||||
int vfs_setxattr(struct dentry *, const char *, const void *, size_t, int);
 | 
					int vfs_setxattr(struct dentry *, const char *, const void *, size_t, int);
 | 
				
			||||||
int vfs_removexattr(struct dentry *, const char *);
 | 
					int vfs_removexattr(struct dentry *, const char *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue