lkml.org 
[lkml]   [2015]   [Sep]   [15]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 3.4 022/146] btrfs: don't accept bare namespace as a valid xattr
    Date
    From: David Sterba <dsterba@suse.cz>

    3.4.109-rc1 review patch. If anyone has any objections, please let me know.

    ------------------


    commit 3c3b04d10ff1811a27f86684ccd2f5ba6983211d upstream.

    Due to insufficient check in btrfs_is_valid_xattr, this unexpectedly
    works:

    $ touch file
    $ setfattr -n user. -v 1 file
    $ getfattr -d file
    user.="1"

    ie. the missing attribute name after the namespace.

    Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=94291
    Reported-by: William Douglas <william.douglas@intel.com>
    Signed-off-by: David Sterba <dsterba@suse.cz>
    Signed-off-by: Chris Mason <clm@fb.com>
    [lizf: Backported to 3.4:
    - 3.4 doesn't support XATTR_BTRFS_PREFIX]
    Signed-off-by: Zefan Li <lizefan@huawei.com>
    ---
    fs/btrfs/xattr.c | 50 +++++++++++++++++++++++++++++++++++++-------------
    1 file changed, 37 insertions(+), 13 deletions(-)

    diff --git a/fs/btrfs/xattr.c b/fs/btrfs/xattr.c
    index e7a5659..0ee73d1 100644
    --- a/fs/btrfs/xattr.c
    +++ b/fs/btrfs/xattr.c
    @@ -310,21 +310,40 @@ const struct xattr_handler *btrfs_xattr_handlers[] = {
    /*
    * Check if the attribute is in a supported namespace.
    *
    - * This applied after the check for the synthetic attributes in the system
    + * This is applied after the check for the synthetic attributes in the system
    * namespace.
    */
    -static bool btrfs_is_valid_xattr(const char *name)
    +static int btrfs_is_valid_xattr(const char *name)
    {
    - return !strncmp(name, XATTR_SECURITY_PREFIX,
    - XATTR_SECURITY_PREFIX_LEN) ||
    - !strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN) ||
    - !strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) ||
    - !strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN);
    + int len = strlen(name);
    + int prefixlen = 0;
    +
    + if (!strncmp(name, XATTR_SECURITY_PREFIX,
    + XATTR_SECURITY_PREFIX_LEN))
    + prefixlen = XATTR_SECURITY_PREFIX_LEN;
    + else if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
    + prefixlen = XATTR_SYSTEM_PREFIX_LEN;
    + else if (!strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN))
    + prefixlen = XATTR_TRUSTED_PREFIX_LEN;
    + else if (!strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN))
    + prefixlen = XATTR_USER_PREFIX_LEN;
    + else
    + return -EOPNOTSUPP;
    +
    + /*
    + * The name cannot consist of just prefix
    + */
    + if (len <= prefixlen)
    + return -EINVAL;
    +
    + return 0;
    }

    ssize_t btrfs_getxattr(struct dentry *dentry, const char *name,
    void *buffer, size_t size)
    {
    + int ret;
    +
    /*
    * If this is a request for a synthetic attribute in the system.*
    * namespace use the generic infrastructure to resolve a handler
    @@ -333,8 +352,9 @@ ssize_t btrfs_getxattr(struct dentry *dentry, const char *name,
    if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
    return generic_getxattr(dentry, name, buffer, size);

    - if (!btrfs_is_valid_xattr(name))
    - return -EOPNOTSUPP;
    + ret = btrfs_is_valid_xattr(name);
    + if (ret)
    + return ret;
    return __btrfs_getxattr(dentry->d_inode, name, buffer, size);
    }

    @@ -342,6 +362,7 @@ int btrfs_setxattr(struct dentry *dentry, const char *name, const void *value,
    size_t size, int flags)
    {
    struct btrfs_root *root = BTRFS_I(dentry->d_inode)->root;
    + int ret;

    /*
    * The permission on security.* and system.* is not checked
    @@ -358,8 +379,9 @@ int btrfs_setxattr(struct dentry *dentry, const char *name, const void *value,
    if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
    return generic_setxattr(dentry, name, value, size, flags);

    - if (!btrfs_is_valid_xattr(name))
    - return -EOPNOTSUPP;
    + ret = btrfs_is_valid_xattr(name);
    + if (ret)
    + return ret;

    if (size == 0)
    value = ""; /* empty EA, do not remove */
    @@ -371,6 +393,7 @@ int btrfs_setxattr(struct dentry *dentry, const char *name, const void *value,
    int btrfs_removexattr(struct dentry *dentry, const char *name)
    {
    struct btrfs_root *root = BTRFS_I(dentry->d_inode)->root;
    + int ret;

    /*
    * The permission on security.* and system.* is not checked
    @@ -387,8 +410,9 @@ int btrfs_removexattr(struct dentry *dentry, const char *name)
    if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
    return generic_removexattr(dentry, name);

    - if (!btrfs_is_valid_xattr(name))
    - return -EOPNOTSUPP;
    + ret = btrfs_is_valid_xattr(name);
    + if (ret)
    + return ret;

    return __btrfs_setxattr(NULL, dentry->d_inode, name, NULL, 0,
    XATTR_REPLACE);
    --
    1.9.1


    \
     
     \ /
      Last update: 2015-09-15 11:21    [W:4.834 / U:1.320 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site