lkml.org 
[lkml]   [2017]   [Nov]   [6]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Date
    Subject[PATCH 3.16 134/294] cifs: return ENAMETOOLONG for overlong names in cifs_open()/cifs_lookup()
    3.16.50-rc1 review patch.  If anyone has any objections, please let me know.

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

    From: Ronnie Sahlberg <lsahlber@redhat.com>

    commit d3edede29f74d335f81d95a4588f5f136a9f7dcf upstream.

    Add checking for the path component length and verify it is <= the maximum
    that the server advertizes via FileFsAttributeInformation.

    With this patch cifs.ko will now return ENAMETOOLONG instead of ENOENT
    when users to access an overlong path.

    To test this, try to cd into a (non-existing) directory on a CIFS share
    that has a too long name:
    cd /mnt/aaaaaaaaaaaaaaa...

    and it now should show a good error message from the shell:
    bash: cd: /mnt/aaaaaaaaaaaaaaaa...aaaaaa: File name too long

    rh bz 1153996

    Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com>
    Signed-off-by: Steve French <smfrench@gmail.com>
    Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
    ---
    fs/cifs/dir.c | 18 ++++++++++++------
    1 file changed, 12 insertions(+), 6 deletions(-)

    --- a/fs/cifs/dir.c
    +++ b/fs/cifs/dir.c
    @@ -183,15 +183,20 @@ cifs_bp_rename_retry:
    }

    /*
    + * Don't allow path components longer than the server max.
    * Don't allow the separator character in a path component.
    * The VFS will not allow "/", but "\" is allowed by posix.
    */
    static int
    -check_name(struct dentry *direntry)
    +check_name(struct dentry *direntry, struct cifs_tcon *tcon)
    {
    struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
    int i;

    + if (unlikely(direntry->d_name.len >
    + tcon->fsAttrInfo.MaxPathNameComponentLength))
    + return -ENAMETOOLONG;
    +
    if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)) {
    for (i = 0; i < direntry->d_name.len; i++) {
    if (direntry->d_name.name[i] == '\\') {
    @@ -489,10 +494,6 @@ cifs_atomic_open(struct inode *inode, st
    return finish_no_open(file, res);
    }

    - rc = check_name(direntry);
    - if (rc)
    - return rc;
    -
    xid = get_xid();

    cifs_dbg(FYI, "parent inode = 0x%p name is: %s and dentry = 0x%p\n",
    @@ -505,6 +506,11 @@ cifs_atomic_open(struct inode *inode, st
    }

    tcon = tlink_tcon(tlink);
    +
    + rc = check_name(direntry, tcon);
    + if (rc)
    + goto out_free_xid;
    +
    server = tcon->ses->server;

    if (server->ops->new_lease_key)
    @@ -752,7 +758,7 @@ cifs_lookup(struct inode *parent_dir_ino
    }
    pTcon = tlink_tcon(tlink);

    - rc = check_name(direntry);
    + rc = check_name(direntry, pTcon);
    if (rc)
    goto lookup_out;

    \
     
     \ /
      Last update: 2017-11-08 20:58    [W:4.073 / U:0.012 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site