Skip to content

Commit

Permalink
vfs: Distinguish between full xattr names and proper prefixes
Browse files Browse the repository at this point in the history
Add an additional "name" field to struct xattr_handler.  When the name
is set, the handler matches attributes with exactly that name.  When the
prefix is set instead, the handler matches attributes with the given
prefix and with a non-empty suffix.

This patch should avoid bugs like the one fixed in commit c361016 in
the future.

Signed-off-by: Andreas Gruenbacher <[email protected]>
Reviewed-by: James Morris <[email protected]>
Signed-off-by: Al Viro <[email protected]>
  • Loading branch information
Andreas Gruenbacher authored and Al Viro committed Dec 7, 2015
1 parent 97d7929 commit 98e9cb5
Show file tree
Hide file tree
Showing 22 changed files with 47 additions and 130 deletions.
16 changes: 5 additions & 11 deletions fs/9p/acl.c
Original file line number Diff line number Diff line change
Expand Up @@ -220,15 +220,12 @@ static int v9fs_xattr_get_acl(const struct xattr_handler *handler,
struct posix_acl *acl;
int error;

if (strcmp(name, "") != 0)
return -EINVAL;

v9ses = v9fs_dentry2v9ses(dentry);
/*
* We allow set/get/list of acl when access=client is not specified
*/
if ((v9ses->flags & V9FS_ACCESS_MASK) != V9FS_ACCESS_CLIENT)
return v9fs_xattr_get(dentry, handler->prefix, buffer, size);
return v9fs_xattr_get(dentry, handler->name, buffer, size);

acl = v9fs_get_cached_acl(d_inode(dentry), handler->flags);
if (IS_ERR(acl))
Expand All @@ -250,16 +247,13 @@ static int v9fs_xattr_set_acl(const struct xattr_handler *handler,
struct v9fs_session_info *v9ses;
struct inode *inode = d_inode(dentry);

if (strcmp(name, "") != 0)
return -EINVAL;

v9ses = v9fs_dentry2v9ses(dentry);
/*
* set the attribute on the remote. Without even looking at the
* xattr value. We leave it to the server to validate
*/
if ((v9ses->flags & V9FS_ACCESS_MASK) != V9FS_ACCESS_CLIENT)
return v9fs_xattr_set(dentry, handler->prefix, value, size,
return v9fs_xattr_set(dentry, handler->name, value, size,
flags);

if (S_ISLNK(inode->i_mode))
Expand Down Expand Up @@ -319,7 +313,7 @@ static int v9fs_xattr_set_acl(const struct xattr_handler *handler,
default:
BUG();
}
retval = v9fs_xattr_set(dentry, handler->prefix, value, size, flags);
retval = v9fs_xattr_set(dentry, handler->name, value, size, flags);
if (!retval)
set_cached_acl(inode, handler->flags, acl);
err_out:
Expand All @@ -328,14 +322,14 @@ static int v9fs_xattr_set_acl(const struct xattr_handler *handler,
}

const struct xattr_handler v9fs_xattr_acl_access_handler = {
.prefix = XATTR_NAME_POSIX_ACL_ACCESS,
.name = XATTR_NAME_POSIX_ACL_ACCESS,
.flags = ACL_TYPE_ACCESS,
.get = v9fs_xattr_get_acl,
.set = v9fs_xattr_set_acl,
};

const struct xattr_handler v9fs_xattr_acl_default_handler = {
.prefix = XATTR_NAME_POSIX_ACL_DEFAULT,
.name = XATTR_NAME_POSIX_ACL_DEFAULT,
.flags = ACL_TYPE_DEFAULT,
.get = v9fs_xattr_get_acl,
.set = v9fs_xattr_set_acl,
Expand Down
4 changes: 0 additions & 4 deletions fs/9p/xattr.c
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,6 @@ static int v9fs_xattr_handler_get(const struct xattr_handler *handler,
{
const char *full_name = xattr_full_name(handler, name);

if (strcmp(name, "") == 0)
return -EINVAL;
return v9fs_xattr_get(dentry, full_name, buffer, size);
}

Expand All @@ -154,8 +152,6 @@ static int v9fs_xattr_handler_set(const struct xattr_handler *handler,
{
const char *full_name = xattr_full_name(handler, name);

if (strcmp(name, "") == 0)
return -EINVAL;
return v9fs_xattr_set(dentry, full_name, value, size, flags);
}

Expand Down
4 changes: 0 additions & 4 deletions fs/ext2/xattr_security.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@ ext2_xattr_security_get(const struct xattr_handler *handler,
struct dentry *dentry, const char *name,
void *buffer, size_t size)
{
if (strcmp(name, "") == 0)
return -EINVAL;
return ext2_xattr_get(d_inode(dentry), EXT2_XATTR_INDEX_SECURITY, name,
buffer, size);
}
Expand All @@ -39,8 +37,6 @@ ext2_xattr_security_set(const struct xattr_handler *handler,
struct dentry *dentry, const char *name,
const void *value, size_t size, int flags)
{
if (strcmp(name, "") == 0)
return -EINVAL;
return ext2_xattr_set(d_inode(dentry), EXT2_XATTR_INDEX_SECURITY, name,
value, size, flags);
}
Expand Down
4 changes: 0 additions & 4 deletions fs/ext2/xattr_trusted.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,6 @@ ext2_xattr_trusted_get(const struct xattr_handler *handler,
struct dentry *dentry, const char *name,
void *buffer, size_t size)
{
if (strcmp(name, "") == 0)
return -EINVAL;
return ext2_xattr_get(d_inode(dentry), EXT2_XATTR_INDEX_TRUSTED, name,
buffer, size);
}
Expand All @@ -43,8 +41,6 @@ ext2_xattr_trusted_set(const struct xattr_handler *handler,
struct dentry *dentry, const char *name,
const void *value, size_t size, int flags)
{
if (strcmp(name, "") == 0)
return -EINVAL;
return ext2_xattr_set(d_inode(dentry), EXT2_XATTR_INDEX_TRUSTED, name,
value, size, flags);
}
Expand Down
4 changes: 0 additions & 4 deletions fs/ext2/xattr_user.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,6 @@ ext2_xattr_user_get(const struct xattr_handler *handler,
struct dentry *dentry, const char *name,
void *buffer, size_t size)
{
if (strcmp(name, "") == 0)
return -EINVAL;
if (!test_opt(dentry->d_sb, XATTR_USER))
return -EOPNOTSUPP;
return ext2_xattr_get(d_inode(dentry), EXT2_XATTR_INDEX_USER,
Expand All @@ -47,8 +45,6 @@ ext2_xattr_user_set(const struct xattr_handler *handler,
struct dentry *dentry, const char *name,
const void *value, size_t size, int flags)
{
if (strcmp(name, "") == 0)
return -EINVAL;
if (!test_opt(dentry->d_sb, XATTR_USER))
return -EOPNOTSUPP;

Expand Down
4 changes: 0 additions & 4 deletions fs/ext4/xattr_security.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,6 @@ ext4_xattr_security_get(const struct xattr_handler *handler,
struct dentry *dentry, const char *name,
void *buffer, size_t size)
{
if (strcmp(name, "") == 0)
return -EINVAL;
return ext4_xattr_get(d_inode(dentry), EXT4_XATTR_INDEX_SECURITY,
name, buffer, size);
}
Expand All @@ -44,8 +42,6 @@ ext4_xattr_security_set(const struct xattr_handler *handler,
struct dentry *dentry, const char *name,
const void *value, size_t size, int flags)
{
if (strcmp(name, "") == 0)
return -EINVAL;
return ext4_xattr_set(d_inode(dentry), EXT4_XATTR_INDEX_SECURITY,
name, value, size, flags);
}
Expand Down
4 changes: 0 additions & 4 deletions fs/ext4/xattr_trusted.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,6 @@ ext4_xattr_trusted_get(const struct xattr_handler *handler,
struct dentry *dentry, const char *name, void *buffer,
size_t size)
{
if (strcmp(name, "") == 0)
return -EINVAL;
return ext4_xattr_get(d_inode(dentry), EXT4_XATTR_INDEX_TRUSTED,
name, buffer, size);
}
Expand All @@ -47,8 +45,6 @@ ext4_xattr_trusted_set(const struct xattr_handler *handler,
struct dentry *dentry, const char *name,
const void *value, size_t size, int flags)
{
if (strcmp(name, "") == 0)
return -EINVAL;
return ext4_xattr_set(d_inode(dentry), EXT4_XATTR_INDEX_TRUSTED,
name, value, size, flags);
}
Expand Down
4 changes: 0 additions & 4 deletions fs/ext4/xattr_user.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,6 @@ ext4_xattr_user_get(const struct xattr_handler *handler,
struct dentry *dentry, const char *name,
void *buffer, size_t size)
{
if (strcmp(name, "") == 0)
return -EINVAL;
if (!test_opt(dentry->d_sb, XATTR_USER))
return -EOPNOTSUPP;
return ext4_xattr_get(d_inode(dentry), EXT4_XATTR_INDEX_USER,
Expand All @@ -48,8 +46,6 @@ ext4_xattr_user_set(const struct xattr_handler *handler,
struct dentry *dentry, const char *name,
const void *value, size_t size, int flags)
{
if (strcmp(name, "") == 0)
return -EINVAL;
if (!test_opt(dentry->d_sb, XATTR_USER))
return -EOPNOTSUPP;
return ext4_xattr_set(d_inode(dentry), EXT4_XATTR_INDEX_USER,
Expand Down
20 changes: 6 additions & 14 deletions fs/f2fs/xattr.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ static size_t f2fs_xattr_generic_list(const struct xattr_handler *handler,
const char *name, size_t len)
{
struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb);
const char *prefix;
int total_len, prefix_len;

switch (handler->flags) {
Expand All @@ -47,10 +48,11 @@ static size_t f2fs_xattr_generic_list(const struct xattr_handler *handler,
return -EINVAL;
}

prefix_len = strlen(handler->prefix);
prefix = xattr_prefix(handler);
prefix_len = strlen(prefix);
total_len = prefix_len + len + 1;
if (list && total_len <= list_size) {
memcpy(list, handler->prefix, prefix_len);
memcpy(list, prefix, prefix_len);
memcpy(list + prefix_len, name, len);
list[prefix_len + len] = '\0';
}
Expand All @@ -77,8 +79,6 @@ static int f2fs_xattr_generic_get(const struct xattr_handler *handler,
default:
return -EINVAL;
}
if (strcmp(name, "") == 0)
return -EINVAL;
return f2fs_getxattr(d_inode(dentry), handler->flags, name,
buffer, size, NULL);
}
Expand All @@ -103,9 +103,6 @@ static int f2fs_xattr_generic_set(const struct xattr_handler *handler,
default:
return -EINVAL;
}
if (strcmp(name, "") == 0)
return -EINVAL;

return f2fs_setxattr(d_inode(dentry), handler->flags, name,
value, size, NULL, flags);
}
Expand All @@ -114,7 +111,7 @@ static size_t f2fs_xattr_advise_list(const struct xattr_handler *handler,
struct dentry *dentry, char *list, size_t list_size,
const char *name, size_t len)
{
const char *xname = F2FS_SYSTEM_ADVISE_PREFIX;
const char *xname = F2FS_SYSTEM_ADVISE_NAME;
size_t size;

size = strlen(xname) + 1;
Expand All @@ -129,9 +126,6 @@ static int f2fs_xattr_advise_get(const struct xattr_handler *handler,
{
struct inode *inode = d_inode(dentry);

if (strcmp(name, "") != 0)
return -EINVAL;

if (buffer)
*((char *)buffer) = F2FS_I(inode)->i_advise;
return sizeof(char);
Expand All @@ -143,8 +137,6 @@ static int f2fs_xattr_advise_set(const struct xattr_handler *handler,
{
struct inode *inode = d_inode(dentry);

if (strcmp(name, "") != 0)
return -EINVAL;
if (!inode_owner_or_capable(inode))
return -EPERM;
if (value == NULL)
Expand Down Expand Up @@ -197,7 +189,7 @@ const struct xattr_handler f2fs_xattr_trusted_handler = {
};

const struct xattr_handler f2fs_xattr_advise_handler = {
.prefix = F2FS_SYSTEM_ADVISE_PREFIX,
.name = F2FS_SYSTEM_ADVISE_NAME,
.flags = F2FS_XATTR_INDEX_ADVISE,
.list = f2fs_xattr_advise_list,
.get = f2fs_xattr_advise_get,
Expand Down
2 changes: 1 addition & 1 deletion fs/f2fs/xattr.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
#define F2FS_XATTR_REFCOUNT_MAX 1024

/* Name indexes */
#define F2FS_SYSTEM_ADVISE_PREFIX "system.advise"
#define F2FS_SYSTEM_ADVISE_NAME "system.advise"
#define F2FS_XATTR_INDEX_USER 1
#define F2FS_XATTR_INDEX_POSIX_ACL_ACCESS 2
#define F2FS_XATTR_INDEX_POSIX_ACL_DEFAULT 3
Expand Down
12 changes: 0 additions & 12 deletions fs/hfsplus/xattr.c
Original file line number Diff line number Diff line change
Expand Up @@ -431,9 +431,6 @@ int hfsplus_setxattr(struct dentry *dentry, const char *name,
char *xattr_name;
int res;

if (!strcmp(name, ""))
return -EINVAL;

xattr_name = kmalloc(NLS_MAX_CHARSET_SIZE * HFSPLUS_ATTR_MAX_STRLEN + 1,
GFP_KERNEL);
if (!xattr_name)
Expand Down Expand Up @@ -589,9 +586,6 @@ ssize_t hfsplus_getxattr(struct dentry *dentry, const char *name,
int res;
char *xattr_name;

if (!strcmp(name, ""))
return -EINVAL;

xattr_name = kmalloc(NLS_MAX_CHARSET_SIZE * HFSPLUS_ATTR_MAX_STRLEN + 1,
GFP_KERNEL);
if (!xattr_name)
Expand Down Expand Up @@ -853,9 +847,6 @@ static int hfsplus_osx_getxattr(const struct xattr_handler *handler,
struct dentry *dentry, const char *name,
void *buffer, size_t size)
{
if (!strcmp(name, ""))
return -EINVAL;

/*
* Don't allow retrieving properly prefixed attributes
* by prepending them with "osx."
Expand All @@ -876,9 +867,6 @@ static int hfsplus_osx_setxattr(const struct xattr_handler *handler,
struct dentry *dentry, const char *name,
const void *buffer, size_t size, int flags)
{
if (!strcmp(name, ""))
return -EINVAL;

/*
* Don't allow setting properly prefixed attributes
* by prepending them with "osx."
Expand Down
6 changes: 0 additions & 6 deletions fs/jffs2/security.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,6 @@ static int jffs2_security_getxattr(const struct xattr_handler *handler,
struct dentry *dentry, const char *name,
void *buffer, size_t size)
{
if (!strcmp(name, ""))
return -EINVAL;

return do_jffs2_getxattr(d_inode(dentry), JFFS2_XPREFIX_SECURITY,
name, buffer, size);
}
Expand All @@ -63,9 +60,6 @@ static int jffs2_security_setxattr(const struct xattr_handler *handler,
struct dentry *dentry, const char *name,
const void *buffer, size_t size, int flags)
{
if (!strcmp(name, ""))
return -EINVAL;

return do_jffs2_setxattr(d_inode(dentry), JFFS2_XPREFIX_SECURITY,
name, buffer, size, flags);
}
Expand Down
4 changes: 0 additions & 4 deletions fs/jffs2/xattr_trusted.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ static int jffs2_trusted_getxattr(const struct xattr_handler *handler,
struct dentry *dentry, const char *name,
void *buffer, size_t size)
{
if (!strcmp(name, ""))
return -EINVAL;
return do_jffs2_getxattr(d_inode(dentry), JFFS2_XPREFIX_TRUSTED,
name, buffer, size);
}
Expand All @@ -30,8 +28,6 @@ static int jffs2_trusted_setxattr(const struct xattr_handler *handler,
struct dentry *dentry, const char *name,
const void *buffer, size_t size, int flags)
{
if (!strcmp(name, ""))
return -EINVAL;
return do_jffs2_setxattr(d_inode(dentry), JFFS2_XPREFIX_TRUSTED,
name, buffer, size, flags);
}
Expand Down
4 changes: 0 additions & 4 deletions fs/jffs2/xattr_user.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ static int jffs2_user_getxattr(const struct xattr_handler *handler,
struct dentry *dentry, const char *name,
void *buffer, size_t size)
{
if (!strcmp(name, ""))
return -EINVAL;
return do_jffs2_getxattr(d_inode(dentry), JFFS2_XPREFIX_USER,
name, buffer, size);
}
Expand All @@ -30,8 +28,6 @@ static int jffs2_user_setxattr(const struct xattr_handler *handler,
struct dentry *dentry, const char *name,
const void *buffer, size_t size, int flags)
{
if (!strcmp(name, ""))
return -EINVAL;
return do_jffs2_setxattr(d_inode(dentry), JFFS2_XPREFIX_USER,
name, buffer, size, flags);
}
Expand Down
8 changes: 1 addition & 7 deletions fs/nfs/nfs4proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -6253,19 +6253,13 @@ static int nfs4_xattr_set_nfs4_acl(const struct xattr_handler *handler,
const void *buf, size_t buflen,
int flags)
{
if (strcmp(key, "") != 0)
return -EINVAL;

return nfs4_proc_set_acl(d_inode(dentry), buf, buflen);
}

static int nfs4_xattr_get_nfs4_acl(const struct xattr_handler *handler,
struct dentry *dentry, const char *key,
void *buf, size_t buflen)
{
if (strcmp(key, "") != 0)
return -EINVAL;

return nfs4_proc_get_acl(d_inode(dentry), buf, buflen);
}

Expand Down Expand Up @@ -8834,7 +8828,7 @@ const struct nfs_rpc_ops nfs_v4_clientops = {
};

static const struct xattr_handler nfs4_xattr_nfs4_acl_handler = {
.prefix = XATTR_NAME_NFSV4_ACL,
.name = XATTR_NAME_NFSV4_ACL,
.list = nfs4_xattr_list_nfs4_acl,
.get = nfs4_xattr_get_nfs4_acl,
.set = nfs4_xattr_set_nfs4_acl,
Expand Down
Loading

0 comments on commit 98e9cb5

Please sign in to comment.