lkml.org 
[lkml]   [2010]   [Aug]   [11]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[035/111] jfs: dont allow os2 xattr namespace overlap with others
    2.6.32-stable review patch.  If anyone has any objections, please let us know.

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

    From: Dave Kleikamp <shaggy@linux.vnet.ibm.com>

    commit aca0fa34bdaba39bfddddba8ca70dba4782e8fe6 upstream.

    It's currently possible to bypass xattr namespace access rules by
    prefixing valid xattr names with "os2.", since the os2 namespace stores
    extended attributes in a legacy format with no prefix.

    This patch adds checking to deny access to any valid namespace prefix
    following "os2.".

    Signed-off-by: Dave Kleikamp <shaggy@linux.vnet.ibm.com>
    Reported-by: Sergey Vlasov <vsu@altlinux.ru>
    Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
    Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

    ---
    fs/jfs/xattr.c | 87 ++++++++++++++++++++++++---------------------------------
    1 file changed, 38 insertions(+), 49 deletions(-)

    --- a/fs/jfs/xattr.c
    +++ b/fs/jfs/xattr.c
    @@ -85,46 +85,25 @@ struct ea_buffer {
    #define EA_MALLOC 0x0008


    +static int is_known_namespace(const char *name)
    +{
    + if (strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN) &&
    + strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN) &&
    + strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) &&
    + strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN))
    + return false;
    +
    + return true;
    +}
    +
    /*
    * These three routines are used to recognize on-disk extended attributes
    * that are in a recognized namespace. If the attribute is not recognized,
    * "os2." is prepended to the name
    */
    -static inline int is_os2_xattr(struct jfs_ea *ea)
    +static int is_os2_xattr(struct jfs_ea *ea)
    {
    - /*
    - * Check for "system."
    - */
    - if ((ea->namelen >= XATTR_SYSTEM_PREFIX_LEN) &&
    - !strncmp(ea->name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
    - return false;
    - /*
    - * Check for "user."
    - */
    - if ((ea->namelen >= XATTR_USER_PREFIX_LEN) &&
    - !strncmp(ea->name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN))
    - return false;
    - /*
    - * Check for "security."
    - */
    - if ((ea->namelen >= XATTR_SECURITY_PREFIX_LEN) &&
    - !strncmp(ea->name, XATTR_SECURITY_PREFIX,
    - XATTR_SECURITY_PREFIX_LEN))
    - return false;
    - /*
    - * Check for "trusted."
    - */
    - if ((ea->namelen >= XATTR_TRUSTED_PREFIX_LEN) &&
    - !strncmp(ea->name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN))
    - return false;
    - /*
    - * Add any other valid namespace prefixes here
    - */
    -
    - /*
    - * We assume it's OS/2's flat namespace
    - */
    - return true;
    + return !is_known_namespace(ea->name);
    }

    static inline int name_size(struct jfs_ea *ea)
    @@ -762,13 +741,23 @@ static int can_set_xattr(struct inode *i
    if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
    return can_set_system_xattr(inode, name, value, value_len);

    + if (!strncmp(name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN)) {
    + /*
    + * This makes sure that we aren't trying to set an
    + * attribute in a different namespace by prefixing it
    + * with "os2."
    + */
    + if (is_known_namespace(name + XATTR_OS2_PREFIX_LEN))
    + return -EOPNOTSUPP;
    + return 0;
    + }
    +
    /*
    * Don't allow setting an attribute in an unknown namespace.
    */
    if (strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) &&
    strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) &&
    - strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN) &&
    - strncmp(name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN))
    + strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN))
    return -EOPNOTSUPP;

    return 0;
    @@ -950,19 +939,8 @@ ssize_t __jfs_getxattr(struct inode *ino
    int xattr_size;
    ssize_t size;
    int namelen = strlen(name);
    - char *os2name = NULL;
    char *value;

    - if (strncmp(name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) == 0) {
    - os2name = kmalloc(namelen - XATTR_OS2_PREFIX_LEN + 1,
    - GFP_KERNEL);
    - if (!os2name)
    - return -ENOMEM;
    - strcpy(os2name, name + XATTR_OS2_PREFIX_LEN);
    - name = os2name;
    - namelen -= XATTR_OS2_PREFIX_LEN;
    - }
    -
    down_read(&JFS_IP(inode)->xattr_sem);

    xattr_size = ea_get(inode, &ea_buf, 0);
    @@ -1000,8 +978,6 @@ ssize_t __jfs_getxattr(struct inode *ino
    out:
    up_read(&JFS_IP(inode)->xattr_sem);

    - kfree(os2name);
    -
    return size;
    }

    @@ -1010,6 +986,19 @@ ssize_t jfs_getxattr(struct dentry *dent
    {
    int err;

    + if (strncmp(name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) == 0) {
    + /*
    + * skip past "os2." prefix
    + */
    + name += XATTR_OS2_PREFIX_LEN;
    + /*
    + * Don't allow retrieving properly prefixed attributes
    + * by prepending them with "os2."
    + */
    + if (is_known_namespace(name))
    + return -EOPNOTSUPP;
    + }
    +
    err = __jfs_getxattr(dentry->d_inode, name, data, buf_size);

    return err;



    \
     
     \ /
      Last update: 2010-08-12 02:45    [W:0.037 / U:0.312 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site