lkml.org 
[lkml]   [2016]   [Jan]   [27]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.2.y-ckt 003/268] ovl: use a minimal buffer in ovl_copy_xattr
    Date
    4.2.8-ckt3 -stable review patch.  If anyone has any objections, please let me know.

    ---8<------------------------------------------------------------

    From: Vito Caputo <vito.caputo@coreos.com>

    commit e4ad29fa0d224d05e08b2858e65f112fd8edd4fe upstream.

    Rather than always allocating the high-order XATTR_SIZE_MAX buffer
    which is costly and prone to failure, only allocate what is needed and
    realloc if necessary.

    Fixes https://github.com/coreos/bugs/issues/489

    Signed-off-by: Miklos Szeredi <miklos@szeredi.hu>
    Signed-off-by: Kamal Mostafa <kamal@canonical.com>
    ---
    fs/overlayfs/copy_up.c | 39 +++++++++++++++++++++++++--------------
    1 file changed, 25 insertions(+), 14 deletions(-)

    diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c
    index 394e87f..758012b 100644
    --- a/fs/overlayfs/copy_up.c
    +++ b/fs/overlayfs/copy_up.c
    @@ -22,9 +22,9 @@

    int ovl_copy_xattr(struct dentry *old, struct dentry *new)
    {
    - ssize_t list_size, size;
    - char *buf, *name, *value;
    - int error;
    + ssize_t list_size, size, value_size = 0;
    + char *buf, *name, *value = NULL;
    + int uninitialized_var(error);

    if (!old->d_inode->i_op->getxattr ||
    !new->d_inode->i_op->getxattr)
    @@ -41,29 +41,40 @@ int ovl_copy_xattr(struct dentry *old, struct dentry *new)
    if (!buf)
    return -ENOMEM;

    - error = -ENOMEM;
    - value = kmalloc(XATTR_SIZE_MAX, GFP_KERNEL);
    - if (!value)
    - goto out;
    -
    list_size = vfs_listxattr(old, buf, list_size);
    if (list_size <= 0) {
    error = list_size;
    - goto out_free_value;
    + goto out;
    }

    for (name = buf; name < (buf + list_size); name += strlen(name) + 1) {
    - size = vfs_getxattr(old, name, value, XATTR_SIZE_MAX);
    +retry:
    + size = vfs_getxattr(old, name, value, value_size);
    + if (size == -ERANGE)
    + size = vfs_getxattr(old, name, NULL, 0);
    +
    if (size < 0) {
    error = size;
    - goto out_free_value;
    + break;
    + }
    +
    + if (size > value_size) {
    + void *new;
    +
    + new = krealloc(value, size, GFP_KERNEL);
    + if (!new) {
    + error = -ENOMEM;
    + break;
    + }
    + value = new;
    + value_size = size;
    + goto retry;
    }
    +
    error = vfs_setxattr(new, name, value, size, 0);
    if (error)
    - goto out_free_value;
    + break;
    }
    -
    -out_free_value:
    kfree(value);
    out:
    kfree(buf);
    --
    1.9.1
    \
     
     \ /
      Last update: 2016-01-27 23:21    [W:2.473 / U:0.008 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site