Commit b1ab7e4b authored by David P. Quigley's avatar David P. Quigley Committed by James Morris

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: default avatarDavid P. Quigley <dpquigl@tycho.nsa.gov>
Acked-by: default avatarSerge Hallyn <serue@us.ibm.com>
Signed-off-by: default avatarJames Morris <jmorris@namei.org>
parent 733e5e4b
...@@ -66,22 +66,28 @@ xattr_permission(struct inode *inode, const char *name, int mask) ...@@ -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, ...@@ -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 { ...@@ -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 *);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment