aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Layton <jlayton@redhat.com>2007-11-16 17:21:07 -0500
committerSteve French <sfrench@us.ibm.com>2007-11-16 17:21:07 -0500
commit70fe7dc05596a405ee6a83265f675a544e32f7d8 (patch)
tree92bbeb52c1f66cdefd556bdd6d5170e751ab457b
parent68bf728a225b7f2045bb501854d6e7695b9b015d (diff)
[CIFS] clean up error handling in cifs_mount
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>
-rw-r--r--fs/cifs/connect.c88
1 files changed, 30 insertions, 58 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 26e1087e081f..58c509e6ac6a 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -1781,11 +1781,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1781 1781
1782 memset(&volume_info, 0, sizeof(struct smb_vol)); 1782 memset(&volume_info, 0, sizeof(struct smb_vol));
1783 if (cifs_parse_mount_options(mount_data, devname, &volume_info)) { 1783 if (cifs_parse_mount_options(mount_data, devname, &volume_info)) {
1784 kfree(volume_info.UNC); 1784 rc = -EINVAL;
1785 kfree(volume_info.password); 1785 goto out;
1786 kfree(volume_info.prepath);
1787 FreeXid(xid);
1788 return -EINVAL;
1789 } 1786 }
1790 1787
1791 if (volume_info.nullauth) { 1788 if (volume_info.nullauth) {
@@ -1798,11 +1795,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1798 cifserror("No username specified"); 1795 cifserror("No username specified");
1799 /* In userspace mount helper we can get user name from alternate 1796 /* In userspace mount helper we can get user name from alternate
1800 locations such as env variables and files on disk */ 1797 locations such as env variables and files on disk */
1801 kfree(volume_info.UNC); 1798 rc = -EINVAL;
1802 kfree(volume_info.password); 1799 goto out;
1803 kfree(volume_info.prepath);
1804 FreeXid(xid);
1805 return -EINVAL;
1806 } 1800 }
1807 1801
1808 if (volume_info.UNCip && volume_info.UNC) { 1802 if (volume_info.UNCip && volume_info.UNC) {
@@ -1821,11 +1815,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1821 1815
1822 if (rc <= 0) { 1816 if (rc <= 0) {
1823 /* we failed translating address */ 1817 /* we failed translating address */
1824 kfree(volume_info.UNC); 1818 rc = -EINVAL;
1825 kfree(volume_info.password); 1819 goto out;
1826 kfree(volume_info.prepath);
1827 FreeXid(xid);
1828 return -EINVAL;
1829 } 1820 }
1830 1821
1831 cFYI(1, ("UNC: %s ip: %s", volume_info.UNC, volume_info.UNCip)); 1822 cFYI(1, ("UNC: %s ip: %s", volume_info.UNC, volume_info.UNCip));
@@ -1835,20 +1826,14 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1835 /* BB using ip addr as server name to connect to the 1826 /* BB using ip addr as server name to connect to the
1836 DFS root below */ 1827 DFS root below */
1837 cERROR(1, ("Connecting to DFS root not implemented yet")); 1828 cERROR(1, ("Connecting to DFS root not implemented yet"));
1838 kfree(volume_info.UNC); 1829 rc = -EINVAL;
1839 kfree(volume_info.password); 1830 goto out;
1840 kfree(volume_info.prepath);
1841 FreeXid(xid);
1842 return -EINVAL;
1843 } else /* which servers DFS root would we conect to */ { 1831 } else /* which servers DFS root would we conect to */ {
1844 cERROR(1, 1832 cERROR(1,
1845 ("CIFS mount error: No UNC path (e.g. -o " 1833 ("CIFS mount error: No UNC path (e.g. -o "
1846 "unc=//192.168.1.100/public) specified")); 1834 "unc=//192.168.1.100/public) specified"));
1847 kfree(volume_info.UNC); 1835 rc = -EINVAL;
1848 kfree(volume_info.password); 1836 goto out;
1849 kfree(volume_info.prepath);
1850 FreeXid(xid);
1851 return -EINVAL;
1852 } 1837 }
1853 1838
1854 /* this is needed for ASCII cp to Unicode converts */ 1839 /* this is needed for ASCII cp to Unicode converts */
@@ -1860,11 +1845,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1860 if (cifs_sb->local_nls == NULL) { 1845 if (cifs_sb->local_nls == NULL) {
1861 cERROR(1, ("CIFS mount error: iocharset %s not found", 1846 cERROR(1, ("CIFS mount error: iocharset %s not found",
1862 volume_info.iocharset)); 1847 volume_info.iocharset));
1863 kfree(volume_info.UNC); 1848 rc = -ELIBACC;
1864 kfree(volume_info.password); 1849 goto out;
1865 kfree(volume_info.prepath);
1866 FreeXid(xid);
1867 return -ELIBACC;
1868 } 1850 }
1869 } 1851 }
1870 1852
@@ -1878,11 +1860,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1878 &sin_server6.sin6_addr, 1860 &sin_server6.sin6_addr,
1879 volume_info.username, &srvTcp); 1861 volume_info.username, &srvTcp);
1880 } else { 1862 } else {
1881 kfree(volume_info.UNC); 1863 rc = -EINVAL;
1882 kfree(volume_info.password); 1864 goto out;
1883 kfree(volume_info.prepath);
1884 FreeXid(xid);
1885 return -EINVAL;
1886 } 1865 }
1887 1866
1888 if (srvTcp) { 1867 if (srvTcp) {
@@ -1906,22 +1885,14 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1906 "Aborting operation")); 1885 "Aborting operation"));
1907 if (csocket != NULL) 1886 if (csocket != NULL)
1908 sock_release(csocket); 1887 sock_release(csocket);
1909 kfree(volume_info.UNC); 1888 goto out;
1910 kfree(volume_info.password);
1911 kfree(volume_info.prepath);
1912 FreeXid(xid);
1913 return rc;
1914 } 1889 }
1915 1890
1916 srvTcp = kzalloc(sizeof(struct TCP_Server_Info), GFP_KERNEL); 1891 srvTcp = kzalloc(sizeof(struct TCP_Server_Info), GFP_KERNEL);
1917 if (!srvTcp) { 1892 if (!srvTcp) {
1918 rc = -ENOMEM; 1893 rc = -ENOMEM;
1919 sock_release(csocket); 1894 sock_release(csocket);
1920 kfree(volume_info.UNC); 1895 goto out;
1921 kfree(volume_info.password);
1922 kfree(volume_info.prepath);
1923 FreeXid(xid);
1924 return rc;
1925 } else { 1896 } else {
1926 memcpy(&srvTcp->addr.sockAddr, &sin_server, 1897 memcpy(&srvTcp->addr.sockAddr, &sin_server,
1927 sizeof(struct sockaddr_in)); 1898 sizeof(struct sockaddr_in));
@@ -1943,11 +1914,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1943 cERROR(1, ("error %d create cifsd thread", rc)); 1914 cERROR(1, ("error %d create cifsd thread", rc));
1944 srvTcp->tsk = NULL; 1915 srvTcp->tsk = NULL;
1945 sock_release(csocket); 1916 sock_release(csocket);
1946 kfree(volume_info.UNC); 1917 goto out;
1947 kfree(volume_info.password);
1948 kfree(volume_info.prepath);
1949 FreeXid(xid);
1950 return rc;
1951 } 1918 }
1952 wait_for_completion(&cifsd_complete); 1919 wait_for_completion(&cifsd_complete);
1953 rc = 0; 1920 rc = 0;
@@ -1962,8 +1929,6 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1962 if (existingCifsSes) { 1929 if (existingCifsSes) {
1963 pSesInfo = existingCifsSes; 1930 pSesInfo = existingCifsSes;
1964 cFYI(1, ("Existing smb sess found")); 1931 cFYI(1, ("Existing smb sess found"));
1965 kfree(volume_info.password);
1966 /* volume_info.UNC freed at end of function */
1967 } else if (!rc) { 1932 } else if (!rc) {
1968 cFYI(1, ("Existing smb sess not found")); 1933 cFYI(1, ("Existing smb sess not found"));
1969 pSesInfo = sesInfoAlloc(); 1934 pSesInfo = sesInfoAlloc();
@@ -1977,8 +1942,11 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1977 1942
1978 if (!rc) { 1943 if (!rc) {
1979 /* volume_info.password freed at unmount */ 1944 /* volume_info.password freed at unmount */
1980 if (volume_info.password) 1945 if (volume_info.password) {
1981 pSesInfo->password = volume_info.password; 1946 pSesInfo->password = volume_info.password;
1947 /* set to NULL to prevent freeing on exit */
1948 volume_info.password = NULL;
1949 }
1982 if (volume_info.username) 1950 if (volume_info.username)
1983 strncpy(pSesInfo->userName, 1951 strncpy(pSesInfo->userName,
1984 volume_info.username, 1952 volume_info.username,
@@ -2000,8 +1968,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
2000 up(&pSesInfo->sesSem); 1968 up(&pSesInfo->sesSem);
2001 if (!rc) 1969 if (!rc)
2002 atomic_inc(&srvTcp->socketUseCount); 1970 atomic_inc(&srvTcp->socketUseCount);
2003 } else 1971 }
2004 kfree(volume_info.password);
2005 } 1972 }
2006 1973
2007 /* search for existing tcon to this server share */ 1974 /* search for existing tcon to this server share */
@@ -2106,9 +2073,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
2106 "", cifs_sb->local_nls, 2073 "", cifs_sb->local_nls,
2107 cifs_sb->mnt_cifs_flags & 2074 cifs_sb->mnt_cifs_flags &
2108 CIFS_MOUNT_MAP_SPECIAL_CHR); 2075 CIFS_MOUNT_MAP_SPECIAL_CHR);
2109 kfree(volume_info.UNC); 2076 rc = -ENODEV;
2110 FreeXid(xid); 2077 goto out;
2111 return -ENODEV;
2112 } else { 2078 } else {
2113 /* BB Do we need to wrap sesSem around 2079 /* BB Do we need to wrap sesSem around
2114 * this TCon call and Unix SetFS as 2080 * this TCon call and Unix SetFS as
@@ -2231,6 +2197,12 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
2231 (in which case it is not needed anymore) but when new sesion is created 2197 (in which case it is not needed anymore) but when new sesion is created
2232 the password ptr is put in the new session structure (in which case the 2198 the password ptr is put in the new session structure (in which case the
2233 password will be freed at unmount time) */ 2199 password will be freed at unmount time) */
2200out:
2201 /* zero out password before freeing */
2202 if (volume_info.password != NULL) {
2203 memset(volume_info.password, 0, strlen(volume_info.password));
2204 kfree(volume_info.password);
2205 }
2234 kfree(volume_info.UNC); 2206 kfree(volume_info.UNC);
2235 kfree(volume_info.prepath); 2207 kfree(volume_info.prepath);
2236 FreeXid(xid); 2208 FreeXid(xid);