aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRonnie Sahlberg <lsahlber@redhat.com>2017-08-23 00:48:14 -0400
committerSteve French <smfrench@gmail.com>2017-08-23 14:34:52 -0400
commitd3edede29f74d335f81d95a4588f5f136a9f7dcf (patch)
tree391465f2a1f199a8e5b789faca7556dac3b1ecc9
parent42bec214d8bd432be6d32a1acb0a9079ecd4d142 (diff)
cifs: return ENAMETOOLONG for overlong names in cifs_open()/cifs_lookup()
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> Cc: <stable@vger.kernel.org>
-rw-r--r--fs/cifs/dir.c18
1 files changed, 12 insertions, 6 deletions
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 56366e984076..569d3fb736be 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -194,15 +194,20 @@ cifs_bp_rename_retry:
194} 194}
195 195
196/* 196/*
197 * Don't allow path components longer than the server max.
197 * Don't allow the separator character in a path component. 198 * Don't allow the separator character in a path component.
198 * The VFS will not allow "/", but "\" is allowed by posix. 199 * The VFS will not allow "/", but "\" is allowed by posix.
199 */ 200 */
200static int 201static int
201check_name(struct dentry *direntry) 202check_name(struct dentry *direntry, struct cifs_tcon *tcon)
202{ 203{
203 struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb); 204 struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
204 int i; 205 int i;
205 206
207 if (unlikely(direntry->d_name.len >
208 tcon->fsAttrInfo.MaxPathNameComponentLength))
209 return -ENAMETOOLONG;
210
206 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)) { 211 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)) {
207 for (i = 0; i < direntry->d_name.len; i++) { 212 for (i = 0; i < direntry->d_name.len; i++) {
208 if (direntry->d_name.name[i] == '\\') { 213 if (direntry->d_name.name[i] == '\\') {
@@ -500,10 +505,6 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry,
500 return finish_no_open(file, res); 505 return finish_no_open(file, res);
501 } 506 }
502 507
503 rc = check_name(direntry);
504 if (rc)
505 return rc;
506
507 xid = get_xid(); 508 xid = get_xid();
508 509
509 cifs_dbg(FYI, "parent inode = 0x%p name is: %pd and dentry = 0x%p\n", 510 cifs_dbg(FYI, "parent inode = 0x%p name is: %pd and dentry = 0x%p\n",
@@ -516,6 +517,11 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry,
516 } 517 }
517 518
518 tcon = tlink_tcon(tlink); 519 tcon = tlink_tcon(tlink);
520
521 rc = check_name(direntry, tcon);
522 if (rc)
523 goto out_free_xid;
524
519 server = tcon->ses->server; 525 server = tcon->ses->server;
520 526
521 if (server->ops->new_lease_key) 527 if (server->ops->new_lease_key)
@@ -776,7 +782,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
776 } 782 }
777 pTcon = tlink_tcon(tlink); 783 pTcon = tlink_tcon(tlink);
778 784
779 rc = check_name(direntry); 785 rc = check_name(direntry, pTcon);
780 if (rc) 786 if (rc)
781 goto lookup_out; 787 goto lookup_out;
782 788