Move all of the kfree's sprinkled in the middle of the function to the
end, and have the code set rc and just goto there on error. Also zero
out the password string before freeing it. Looks like this should also
fix a potential memory leak of the prepath string if an error occurs
near the end of the function.
Signed-off-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: Steve French <sfrench@us.ibm.com>
memset(&volume_info, 0, sizeof(struct smb_vol));
if (cifs_parse_mount_options(mount_data, devname, &volume_info)) {
memset(&volume_info, 0, sizeof(struct smb_vol));
if (cifs_parse_mount_options(mount_data, devname, &volume_info)) {
- kfree(volume_info.UNC);
- kfree(volume_info.password);
- kfree(volume_info.prepath);
- FreeXid(xid);
- return -EINVAL;
+ rc = -EINVAL;
+ goto out;
}
if (volume_info.nullauth) {
}
if (volume_info.nullauth) {
cifserror("No username specified");
/* In userspace mount helper we can get user name from alternate
locations such as env variables and files on disk */
cifserror("No username specified");
/* In userspace mount helper we can get user name from alternate
locations such as env variables and files on disk */
- kfree(volume_info.UNC);
- kfree(volume_info.password);
- kfree(volume_info.prepath);
- FreeXid(xid);
- return -EINVAL;
+ rc = -EINVAL;
+ goto out;
}
if (volume_info.UNCip && volume_info.UNC) {
}
if (volume_info.UNCip && volume_info.UNC) {
if (rc <= 0) {
/* we failed translating address */
if (rc <= 0) {
/* we failed translating address */
- kfree(volume_info.UNC);
- kfree(volume_info.password);
- kfree(volume_info.prepath);
- FreeXid(xid);
- return -EINVAL;
+ rc = -EINVAL;
+ goto out;
}
cFYI(1, ("UNC: %s ip: %s", volume_info.UNC, volume_info.UNCip));
}
cFYI(1, ("UNC: %s ip: %s", volume_info.UNC, volume_info.UNCip));
/* BB using ip addr as server name to connect to the
DFS root below */
cERROR(1, ("Connecting to DFS root not implemented yet"));
/* BB using ip addr as server name to connect to the
DFS root below */
cERROR(1, ("Connecting to DFS root not implemented yet"));
- kfree(volume_info.UNC);
- kfree(volume_info.password);
- kfree(volume_info.prepath);
- FreeXid(xid);
- return -EINVAL;
+ rc = -EINVAL;
+ goto out;
} else /* which servers DFS root would we conect to */ {
cERROR(1,
("CIFS mount error: No UNC path (e.g. -o "
"unc=//192.168.1.100/public) specified"));
} else /* which servers DFS root would we conect to */ {
cERROR(1,
("CIFS mount error: No UNC path (e.g. -o "
"unc=//192.168.1.100/public) specified"));
- kfree(volume_info.UNC);
- kfree(volume_info.password);
- kfree(volume_info.prepath);
- FreeXid(xid);
- return -EINVAL;
+ rc = -EINVAL;
+ goto out;
}
/* this is needed for ASCII cp to Unicode converts */
}
/* this is needed for ASCII cp to Unicode converts */
if (cifs_sb->local_nls == NULL) {
cERROR(1, ("CIFS mount error: iocharset %s not found",
volume_info.iocharset));
if (cifs_sb->local_nls == NULL) {
cERROR(1, ("CIFS mount error: iocharset %s not found",
volume_info.iocharset));
- kfree(volume_info.UNC);
- kfree(volume_info.password);
- kfree(volume_info.prepath);
- FreeXid(xid);
- return -ELIBACC;
+ rc = -ELIBACC;
+ goto out;
&sin_server6.sin6_addr,
volume_info.username, &srvTcp);
} else {
&sin_server6.sin6_addr,
volume_info.username, &srvTcp);
} else {
- kfree(volume_info.UNC);
- kfree(volume_info.password);
- kfree(volume_info.prepath);
- FreeXid(xid);
- return -EINVAL;
+ rc = -EINVAL;
+ goto out;
"Aborting operation"));
if (csocket != NULL)
sock_release(csocket);
"Aborting operation"));
if (csocket != NULL)
sock_release(csocket);
- kfree(volume_info.UNC);
- kfree(volume_info.password);
- kfree(volume_info.prepath);
- FreeXid(xid);
- return rc;
}
srvTcp = kzalloc(sizeof(struct TCP_Server_Info), GFP_KERNEL);
if (!srvTcp) {
rc = -ENOMEM;
sock_release(csocket);
}
srvTcp = kzalloc(sizeof(struct TCP_Server_Info), GFP_KERNEL);
if (!srvTcp) {
rc = -ENOMEM;
sock_release(csocket);
- kfree(volume_info.UNC);
- kfree(volume_info.password);
- kfree(volume_info.prepath);
- FreeXid(xid);
- return rc;
} else {
memcpy(&srvTcp->addr.sockAddr, &sin_server,
sizeof(struct sockaddr_in));
} else {
memcpy(&srvTcp->addr.sockAddr, &sin_server,
sizeof(struct sockaddr_in));
cERROR(1, ("error %d create cifsd thread", rc));
srvTcp->tsk = NULL;
sock_release(csocket);
cERROR(1, ("error %d create cifsd thread", rc));
srvTcp->tsk = NULL;
sock_release(csocket);
- kfree(volume_info.UNC);
- kfree(volume_info.password);
- kfree(volume_info.prepath);
- FreeXid(xid);
- return rc;
}
wait_for_completion(&cifsd_complete);
rc = 0;
}
wait_for_completion(&cifsd_complete);
rc = 0;
if (existingCifsSes) {
pSesInfo = existingCifsSes;
cFYI(1, ("Existing smb sess found"));
if (existingCifsSes) {
pSesInfo = existingCifsSes;
cFYI(1, ("Existing smb sess found"));
- kfree(volume_info.password);
- /* volume_info.UNC freed at end of function */
} else if (!rc) {
cFYI(1, ("Existing smb sess not found"));
pSesInfo = sesInfoAlloc();
} else if (!rc) {
cFYI(1, ("Existing smb sess not found"));
pSesInfo = sesInfoAlloc();
if (!rc) {
/* volume_info.password freed at unmount */
if (!rc) {
/* 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 */
+ volume_info.password = NULL;
+ }
if (volume_info.username)
strncpy(pSesInfo->userName,
volume_info.username,
if (volume_info.username)
strncpy(pSesInfo->userName,
volume_info.username,
up(&pSesInfo->sesSem);
if (!rc)
atomic_inc(&srvTcp->socketUseCount);
up(&pSesInfo->sesSem);
if (!rc)
atomic_inc(&srvTcp->socketUseCount);
- } else
- kfree(volume_info.password);
}
/* search for existing tcon to this server share */
}
/* search for existing tcon to this server share */
"", cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
"", cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
- kfree(volume_info.UNC);
- FreeXid(xid);
- return -ENODEV;
+ rc = -ENODEV;
+ goto out;
} else {
/* BB Do we need to wrap sesSem around
* this TCon call and Unix SetFS as
} else {
/* BB Do we need to wrap sesSem around
* this TCon call and Unix SetFS as
(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
password will be freed at unmount time) */
(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
password will be freed at unmount time) */
+out:
+ /* zero out password before freeing */
+ if (volume_info.password != NULL) {
+ memset(volume_info.password, 0, strlen(volume_info.password));
+ kfree(volume_info.password);
+ }
kfree(volume_info.UNC);
kfree(volume_info.prepath);
FreeXid(xid);
kfree(volume_info.UNC);
kfree(volume_info.prepath);
FreeXid(xid);