From 3e715513643f0207c8f3c22010b54954cd697474 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Mon, 13 Jun 2011 11:50:41 -0400 Subject: cifs: show sec= option in /proc/mounts Signed-off-by: Jeff Layton Signed-off-by: Steve French --- fs/cifs/cifsfs.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) (limited to 'fs/cifs/cifsfs.c') diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 989442dcfb45..e9def996e383 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -352,6 +352,37 @@ cifs_show_address(struct seq_file *s, struct TCP_Server_Info *server) } } +static void +cifs_show_security(struct seq_file *s, struct TCP_Server_Info *server) +{ + seq_printf(s, ",sec="); + + switch (server->secType) { + case LANMAN: + seq_printf(s, "lanman"); + break; + case NTLMv2: + seq_printf(s, "ntlmv2"); + break; + case NTLM: + seq_printf(s, "ntlm"); + break; + case Kerberos: + seq_printf(s, "krb5"); + break; + case RawNTLMSSP: + seq_printf(s, "ntlmssp"); + break; + default: + /* shouldn't ever happen */ + seq_printf(s, "unknown"); + break; + } + + if (server->sec_mode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) + seq_printf(s, "i"); +} + /* * cifs_show_options() is for displaying mount options in /proc/mounts. * Not all settable options are displayed but most of the important @@ -365,6 +396,8 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m) struct sockaddr *srcaddr; srcaddr = (struct sockaddr *)&tcon->ses->server->srcaddr; + cifs_show_security(s, tcon->ses->server); + seq_printf(s, ",unc=%s", tcon->treeName); if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER) -- cgit v1.2.1 From ec12781f192568f7ea860f440f890389ba393df7 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 18 Jun 2011 20:03:36 -0400 Subject: cifs_permission() doesn't need to bail out in RCU mode nothing potentially blocking except generic_permission(), which will DTRT Signed-off-by: Al Viro --- fs/cifs/cifsfs.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'fs/cifs/cifsfs.c') diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index e9def996e383..2f0c58646c10 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -257,9 +257,6 @@ static int cifs_permission(struct inode *inode, int mask, unsigned int flags) { struct cifs_sb_info *cifs_sb; - if (flags & IPERM_FLAG_RCU) - return -ECHILD; - cifs_sb = CIFS_SB(inode->i_sb); if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) { -- cgit v1.2.1 From dd8544661947ad6d8d87b3c9d4333bfa1583d1bc Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 17 Jun 2011 08:24:42 -0400 Subject: take bdi setup/destruction into cifs_mount/cifs_umount Acked-by: Pavel Shilovsky Reviewed-by: Jeff Layton Signed-off-by: Al Viro --- fs/cifs/cifsfs.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) (limited to 'fs/cifs/cifsfs.c') diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 2f0c58646c10..5d3c4fa4b546 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -116,18 +116,12 @@ cifs_read_super(struct super_block *sb, struct smb_vol *volume_info, spin_lock_init(&cifs_sb->tlink_tree_lock); cifs_sb->tlink_tree = RB_ROOT; - rc = bdi_setup_and_register(&cifs_sb->bdi, "cifs", BDI_CAP_MAP_COPY); - if (rc) - return rc; - - cifs_sb->bdi.ra_pages = default_backing_dev_info.ra_pages; - rc = cifs_mount(sb, cifs_sb, volume_info, devname); if (rc) { if (!silent) cERROR(1, "cifs_mount failed w/return code = %d", rc); - goto out_mount_failed; + return rc; } sb->s_magic = CIFS_MAGIC_NUMBER; @@ -171,9 +165,6 @@ out_no_root: iput(inode); cifs_umount(sb, cifs_sb); - -out_mount_failed: - bdi_destroy(&cifs_sb->bdi); return rc; } @@ -199,7 +190,6 @@ cifs_put_super(struct super_block *sb) } unload_nls(cifs_sb->local_nls); - bdi_destroy(&cifs_sb->bdi); kfree(cifs_sb); } -- cgit v1.2.1 From 6d6861757dfadb7d6aec6bb34acd471210a755f9 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 17 Jun 2011 08:34:57 -0400 Subject: cifs: double free on mount failure if we get to out_super with ->s_root already set (e.g. with cifs_get_root() failure), we'll end up with cifs_put_super() called and ->mountdata freed twice. We'll also get cifs_sb freed twice and cifs_sb->local_nls dropped twice. The problem is, we can get to out_super both with and without ->s_root, which makes ->put_super() a bad place for such work. Switch to ->kill_sb(), have all that work done there after kill_anon_super(). Unlike ->put_super(), ->kill_sb() is called by deactivate_locked_super() whether we have ->s_root or not. Acked-by: Pavel Shilovsky Reviewed-by: Jeff Layton Signed-off-by: Al Viro --- fs/cifs/cifsfs.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'fs/cifs/cifsfs.c') diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 5d3c4fa4b546..dc76c7bccb15 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -184,11 +184,13 @@ cifs_put_super(struct super_block *sb) rc = cifs_umount(sb, cifs_sb); if (rc) cERROR(1, "cifs_umount failed with return code %d", rc); - if (cifs_sb->mountdata) { - kfree(cifs_sb->mountdata); - cifs_sb->mountdata = NULL; - } +} +static void cifs_kill_sb(struct super_block *sb) +{ + struct cifs_sb_info *cifs_sb = CIFS_SB(sb); + kill_anon_super(sb); + kfree(cifs_sb->mountdata); unload_nls(cifs_sb->local_nls); kfree(cifs_sb); } @@ -729,8 +731,8 @@ out_shared: goto out; out_super: - kfree(cifs_sb->mountdata); deactivate_locked_super(sb); + goto out; out_cifs_sb: unload_nls(cifs_sb->local_nls); @@ -827,7 +829,7 @@ struct file_system_type cifs_fs_type = { .owner = THIS_MODULE, .name = "cifs", .mount = cifs_do_mount, - .kill_sb = kill_anon_super, + .kill_sb = cifs_kill_sb, /* .fs_flags */ }; const struct inode_operations cifs_dir_inode_ops = { -- cgit v1.2.1 From ca171baaad1420a29cca98be5bdf5596cd70b294 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 17 Jun 2011 08:49:12 -0400 Subject: cifs: don't leak nls on mount failure if cifs_sb allocation fails, we still need to drop nls we'd stashed into volume_info - the one we would've copied to cifs_sb if we could allocate the latter. Acked-by: Pavel Shilovsky Reviewed-by: Jeff Layton Signed-off-by: Al Viro --- fs/cifs/cifsfs.c | 1 + 1 file changed, 1 insertion(+) (limited to 'fs/cifs/cifsfs.c') diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index dc76c7bccb15..bfab2bc83726 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -672,6 +672,7 @@ cifs_do_mount(struct file_system_type *fs_type, cifs_sb = kzalloc(sizeof(struct cifs_sb_info), GFP_KERNEL); if (cifs_sb == NULL) { root = ERR_PTR(-ENOMEM); + unload_nls(volume_info->local_nls); goto out; } -- cgit v1.2.1 From 2c6292ae4be00454882246d07f38cdf15a823c2a Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 17 Jun 2011 09:05:48 -0400 Subject: cifs: don't pass superblock to cifs_mount() To close sget() races we'll need to be able to set cifs_sb up before we get the superblock, so we'll want to be able to do cifs_mount() earlier. Fortunately, it's easy to do - setting ->s_maxbytes can be done in cifs_read_super(), ditto for ->s_time_gran and as for putting MS_POSIXACL into ->s_flags, we can mirror it in ->mnt_cifs_flags until cifs_read_super() is called. Kill unused 'devname' argument, while we are at it... Acked-by: Pavel Shilovsky Reviewed-by: Jeff Layton Signed-off-by: Al Viro --- fs/cifs/cifsfs.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'fs/cifs/cifsfs.c') diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index bfab2bc83726..8f7451f3c8e6 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -116,7 +116,7 @@ cifs_read_super(struct super_block *sb, struct smb_vol *volume_info, spin_lock_init(&cifs_sb->tlink_tree_lock); cifs_sb->tlink_tree = RB_ROOT; - rc = cifs_mount(sb, cifs_sb, volume_info, devname); + rc = cifs_mount(cifs_sb, volume_info); if (rc) { if (!silent) @@ -124,6 +124,17 @@ cifs_read_super(struct super_block *sb, struct smb_vol *volume_info, return rc; } + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIXACL) + sb->s_flags |= MS_POSIXACL; + + if (cifs_sb_master_tcon(cifs_sb)->ses->capabilities & CAP_LARGE_FILES) + sb->s_maxbytes = MAX_LFS_FILESIZE; + else + sb->s_maxbytes = MAX_NON_LFS; + + /* BB FIXME fix time_gran to be larger for LANMAN sessions */ + sb->s_time_gran = 100; + sb->s_magic = CIFS_MAGIC_NUMBER; sb->s_op = &cifs_super_ops; sb->s_bdi = &cifs_sb->bdi; -- cgit v1.2.1 From d687ca380f1a8f3043f42efd2403cbe58c846e70 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 17 Jun 2011 09:14:27 -0400 Subject: cifs: leak on mount if we share superblock cifs_sb and nls end up leaked... Acked-by: Pavel Shilovsky Reviewed-by: Jeff Layton Signed-off-by: Al Viro --- fs/cifs/cifsfs.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'fs/cifs/cifsfs.c') diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 8f7451f3c8e6..4162ee45d043 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -701,6 +701,8 @@ cifs_do_mount(struct file_system_type *fs_type, if (sb->s_fs_info) { cFYI(1, "Use existing superblock"); + unload_nls(cifs_sb->local_nls); + kfree(cifs_sb); goto out_shared; } -- cgit v1.2.1 From 5d3bc605cafe3f367b1c43b673bf643245c81626 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 17 Jun 2011 09:17:28 -0400 Subject: cifs: allocate mountdata earlier pull mountdata allocation up, so that it won't stand in the way when we lift cifs_mount() to location before sget(). Acked-by: Pavel Shilovsky Reviewed-by: Jeff Layton Signed-off-by: Al Viro --- fs/cifs/cifsfs.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) (limited to 'fs/cifs/cifsfs.c') diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 4162ee45d043..ec19161dd278 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -687,6 +687,14 @@ cifs_do_mount(struct file_system_type *fs_type, goto out; } + cifs_sb->mountdata = kstrndup(data, PAGE_SIZE, GFP_KERNEL); + if (cifs_sb->mountdata == NULL) { + root = ERR_PTR(-ENOMEM); + unload_nls(volume_info->local_nls); + kfree(cifs_sb); + goto out; + } + cifs_setup_cifs_sb(volume_info, cifs_sb); mnt_data.vol = volume_info; @@ -701,22 +709,12 @@ cifs_do_mount(struct file_system_type *fs_type, if (sb->s_fs_info) { cFYI(1, "Use existing superblock"); + kfree(cifs_sb->mountdata); unload_nls(cifs_sb->local_nls); kfree(cifs_sb); goto out_shared; } - /* - * Copy mount params for use in submounts. Better to do - * the copy here and deal with the error before cleanup gets - * complicated post-mount. - */ - cifs_sb->mountdata = kstrndup(data, PAGE_SIZE, GFP_KERNEL); - if (cifs_sb->mountdata == NULL) { - root = ERR_PTR(-ENOMEM); - goto out_super; - } - sb->s_flags = flags; /* BB should we make this contingent on mount parm? */ sb->s_flags |= MS_NODIRATIME | MS_NOATIME; @@ -749,6 +747,7 @@ out_super: goto out; out_cifs_sb: + kfree(cifs_sb->mountdata); unload_nls(cifs_sb->local_nls); kfree(cifs_sb); -- cgit v1.2.1 From 2ced6f693581357b2a5bf8b031a702c624b12d0d Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 17 Jun 2011 09:20:04 -0400 Subject: cifs: initialize ->tlink_tree in cifs_setup_cifs_sb() no need to wait until cifs_read_super() and we need it done by the time cifs_mount() will be called. Acked-by: Pavel Shilovsky Reviewed-by: Jeff Layton Signed-off-by: Al Viro --- fs/cifs/cifsfs.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'fs/cifs/cifsfs.c') diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index ec19161dd278..61c7aa870f1c 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -113,9 +113,6 @@ cifs_read_super(struct super_block *sb, struct smb_vol *volume_info, cifs_sb = CIFS_SB(sb); - spin_lock_init(&cifs_sb->tlink_tree_lock); - cifs_sb->tlink_tree = RB_ROOT; - rc = cifs_mount(cifs_sb, volume_info); if (rc) { -- cgit v1.2.1 From 2a9b99516c662d1713d58648e4a4c9aef72051bc Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 17 Jun 2011 09:27:16 -0400 Subject: sanitize cifs_umount() prototype a) superblock argument is unused b) it always returns 0 Acked-by: Pavel Shilovsky Reviewed-by: Jeff Layton Signed-off-by: Al Viro --- fs/cifs/cifsfs.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'fs/cifs/cifsfs.c') diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 61c7aa870f1c..2af14d4577a7 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -172,7 +172,7 @@ out_no_root: if (inode) iput(inode); - cifs_umount(sb, cifs_sb); + cifs_umount(cifs_sb); return rc; } @@ -189,9 +189,7 @@ cifs_put_super(struct super_block *sb) return; } - rc = cifs_umount(sb, cifs_sb); - if (rc) - cERROR(1, "cifs_umount failed with return code %d", rc); + cifs_umount(cifs_sb); } static void cifs_kill_sb(struct super_block *sb) -- cgit v1.2.1 From 97d1152acec0647b72f8c6ecc57da0d6fed574de Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 17 Jun 2011 09:29:57 -0400 Subject: cifs: pull cifs_mount() call up ... to the point prior to sget(). Now we have cifs_sb set up early enough. Acked-by: Pavel Shilovsky Reviewed-by: Jeff Layton Signed-off-by: Al Viro --- fs/cifs/cifsfs.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) (limited to 'fs/cifs/cifsfs.c') diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 2af14d4577a7..4004bc647a72 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -104,8 +104,7 @@ cifs_sb_deactive(struct super_block *sb) } static int -cifs_read_super(struct super_block *sb, struct smb_vol *volume_info, - const char *devname, int silent) +cifs_read_super(struct super_block *sb) { struct inode *inode; struct cifs_sb_info *cifs_sb; @@ -113,14 +112,6 @@ cifs_read_super(struct super_block *sb, struct smb_vol *volume_info, cifs_sb = CIFS_SB(sb); - rc = cifs_mount(cifs_sb, volume_info); - - if (rc) { - if (!silent) - cERROR(1, "cifs_mount failed w/return code = %d", rc); - return rc; - } - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIXACL) sb->s_flags |= MS_POSIXACL; @@ -692,6 +683,17 @@ cifs_do_mount(struct file_system_type *fs_type, cifs_setup_cifs_sb(volume_info, cifs_sb); + rc = cifs_mount(cifs_sb, volume_info); + if (rc) { + if (!(flags & MS_SILENT)) + cERROR(1, "cifs_mount failed w/return code = %d", rc); + root = ERR_PTR(rc); + unload_nls(volume_info->local_nls); + kfree(cifs_sb->mountdata); + kfree(cifs_sb); + goto out; + } + mnt_data.vol = volume_info; mnt_data.cifs_sb = cifs_sb; mnt_data.flags = flags; @@ -699,11 +701,13 @@ cifs_do_mount(struct file_system_type *fs_type, sb = sget(fs_type, cifs_match_super, set_anon_super, &mnt_data); if (IS_ERR(sb)) { root = ERR_CAST(sb); + cifs_umount(cifs_sb); goto out_cifs_sb; } if (sb->s_fs_info) { cFYI(1, "Use existing superblock"); + cifs_umount(cifs_sb); kfree(cifs_sb->mountdata); unload_nls(cifs_sb->local_nls); kfree(cifs_sb); @@ -715,8 +719,7 @@ cifs_do_mount(struct file_system_type *fs_type, sb->s_flags |= MS_NODIRATIME | MS_NOATIME; sb->s_fs_info = cifs_sb; - rc = cifs_read_super(sb, volume_info, dev_name, - flags & MS_SILENT ? 1 : 0); + rc = cifs_read_super(sb); if (rc) { root = ERR_PTR(rc); goto out_super; -- cgit v1.2.1 From 98ab494dd1d25388981114057cf9446250cc7dc7 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 17 Jun 2011 09:32:10 -0400 Subject: cifs: move cifs_umount() call into ->kill_sb() instead of calling it manually in case if cifs_read_super() fails to set ->s_root, just call it from ->kill_sb(). cifs_put_super() is gone now *and* we have cifs_sb shutdown and destruction done after the superblock is gone from ->s_instances. Acked-by: Pavel Shilovsky Reviewed-by: Jeff Layton Signed-off-by: Al Viro --- fs/cifs/cifsfs.c | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) (limited to 'fs/cifs/cifsfs.c') diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 4004bc647a72..15de4561dbc5 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -163,30 +163,14 @@ out_no_root: if (inode) iput(inode); - cifs_umount(cifs_sb); return rc; } -static void -cifs_put_super(struct super_block *sb) -{ - int rc = 0; - struct cifs_sb_info *cifs_sb; - - cFYI(1, "In cifs_put_super"); - cifs_sb = CIFS_SB(sb); - if (cifs_sb == NULL) { - cFYI(1, "Empty cifs superblock info passed to unmount"); - return; - } - - cifs_umount(cifs_sb); -} - static void cifs_kill_sb(struct super_block *sb) { struct cifs_sb_info *cifs_sb = CIFS_SB(sb); kill_anon_super(sb); + cifs_umount(cifs_sb); kfree(cifs_sb->mountdata); unload_nls(cifs_sb->local_nls); kfree(cifs_sb); @@ -537,7 +521,6 @@ static int cifs_drop_inode(struct inode *inode) } static const struct super_operations cifs_super_ops = { - .put_super = cifs_put_super, .statfs = cifs_statfs, .alloc_inode = cifs_alloc_inode, .destroy_inode = cifs_destroy_inode, -- cgit v1.2.1 From d757d71bfc30669a500b72792067e8d1c5d401a5 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 17 Jun 2011 09:42:43 -0400 Subject: cifs: pull freeing mountdata/dropping nls/freeing cifs_sb into cifs_umount() all callers of cifs_umount() proceed to do the same thing; pull it into cifs_umount() itself. Acked-by: Pavel Shilovsky Reviewed-by: Jeff Layton Signed-off-by: Al Viro --- fs/cifs/cifsfs.c | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) (limited to 'fs/cifs/cifsfs.c') diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 15de4561dbc5..46960b7ee433 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -171,9 +171,6 @@ static void cifs_kill_sb(struct super_block *sb) struct cifs_sb_info *cifs_sb = CIFS_SB(sb); kill_anon_super(sb); cifs_umount(cifs_sb); - kfree(cifs_sb->mountdata); - unload_nls(cifs_sb->local_nls); - kfree(cifs_sb); } static int @@ -685,15 +682,12 @@ cifs_do_mount(struct file_system_type *fs_type, if (IS_ERR(sb)) { root = ERR_CAST(sb); cifs_umount(cifs_sb); - goto out_cifs_sb; + goto out; } if (sb->s_fs_info) { cFYI(1, "Use existing superblock"); cifs_umount(cifs_sb); - kfree(cifs_sb->mountdata); - unload_nls(cifs_sb->local_nls); - kfree(cifs_sb); goto out_shared; } @@ -725,13 +719,6 @@ out_shared: out_super: deactivate_locked_super(sb); - goto out; - -out_cifs_sb: - kfree(cifs_sb->mountdata); - unload_nls(cifs_sb->local_nls); - kfree(cifs_sb); - out: cifs_cleanup_volume_info(&volume_info); return root; -- cgit v1.2.1 From ee01a14d9ddcf3f832f9ceb837888501cb496e27 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 17 Jun 2011 09:47:23 -0400 Subject: cifs: close sget() races have ->s_fs_info set by the set() callback passed to sget() Acked-by: Pavel Shilovsky Reviewed-by: Jeff Layton Signed-off-by: Al Viro --- fs/cifs/cifsfs.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'fs/cifs/cifsfs.c') diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 46960b7ee433..ba2b2da360d3 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -629,6 +629,13 @@ out: return dparent; } +static int cifs_set_super(struct super_block *sb, void *data) +{ + struct cifs_mnt_data *mnt_data = data; + sb->s_fs_info = mnt_data->cifs_sb; + return set_anon_super(sb, NULL); +} + static struct dentry * cifs_do_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *data) @@ -678,14 +685,14 @@ cifs_do_mount(struct file_system_type *fs_type, mnt_data.cifs_sb = cifs_sb; mnt_data.flags = flags; - sb = sget(fs_type, cifs_match_super, set_anon_super, &mnt_data); + sb = sget(fs_type, cifs_match_super, cifs_set_super, &mnt_data); if (IS_ERR(sb)) { root = ERR_CAST(sb); cifs_umount(cifs_sb); goto out; } - if (sb->s_fs_info) { + if (sb->s_root) { cFYI(1, "Use existing superblock"); cifs_umount(cifs_sb); goto out_shared; @@ -694,7 +701,6 @@ cifs_do_mount(struct file_system_type *fs_type, sb->s_flags = flags; /* BB should we make this contingent on mount parm? */ sb->s_flags |= MS_NODIRATIME | MS_NOATIME; - sb->s_fs_info = cifs_sb; rc = cifs_read_super(sb); if (rc) { -- cgit v1.2.1 From fa18f1bdce898f0efd0c8639c901d826d01be04f Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 17 Jun 2011 09:50:44 -0400 Subject: cifs: more breakage on mount failures if cifs_get_root() fails, we end up with ->mount() returning NULL, which is not what callers expect. Moreover, in case of superblock reuse we end up leaking a superblock reference... Acked-by: Pavel Shilovsky Reviewed-by: Jeff Layton Signed-off-by: Al Viro --- fs/cifs/cifsfs.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'fs/cifs/cifsfs.c') diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index ba2b2da360d3..234e9d08db76 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -710,19 +710,16 @@ cifs_do_mount(struct file_system_type *fs_type, sb->s_flags |= MS_ACTIVE; +out_shared: root = cifs_get_root(volume_info, sb); - if (root == NULL) + if (root == NULL) { + root = ERR_PTR(-EINVAL); /* XXX */ goto out_super; + } cFYI(1, "dentry root is: %p", root); goto out; -out_shared: - root = cifs_get_root(volume_info, sb); - if (root) - cFYI(1, "dentry root is: %p", root); - goto out; - out_super: deactivate_locked_super(sb); out: -- cgit v1.2.1 From 5c4f1ad7c6aa3b729bd3a93b80f9417d7e978c32 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 17 Jun 2011 09:56:55 -0400 Subject: cifs: tidy cifs_do_mount() up a bit Acked-by: Pavel Shilovsky Reviewed-by: Jeff Layton Signed-off-by: Al Viro --- fs/cifs/cifsfs.c | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) (limited to 'fs/cifs/cifsfs.c') diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 234e9d08db76..9a6696a5eb78 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -656,16 +656,13 @@ cifs_do_mount(struct file_system_type *fs_type, cifs_sb = kzalloc(sizeof(struct cifs_sb_info), GFP_KERNEL); if (cifs_sb == NULL) { root = ERR_PTR(-ENOMEM); - unload_nls(volume_info->local_nls); - goto out; + goto out_nls; } cifs_sb->mountdata = kstrndup(data, PAGE_SIZE, GFP_KERNEL); if (cifs_sb->mountdata == NULL) { root = ERR_PTR(-ENOMEM); - unload_nls(volume_info->local_nls); - kfree(cifs_sb); - goto out; + goto out_cifs_sb; } cifs_setup_cifs_sb(volume_info, cifs_sb); @@ -675,10 +672,7 @@ cifs_do_mount(struct file_system_type *fs_type, if (!(flags & MS_SILENT)) cERROR(1, "cifs_mount failed w/return code = %d", rc); root = ERR_PTR(rc); - unload_nls(volume_info->local_nls); - kfree(cifs_sb->mountdata); - kfree(cifs_sb); - goto out; + goto out_mountdata; } mnt_data.vol = volume_info; @@ -695,22 +689,20 @@ cifs_do_mount(struct file_system_type *fs_type, if (sb->s_root) { cFYI(1, "Use existing superblock"); cifs_umount(cifs_sb); - goto out_shared; - } - - sb->s_flags = flags; - /* BB should we make this contingent on mount parm? */ - sb->s_flags |= MS_NODIRATIME | MS_NOATIME; + } else { + sb->s_flags = flags; + /* BB should we make this contingent on mount parm? */ + sb->s_flags |= MS_NODIRATIME | MS_NOATIME; + + rc = cifs_read_super(sb); + if (rc) { + root = ERR_PTR(rc); + goto out_super; + } - rc = cifs_read_super(sb); - if (rc) { - root = ERR_PTR(rc); - goto out_super; + sb->s_flags |= MS_ACTIVE; } - sb->s_flags |= MS_ACTIVE; - -out_shared: root = cifs_get_root(volume_info, sb); if (root == NULL) { root = ERR_PTR(-EINVAL); /* XXX */ @@ -725,6 +717,14 @@ out_super: out: cifs_cleanup_volume_info(&volume_info); return root; + +out_mountdata: + kfree(cifs_sb->mountdata); +out_cifs_sb: + kfree(cifs_sb); +out_nls: + unload_nls(volume_info->local_nls); + goto out; } static ssize_t cifs_file_aio_write(struct kiocb *iocb, const struct iovec *iov, -- cgit v1.2.1 From 9403c9c598e91d473c0582066e47ed2289292e45 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 17 Jun 2011 10:02:59 -0400 Subject: cifs: propagate errors from cifs_get_root() to mount(2) ... instead of just failing with -EINVAL Acked-by: Pavel Shilovsky Reviewed-by: Jeff Layton Signed-off-by: Al Viro --- fs/cifs/cifsfs.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'fs/cifs/cifsfs.c') diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 9a6696a5eb78..35f9154615fa 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -554,7 +554,7 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb) full_path = cifs_build_path_to_root(vol, cifs_sb, cifs_sb_master_tcon(cifs_sb)); if (full_path == NULL) - return NULL; + return ERR_PTR(-ENOMEM); cFYI(1, "Get root dentry for %s", full_path); @@ -583,7 +583,7 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb) dchild = d_alloc(dparent, &name); if (dchild == NULL) { dput(dparent); - dparent = NULL; + dparent = ERR_PTR(-ENOMEM); goto out; } } @@ -601,7 +601,7 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb) if (rc) { dput(dchild); dput(dparent); - dparent = NULL; + dparent = ERR_PTR(rc); goto out; } alias = d_materialise_unique(dchild, inode); @@ -609,7 +609,7 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb) dput(dchild); if (IS_ERR(alias)) { dput(dparent); - dparent = NULL; + dparent = ERR_PTR(-EINVAL); /* XXX */ goto out; } dchild = alias; @@ -704,10 +704,8 @@ cifs_do_mount(struct file_system_type *fs_type, } root = cifs_get_root(volume_info, sb); - if (root == NULL) { - root = ERR_PTR(-EINVAL); /* XXX */ + if (IS_ERR(root)) goto out_super; - } cFYI(1, "dentry root is: %p", root); goto out; -- cgit v1.2.1