xattr: Fix setting security xattrs on sockfs
The IOP_XATTR flag is set on sockfs because sockfs supports getting the
"system.sockprotoname" xattr. Since commit 6c6ef9f2
, this flag is checked for
setxattr support as well. This is wrong on sockfs because security xattr
support there is supposed to be provided by security_inode_setsecurity. The
smack security module relies on socket labels (xattrs).
Fix this by adding a security xattr handler on sockfs that returns
-EAGAIN, and by checking for -EAGAIN in setxattr.
We cannot simply check for -EOPNOTSUPP in setxattr because there are
filesystems that neither have direct security xattr support nor support
via security_inode_setsecurity. A more proper fix might be to move the
call to security_inode_setsecurity into sockfs, but it's not clear to me
if that is safe: we would end up calling security_inode_post_setxattr after
that as well.
Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
961b708e95
commit
4a59015372
22
fs/xattr.c
22
fs/xattr.c
|
@ -170,7 +170,7 @@ int __vfs_setxattr_noperm(struct dentry *dentry, const char *name,
|
||||||
const void *value, size_t size, int flags)
|
const void *value, size_t size, int flags)
|
||||||
{
|
{
|
||||||
struct inode *inode = dentry->d_inode;
|
struct inode *inode = dentry->d_inode;
|
||||||
int error = -EOPNOTSUPP;
|
int error = -EAGAIN;
|
||||||
int issec = !strncmp(name, XATTR_SECURITY_PREFIX,
|
int issec = !strncmp(name, XATTR_SECURITY_PREFIX,
|
||||||
XATTR_SECURITY_PREFIX_LEN);
|
XATTR_SECURITY_PREFIX_LEN);
|
||||||
|
|
||||||
|
@ -183,15 +183,21 @@ int __vfs_setxattr_noperm(struct dentry *dentry, const char *name,
|
||||||
security_inode_post_setxattr(dentry, name, value,
|
security_inode_post_setxattr(dentry, name, value,
|
||||||
size, flags);
|
size, flags);
|
||||||
}
|
}
|
||||||
} else if (issec) {
|
} else {
|
||||||
const char *suffix = name + XATTR_SECURITY_PREFIX_LEN;
|
|
||||||
|
|
||||||
if (unlikely(is_bad_inode(inode)))
|
if (unlikely(is_bad_inode(inode)))
|
||||||
return -EIO;
|
return -EIO;
|
||||||
error = security_inode_setsecurity(inode, suffix, value,
|
}
|
||||||
size, flags);
|
if (error == -EAGAIN) {
|
||||||
if (!error)
|
error = -EOPNOTSUPP;
|
||||||
fsnotify_xattr(dentry);
|
|
||||||
|
if (issec) {
|
||||||
|
const char *suffix = name + XATTR_SECURITY_PREFIX_LEN;
|
||||||
|
|
||||||
|
error = security_inode_setsecurity(inode, suffix, value,
|
||||||
|
size, flags);
|
||||||
|
if (!error)
|
||||||
|
fsnotify_xattr(dentry);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
|
|
15
net/socket.c
15
net/socket.c
|
@ -341,8 +341,23 @@ static const struct xattr_handler sockfs_xattr_handler = {
|
||||||
.get = sockfs_xattr_get,
|
.get = sockfs_xattr_get,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int sockfs_security_xattr_set(const struct xattr_handler *handler,
|
||||||
|
struct dentry *dentry, struct inode *inode,
|
||||||
|
const char *suffix, const void *value,
|
||||||
|
size_t size, int flags)
|
||||||
|
{
|
||||||
|
/* Handled by LSM. */
|
||||||
|
return -EAGAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct xattr_handler sockfs_security_xattr_handler = {
|
||||||
|
.prefix = XATTR_SECURITY_PREFIX,
|
||||||
|
.set = sockfs_security_xattr_set,
|
||||||
|
};
|
||||||
|
|
||||||
static const struct xattr_handler *sockfs_xattr_handlers[] = {
|
static const struct xattr_handler *sockfs_xattr_handlers[] = {
|
||||||
&sockfs_xattr_handler,
|
&sockfs_xattr_handler,
|
||||||
|
&sockfs_security_xattr_handler,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue