Commit 7586b765 authored by Jeff Layton's avatar Jeff Layton Committed by Steve French

cifs: don't declare smb_vol info on the stack

struct smb_vol is fairly large, it's probably best to kzalloc it...
Signed-off-by: default avatarJeff Layton <jlayton@redhat.com>
Signed-off-by: default avatarSteve French <sfrench@us.ibm.com>
parent 63c038c2
...@@ -2185,27 +2185,30 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, ...@@ -2185,27 +2185,30 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
{ {
int rc = 0; int rc = 0;
int xid; int xid;
struct smb_vol volume_info; struct smb_vol *volume_info;
struct cifsSesInfo *pSesInfo = NULL; struct cifsSesInfo *pSesInfo = NULL;
struct cifsTconInfo *tcon = NULL; struct cifsTconInfo *tcon = NULL;
struct TCP_Server_Info *srvTcp = NULL; struct TCP_Server_Info *srvTcp = NULL;
xid = GetXid(); xid = GetXid();
/* cFYI(1, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data)); */ volume_info = kzalloc(sizeof(struct smb_vol), GFP_KERNEL);
if (!volume_info) {
rc = -ENOMEM;
goto out;
}
memset(&volume_info, 0, sizeof(struct smb_vol)); if (cifs_parse_mount_options(mount_data, devname, volume_info)) {
if (cifs_parse_mount_options(mount_data, devname, &volume_info)) {
rc = -EINVAL; rc = -EINVAL;
goto out; goto out;
} }
if (volume_info.nullauth) { if (volume_info->nullauth) {
cFYI(1, ("null user")); cFYI(1, ("null user"));
volume_info.username = ""; volume_info->username = "";
} else if (volume_info.username) { } else if (volume_info->username) {
/* BB fixme parse for domain name here */ /* BB fixme parse for domain name here */
cFYI(1, ("Username: %s", volume_info.username)); cFYI(1, ("Username: %s", volume_info->username));
} else { } else {
cifserror("No username specified"); cifserror("No username specified");
/* In userspace mount helper we can get user name from alternate /* In userspace mount helper we can get user name from alternate
...@@ -2216,27 +2219,27 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, ...@@ -2216,27 +2219,27 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
/* this is needed for ASCII cp to Unicode converts */ /* this is needed for ASCII cp to Unicode converts */
if (volume_info.iocharset == NULL) { if (volume_info->iocharset == NULL) {
cifs_sb->local_nls = load_nls_default(); cifs_sb->local_nls = load_nls_default();
/* load_nls_default can not return null */ /* load_nls_default can not return null */
} else { } else {
cifs_sb->local_nls = load_nls(volume_info.iocharset); cifs_sb->local_nls = load_nls(volume_info->iocharset);
if (cifs_sb->local_nls == NULL) { if (cifs_sb->local_nls == NULL) {
cERROR(1, ("CIFS mount error: iocharset %s not found", cERROR(1, ("CIFS mount error: iocharset %s not found",
volume_info.iocharset)); volume_info->iocharset));
rc = -ELIBACC; rc = -ELIBACC;
goto out; goto out;
} }
} }
/* get a reference to a tcp session */ /* get a reference to a tcp session */
srvTcp = cifs_get_tcp_session(&volume_info); srvTcp = cifs_get_tcp_session(volume_info);
if (IS_ERR(srvTcp)) { if (IS_ERR(srvTcp)) {
rc = PTR_ERR(srvTcp); rc = PTR_ERR(srvTcp);
goto out; goto out;
} }
pSesInfo = cifs_find_smb_ses(srvTcp, volume_info.username); pSesInfo = cifs_find_smb_ses(srvTcp, volume_info->username);
if (pSesInfo) { if (pSesInfo) {
cFYI(1, ("Existing smb sess found (status=%d)", cFYI(1, ("Existing smb sess found (status=%d)",
pSesInfo->status)); pSesInfo->status));
...@@ -2274,24 +2277,24 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, ...@@ -2274,24 +2277,24 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
list_add(&pSesInfo->smb_ses_list, &srvTcp->smb_ses_list); list_add(&pSesInfo->smb_ses_list, &srvTcp->smb_ses_list);
write_unlock(&cifs_tcp_ses_lock); write_unlock(&cifs_tcp_ses_lock);
/* volume_info.password freed at unmount */ /* volume_info->password freed at unmount */
if (volume_info.password) { if (volume_info->password) {
pSesInfo->password = volume_info.password; pSesInfo->password = volume_info->password;
/* set to NULL to prevent freeing on exit */ /* set to NULL to prevent freeing on exit */
volume_info.password = NULL; volume_info->password = NULL;
} }
if (volume_info.username) if (volume_info->username)
strncpy(pSesInfo->userName, volume_info.username, strncpy(pSesInfo->userName, volume_info->username,
MAX_USERNAME_SIZE); MAX_USERNAME_SIZE);
if (volume_info.domainname) { if (volume_info->domainname) {
int len = strlen(volume_info.domainname); int len = strlen(volume_info->domainname);
pSesInfo->domainName = kmalloc(len + 1, GFP_KERNEL); pSesInfo->domainName = kmalloc(len + 1, GFP_KERNEL);
if (pSesInfo->domainName) if (pSesInfo->domainName)
strcpy(pSesInfo->domainName, strcpy(pSesInfo->domainName,
volume_info.domainname); volume_info->domainname);
} }
pSesInfo->linux_uid = volume_info.linux_uid; pSesInfo->linux_uid = volume_info->linux_uid;
pSesInfo->overrideSecFlg = volume_info.secFlg; pSesInfo->overrideSecFlg = volume_info->secFlg;
down(&pSesInfo->sesSem); down(&pSesInfo->sesSem);
/* BB FIXME need to pass vol->secFlgs BB */ /* BB FIXME need to pass vol->secFlgs BB */
...@@ -2302,14 +2305,14 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, ...@@ -2302,14 +2305,14 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
/* search for existing tcon to this server share */ /* search for existing tcon to this server share */
if (!rc) { if (!rc) {
setup_cifs_sb(&volume_info, cifs_sb); setup_cifs_sb(volume_info, cifs_sb);
tcon = cifs_find_tcon(pSesInfo, volume_info.UNC); tcon = cifs_find_tcon(pSesInfo, volume_info->UNC);
if (tcon) { if (tcon) {
cFYI(1, ("Found match on UNC path")); cFYI(1, ("Found match on UNC path"));
/* existing tcon already has a reference */ /* existing tcon already has a reference */
cifs_put_smb_ses(pSesInfo); cifs_put_smb_ses(pSesInfo);
if (tcon->seal != volume_info.seal) if (tcon->seal != volume_info->seal)
cERROR(1, ("transport encryption setting " cERROR(1, ("transport encryption setting "
"conflicts with existing tid")); "conflicts with existing tid"));
} else { } else {
...@@ -2321,8 +2324,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, ...@@ -2321,8 +2324,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
tcon->ses = pSesInfo; tcon->ses = pSesInfo;
/* check for null share name ie connect to dfs root */ /* check for null share name ie connect to dfs root */
if ((strchr(volume_info.UNC + 3, '\\') == NULL) if ((strchr(volume_info->UNC + 3, '\\') == NULL)
&& (strchr(volume_info.UNC + 3, '/') == NULL)) { && (strchr(volume_info->UNC + 3, '/') == NULL)) {
/* rc = connect_to_dfs_path(...) */ /* rc = connect_to_dfs_path(...) */
cFYI(1, ("DFS root not supported")); cFYI(1, ("DFS root not supported"));
rc = -ENODEV; rc = -ENODEV;
...@@ -2331,10 +2334,10 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, ...@@ -2331,10 +2334,10 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
/* BB Do we need to wrap sesSem around /* BB Do we need to wrap sesSem around
* this TCon call and Unix SetFS as * this TCon call and Unix SetFS as
* we do on SessSetup and reconnect? */ * we do on SessSetup and reconnect? */
rc = CIFSTCon(xid, pSesInfo, volume_info.UNC, rc = CIFSTCon(xid, pSesInfo, volume_info->UNC,
tcon, cifs_sb->local_nls); tcon, cifs_sb->local_nls);
cFYI(1, ("CIFS Tcon rc = %d", rc)); cFYI(1, ("CIFS Tcon rc = %d", rc));
if (volume_info.nodfs) { if (volume_info->nodfs) {
tcon->Flags &= ~SMB_SHARE_IS_IN_DFS; tcon->Flags &= ~SMB_SHARE_IS_IN_DFS;
cFYI(1, ("DFS disabled (%d)", cFYI(1, ("DFS disabled (%d)",
tcon->Flags)); tcon->Flags));
...@@ -2342,7 +2345,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, ...@@ -2342,7 +2345,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
} }
if (rc) if (rc)
goto mount_fail_check; goto mount_fail_check;
tcon->seal = volume_info.seal; tcon->seal = volume_info->seal;
write_lock(&cifs_tcp_ses_lock); write_lock(&cifs_tcp_ses_lock);
list_add(&tcon->tcon_list, &pSesInfo->tcon_list); list_add(&tcon->tcon_list, &pSesInfo->tcon_list);
write_unlock(&cifs_tcp_ses_lock); write_unlock(&cifs_tcp_ses_lock);
...@@ -2352,9 +2355,9 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, ...@@ -2352,9 +2355,9 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
to a share so for resources mounted more than once to a share so for resources mounted more than once
to the same server share the last value passed in to the same server share the last value passed in
for the retry flag is used */ for the retry flag is used */
tcon->retry = volume_info.retry; tcon->retry = volume_info->retry;
tcon->nocase = volume_info.nocase; tcon->nocase = volume_info->nocase;
tcon->local_lease = volume_info.local_lease; tcon->local_lease = volume_info->local_lease;
} }
if (pSesInfo) { if (pSesInfo) {
if (pSesInfo->capabilities & CAP_LARGE_FILES) { if (pSesInfo->capabilities & CAP_LARGE_FILES) {
...@@ -2391,7 +2394,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, ...@@ -2391,7 +2394,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
if (tcon->ses->capabilities & CAP_UNIX) if (tcon->ses->capabilities & CAP_UNIX)
/* reset of caps checks mount to see if unix extensions /* reset of caps checks mount to see if unix extensions
disabled for just this mount */ disabled for just this mount */
reset_cifs_unix_caps(xid, tcon, sb, &volume_info); reset_cifs_unix_caps(xid, tcon, sb, volume_info);
else else
tcon->unix_ext = 0; /* server does not support them */ tcon->unix_ext = 0; /* server does not support them */
...@@ -2410,18 +2413,22 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, ...@@ -2410,18 +2413,22 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
cifs_sb->rsize = min(cifs_sb->rsize, cifs_sb->rsize = min(cifs_sb->rsize,
(tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)); (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE));
/* volume_info.password is freed above when existing session found /* volume_info->password is freed above when existing session found
(in which case it is not needed anymore) but when new sesion is created (in which case it is not needed anymore) but when new sesion is created
the password ptr is put in the new session structure (in which case the the password ptr is put in the new session structure (in which case the
password will be freed at unmount time) */ password will be freed at unmount time) */
out: out:
/* zero out password before freeing */ /* zero out password before freeing */
if (volume_info.password != NULL) { if (volume_info) {
memset(volume_info.password, 0, strlen(volume_info.password)); if (volume_info->password != NULL) {
kfree(volume_info.password); memset(volume_info->password, 0,
strlen(volume_info->password));
kfree(volume_info->password);
}
kfree(volume_info->UNC);
kfree(volume_info->prepath);
kfree(volume_info);
} }
kfree(volume_info.UNC);
kfree(volume_info.prepath);
FreeXid(xid); FreeXid(xid);
return rc; return rc;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment