diff options
author | Pavel Shilovsky <piastry@etersoft.ru> | 2011-05-25 05:35:34 -0400 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2011-05-25 16:02:31 -0400 |
commit | b2e5cd33b598fb496b9366c445bd77c801efabb8 (patch) | |
tree | 19f404a46cc637c7d6034deec5d7b1f9b0553924 /fs/cifs | |
parent | 3c1105df699188a70f5c17dc0795affea388bca7 (diff) |
CIFS: Fix undefined behavior when mount fails
Fix double kfree() calls on the same pointers and cleanup mount code.
Reviewed-and-Tested-by: Jeff Layton <jlayton@samba.org>
Signed-off-by: Pavel Shilovsky <piastry@etersoft.ru>
Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs/cifs')
-rw-r--r-- | fs/cifs/cifsfs.c | 44 |
1 files changed, 17 insertions, 27 deletions
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 131afadce0e0..d1ed7f9946d5 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
@@ -104,29 +104,23 @@ cifs_sb_deactive(struct super_block *sb) | |||
104 | } | 104 | } |
105 | 105 | ||
106 | static int | 106 | static int |
107 | cifs_read_super(struct super_block *sb, struct cifs_sb_info *cifs_sb, | 107 | cifs_read_super(struct super_block *sb, struct smb_vol *volume_info, |
108 | void *data, struct smb_vol *volume_info, const char *devname, | 108 | const char *devname, int silent) |
109 | int silent) | ||
110 | { | 109 | { |
111 | struct inode *inode; | 110 | struct inode *inode; |
111 | struct cifs_sb_info *cifs_sb; | ||
112 | int rc = 0; | 112 | int rc = 0; |
113 | 113 | ||
114 | /* BB should we make this contingent on mount parm? */ | 114 | cifs_sb = CIFS_SB(sb); |
115 | sb->s_flags |= MS_NODIRATIME | MS_NOATIME; | ||
116 | sb->s_fs_info = cifs_sb; | ||
117 | 115 | ||
118 | spin_lock_init(&cifs_sb->tlink_tree_lock); | 116 | spin_lock_init(&cifs_sb->tlink_tree_lock); |
119 | cifs_sb->tlink_tree = RB_ROOT; | 117 | cifs_sb->tlink_tree = RB_ROOT; |
120 | 118 | ||
121 | rc = bdi_setup_and_register(&cifs_sb->bdi, "cifs", BDI_CAP_MAP_COPY); | 119 | rc = bdi_setup_and_register(&cifs_sb->bdi, "cifs", BDI_CAP_MAP_COPY); |
122 | if (rc) { | 120 | if (rc) |
123 | kfree(cifs_sb); | ||
124 | return rc; | 121 | return rc; |
125 | } | ||
126 | cifs_sb->bdi.ra_pages = default_backing_dev_info.ra_pages; | ||
127 | 122 | ||
128 | if (data) | 123 | cifs_sb->bdi.ra_pages = default_backing_dev_info.ra_pages; |
129 | cifs_sb->mountdata = data; | ||
130 | 124 | ||
131 | rc = cifs_mount(sb, cifs_sb, volume_info, devname); | 125 | rc = cifs_mount(sb, cifs_sb, volume_info, devname); |
132 | 126 | ||
@@ -179,15 +173,7 @@ out_no_root: | |||
179 | cifs_umount(sb, cifs_sb); | 173 | cifs_umount(sb, cifs_sb); |
180 | 174 | ||
181 | out_mount_failed: | 175 | out_mount_failed: |
182 | if (cifs_sb) { | 176 | bdi_destroy(&cifs_sb->bdi); |
183 | if (cifs_sb->mountdata) { | ||
184 | kfree(cifs_sb->mountdata); | ||
185 | cifs_sb->mountdata = NULL; | ||
186 | } | ||
187 | unload_nls(cifs_sb->local_nls); | ||
188 | bdi_destroy(&cifs_sb->bdi); | ||
189 | kfree(cifs_sb); | ||
190 | } | ||
191 | return rc; | 177 | return rc; |
192 | } | 178 | } |
193 | 179 | ||
@@ -553,7 +539,6 @@ cifs_do_mount(struct file_system_type *fs_type, | |||
553 | struct cifs_sb_info *cifs_sb; | 539 | struct cifs_sb_info *cifs_sb; |
554 | struct smb_vol *volume_info; | 540 | struct smb_vol *volume_info; |
555 | struct dentry *root; | 541 | struct dentry *root; |
556 | char *copied_data = NULL; | ||
557 | 542 | ||
558 | cFYI(1, "Devname: %s flags: %d ", dev_name, flags); | 543 | cFYI(1, "Devname: %s flags: %d ", dev_name, flags); |
559 | 544 | ||
@@ -576,20 +561,23 @@ cifs_do_mount(struct file_system_type *fs_type, | |||
576 | goto out; | 561 | goto out; |
577 | } | 562 | } |
578 | 563 | ||
579 | sb->s_flags = flags; | ||
580 | |||
581 | /* | 564 | /* |
582 | * Copy mount params for use in submounts. Better to do | 565 | * Copy mount params for use in submounts. Better to do |
583 | * the copy here and deal with the error before cleanup gets | 566 | * the copy here and deal with the error before cleanup gets |
584 | * complicated post-mount. | 567 | * complicated post-mount. |
585 | */ | 568 | */ |
586 | copied_data = kstrndup(data, PAGE_SIZE, GFP_KERNEL); | 569 | cifs_sb->mountdata = kstrndup(data, PAGE_SIZE, GFP_KERNEL); |
587 | if (copied_data == NULL) { | 570 | if (cifs_sb->mountdata == NULL) { |
588 | root = ERR_PTR(-ENOMEM); | 571 | root = ERR_PTR(-ENOMEM); |
589 | goto err_out; | 572 | goto err_out; |
590 | } | 573 | } |
591 | 574 | ||
592 | rc = cifs_read_super(sb, cifs_sb, copied_data, volume_info, dev_name, | 575 | sb->s_flags = flags; |
576 | /* BB should we make this contingent on mount parm? */ | ||
577 | sb->s_flags |= MS_NODIRATIME | MS_NOATIME; | ||
578 | sb->s_fs_info = cifs_sb; | ||
579 | |||
580 | rc = cifs_read_super(sb, volume_info, dev_name, | ||
593 | flags & MS_SILENT ? 1 : 0); | 581 | flags & MS_SILENT ? 1 : 0); |
594 | if (rc) { | 582 | if (rc) { |
595 | root = ERR_PTR(rc); | 583 | root = ERR_PTR(rc); |
@@ -604,6 +592,8 @@ out: | |||
604 | return root; | 592 | return root; |
605 | 593 | ||
606 | err_out: | 594 | err_out: |
595 | kfree(cifs_sb->mountdata); | ||
596 | unload_nls(cifs_sb->local_nls); | ||
607 | kfree(cifs_sb); | 597 | kfree(cifs_sb); |
608 | deactivate_locked_super(sb); | 598 | deactivate_locked_super(sb); |
609 | cifs_cleanup_volume_info(&volume_info); | 599 | cifs_cleanup_volume_info(&volume_info); |