diff options
Diffstat (limited to 'fs/cifs/connect.c')
-rw-r--r-- | fs/cifs/connect.c | 141 |
1 files changed, 75 insertions, 66 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index c52a76ff4bb9..fd9147cdb5a9 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -438,9 +438,9 @@ incomplete_rcv: | |||
438 | csocket = server->ssocket; | 438 | csocket = server->ssocket; |
439 | wake_up(&server->response_q); | 439 | wake_up(&server->response_q); |
440 | continue; | 440 | continue; |
441 | } else if (length < 4) { | 441 | } else if (length < pdu_length) { |
442 | cFYI(1, ("less than four bytes received (%d bytes)", | 442 | cFYI(1, ("requested %d bytes but only got %d bytes", |
443 | length)); | 443 | pdu_length, length)); |
444 | pdu_length -= length; | 444 | pdu_length -= length; |
445 | msleep(1); | 445 | msleep(1); |
446 | goto incomplete_rcv; | 446 | goto incomplete_rcv; |
@@ -752,6 +752,7 @@ multi_t2_fnd: | |||
752 | } | 752 | } |
753 | write_unlock(&GlobalSMBSeslock); | 753 | write_unlock(&GlobalSMBSeslock); |
754 | 754 | ||
755 | kfree(server->hostname); | ||
755 | kfree(server); | 756 | kfree(server); |
756 | if (length > 0) | 757 | if (length > 0) |
757 | mempool_resize(cifs_req_poolp, length + cifs_min_rcv, | 758 | mempool_resize(cifs_req_poolp, length + cifs_min_rcv, |
@@ -760,6 +761,34 @@ multi_t2_fnd: | |||
760 | return 0; | 761 | return 0; |
761 | } | 762 | } |
762 | 763 | ||
764 | /* extract the host portion of the UNC string */ | ||
765 | static char * | ||
766 | extract_hostname(const char *unc) | ||
767 | { | ||
768 | const char *src; | ||
769 | char *dst, *delim; | ||
770 | unsigned int len; | ||
771 | |||
772 | /* skip double chars at beginning of string */ | ||
773 | /* BB: check validity of these bytes? */ | ||
774 | src = unc + 2; | ||
775 | |||
776 | /* delimiter between hostname and sharename is always '\\' now */ | ||
777 | delim = strchr(src, '\\'); | ||
778 | if (!delim) | ||
779 | return ERR_PTR(-EINVAL); | ||
780 | |||
781 | len = delim - src; | ||
782 | dst = kmalloc((len + 1), GFP_KERNEL); | ||
783 | if (dst == NULL) | ||
784 | return ERR_PTR(-ENOMEM); | ||
785 | |||
786 | memcpy(dst, src, len); | ||
787 | dst[len] = '\0'; | ||
788 | |||
789 | return dst; | ||
790 | } | ||
791 | |||
763 | static int | 792 | static int |
764 | cifs_parse_mount_options(char *options, const char *devname, | 793 | cifs_parse_mount_options(char *options, const char *devname, |
765 | struct smb_vol *vol) | 794 | struct smb_vol *vol) |
@@ -1781,11 +1810,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1781 | 1810 | ||
1782 | memset(&volume_info, 0, sizeof(struct smb_vol)); | 1811 | memset(&volume_info, 0, sizeof(struct smb_vol)); |
1783 | if (cifs_parse_mount_options(mount_data, devname, &volume_info)) { | 1812 | if (cifs_parse_mount_options(mount_data, devname, &volume_info)) { |
1784 | kfree(volume_info.UNC); | 1813 | rc = -EINVAL; |
1785 | kfree(volume_info.password); | 1814 | goto out; |
1786 | kfree(volume_info.prepath); | ||
1787 | FreeXid(xid); | ||
1788 | return -EINVAL; | ||
1789 | } | 1815 | } |
1790 | 1816 | ||
1791 | if (volume_info.nullauth) { | 1817 | if (volume_info.nullauth) { |
@@ -1798,11 +1824,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1798 | cifserror("No username specified"); | 1824 | cifserror("No username specified"); |
1799 | /* In userspace mount helper we can get user name from alternate | 1825 | /* In userspace mount helper we can get user name from alternate |
1800 | locations such as env variables and files on disk */ | 1826 | locations such as env variables and files on disk */ |
1801 | kfree(volume_info.UNC); | 1827 | rc = -EINVAL; |
1802 | kfree(volume_info.password); | 1828 | goto out; |
1803 | kfree(volume_info.prepath); | ||
1804 | FreeXid(xid); | ||
1805 | return -EINVAL; | ||
1806 | } | 1829 | } |
1807 | 1830 | ||
1808 | if (volume_info.UNCip && volume_info.UNC) { | 1831 | if (volume_info.UNCip && volume_info.UNC) { |
@@ -1821,11 +1844,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1821 | 1844 | ||
1822 | if (rc <= 0) { | 1845 | if (rc <= 0) { |
1823 | /* we failed translating address */ | 1846 | /* we failed translating address */ |
1824 | kfree(volume_info.UNC); | 1847 | rc = -EINVAL; |
1825 | kfree(volume_info.password); | 1848 | goto out; |
1826 | kfree(volume_info.prepath); | ||
1827 | FreeXid(xid); | ||
1828 | return -EINVAL; | ||
1829 | } | 1849 | } |
1830 | 1850 | ||
1831 | cFYI(1, ("UNC: %s ip: %s", volume_info.UNC, volume_info.UNCip)); | 1851 | cFYI(1, ("UNC: %s ip: %s", volume_info.UNC, volume_info.UNCip)); |
@@ -1835,20 +1855,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 | 1855 | /* BB using ip addr as server name to connect to the |
1836 | DFS root below */ | 1856 | DFS root below */ |
1837 | cERROR(1, ("Connecting to DFS root not implemented yet")); | 1857 | cERROR(1, ("Connecting to DFS root not implemented yet")); |
1838 | kfree(volume_info.UNC); | 1858 | rc = -EINVAL; |
1839 | kfree(volume_info.password); | 1859 | goto out; |
1840 | kfree(volume_info.prepath); | ||
1841 | FreeXid(xid); | ||
1842 | return -EINVAL; | ||
1843 | } else /* which servers DFS root would we conect to */ { | 1860 | } else /* which servers DFS root would we conect to */ { |
1844 | cERROR(1, | 1861 | cERROR(1, |
1845 | ("CIFS mount error: No UNC path (e.g. -o " | 1862 | ("CIFS mount error: No UNC path (e.g. -o " |
1846 | "unc=//192.168.1.100/public) specified")); | 1863 | "unc=//192.168.1.100/public) specified")); |
1847 | kfree(volume_info.UNC); | 1864 | rc = -EINVAL; |
1848 | kfree(volume_info.password); | 1865 | goto out; |
1849 | kfree(volume_info.prepath); | ||
1850 | FreeXid(xid); | ||
1851 | return -EINVAL; | ||
1852 | } | 1866 | } |
1853 | 1867 | ||
1854 | /* this is needed for ASCII cp to Unicode converts */ | 1868 | /* this is needed for ASCII cp to Unicode converts */ |
@@ -1860,11 +1874,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1860 | if (cifs_sb->local_nls == NULL) { | 1874 | if (cifs_sb->local_nls == NULL) { |
1861 | cERROR(1, ("CIFS mount error: iocharset %s not found", | 1875 | cERROR(1, ("CIFS mount error: iocharset %s not found", |
1862 | volume_info.iocharset)); | 1876 | volume_info.iocharset)); |
1863 | kfree(volume_info.UNC); | 1877 | rc = -ELIBACC; |
1864 | kfree(volume_info.password); | 1878 | goto out; |
1865 | kfree(volume_info.prepath); | ||
1866 | FreeXid(xid); | ||
1867 | return -ELIBACC; | ||
1868 | } | 1879 | } |
1869 | } | 1880 | } |
1870 | 1881 | ||
@@ -1878,11 +1889,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1878 | &sin_server6.sin6_addr, | 1889 | &sin_server6.sin6_addr, |
1879 | volume_info.username, &srvTcp); | 1890 | volume_info.username, &srvTcp); |
1880 | } else { | 1891 | } else { |
1881 | kfree(volume_info.UNC); | 1892 | rc = -EINVAL; |
1882 | kfree(volume_info.password); | 1893 | goto out; |
1883 | kfree(volume_info.prepath); | ||
1884 | FreeXid(xid); | ||
1885 | return -EINVAL; | ||
1886 | } | 1894 | } |
1887 | 1895 | ||
1888 | if (srvTcp) { | 1896 | if (srvTcp) { |
@@ -1906,22 +1914,14 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1906 | "Aborting operation")); | 1914 | "Aborting operation")); |
1907 | if (csocket != NULL) | 1915 | if (csocket != NULL) |
1908 | sock_release(csocket); | 1916 | sock_release(csocket); |
1909 | kfree(volume_info.UNC); | 1917 | goto out; |
1910 | kfree(volume_info.password); | ||
1911 | kfree(volume_info.prepath); | ||
1912 | FreeXid(xid); | ||
1913 | return rc; | ||
1914 | } | 1918 | } |
1915 | 1919 | ||
1916 | srvTcp = kzalloc(sizeof(struct TCP_Server_Info), GFP_KERNEL); | 1920 | srvTcp = kzalloc(sizeof(struct TCP_Server_Info), GFP_KERNEL); |
1917 | if (!srvTcp) { | 1921 | if (!srvTcp) { |
1918 | rc = -ENOMEM; | 1922 | rc = -ENOMEM; |
1919 | sock_release(csocket); | 1923 | sock_release(csocket); |
1920 | kfree(volume_info.UNC); | 1924 | goto out; |
1921 | kfree(volume_info.password); | ||
1922 | kfree(volume_info.prepath); | ||
1923 | FreeXid(xid); | ||
1924 | return rc; | ||
1925 | } else { | 1925 | } else { |
1926 | memcpy(&srvTcp->addr.sockAddr, &sin_server, | 1926 | memcpy(&srvTcp->addr.sockAddr, &sin_server, |
1927 | sizeof(struct sockaddr_in)); | 1927 | sizeof(struct sockaddr_in)); |
@@ -1929,6 +1929,12 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1929 | /* BB Add code for ipv6 case too */ | 1929 | /* BB Add code for ipv6 case too */ |
1930 | srvTcp->ssocket = csocket; | 1930 | srvTcp->ssocket = csocket; |
1931 | srvTcp->protocolType = IPV4; | 1931 | srvTcp->protocolType = IPV4; |
1932 | srvTcp->hostname = extract_hostname(volume_info.UNC); | ||
1933 | if (IS_ERR(srvTcp->hostname)) { | ||
1934 | rc = PTR_ERR(srvTcp->hostname); | ||
1935 | sock_release(csocket); | ||
1936 | goto out; | ||
1937 | } | ||
1932 | init_waitqueue_head(&srvTcp->response_q); | 1938 | init_waitqueue_head(&srvTcp->response_q); |
1933 | init_waitqueue_head(&srvTcp->request_q); | 1939 | init_waitqueue_head(&srvTcp->request_q); |
1934 | INIT_LIST_HEAD(&srvTcp->pending_mid_q); | 1940 | INIT_LIST_HEAD(&srvTcp->pending_mid_q); |
@@ -1938,16 +1944,13 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1938 | srvTcp->tcpStatus = CifsNew; | 1944 | srvTcp->tcpStatus = CifsNew; |
1939 | init_MUTEX(&srvTcp->tcpSem); | 1945 | init_MUTEX(&srvTcp->tcpSem); |
1940 | srvTcp->tsk = kthread_run((void *)(void *)cifs_demultiplex_thread, srvTcp, "cifsd"); | 1946 | srvTcp->tsk = kthread_run((void *)(void *)cifs_demultiplex_thread, srvTcp, "cifsd"); |
1941 | if ( IS_ERR(srvTcp->tsk) ) { | 1947 | if (IS_ERR(srvTcp->tsk)) { |
1942 | rc = PTR_ERR(srvTcp->tsk); | 1948 | rc = PTR_ERR(srvTcp->tsk); |
1943 | cERROR(1, ("error %d create cifsd thread", rc)); | 1949 | cERROR(1, ("error %d create cifsd thread", rc)); |
1944 | srvTcp->tsk = NULL; | 1950 | srvTcp->tsk = NULL; |
1945 | sock_release(csocket); | 1951 | sock_release(csocket); |
1946 | kfree(volume_info.UNC); | 1952 | kfree(srvTcp->hostname); |
1947 | kfree(volume_info.password); | 1953 | goto out; |
1948 | kfree(volume_info.prepath); | ||
1949 | FreeXid(xid); | ||
1950 | return rc; | ||
1951 | } | 1954 | } |
1952 | wait_for_completion(&cifsd_complete); | 1955 | wait_for_completion(&cifsd_complete); |
1953 | rc = 0; | 1956 | rc = 0; |
@@ -1962,8 +1965,6 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1962 | if (existingCifsSes) { | 1965 | if (existingCifsSes) { |
1963 | pSesInfo = existingCifsSes; | 1966 | pSesInfo = existingCifsSes; |
1964 | cFYI(1, ("Existing smb sess found")); | 1967 | cFYI(1, ("Existing smb sess found")); |
1965 | kfree(volume_info.password); | ||
1966 | /* volume_info.UNC freed at end of function */ | ||
1967 | } else if (!rc) { | 1968 | } else if (!rc) { |
1968 | cFYI(1, ("Existing smb sess not found")); | 1969 | cFYI(1, ("Existing smb sess not found")); |
1969 | pSesInfo = sesInfoAlloc(); | 1970 | pSesInfo = sesInfoAlloc(); |
@@ -1977,8 +1978,11 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1977 | 1978 | ||
1978 | if (!rc) { | 1979 | if (!rc) { |
1979 | /* volume_info.password freed at unmount */ | 1980 | /* volume_info.password freed at unmount */ |
1980 | if (volume_info.password) | 1981 | if (volume_info.password) { |
1981 | pSesInfo->password = volume_info.password; | 1982 | pSesInfo->password = volume_info.password; |
1983 | /* set to NULL to prevent freeing on exit */ | ||
1984 | volume_info.password = NULL; | ||
1985 | } | ||
1982 | if (volume_info.username) | 1986 | if (volume_info.username) |
1983 | strncpy(pSesInfo->userName, | 1987 | strncpy(pSesInfo->userName, |
1984 | volume_info.username, | 1988 | volume_info.username, |
@@ -2000,8 +2004,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
2000 | up(&pSesInfo->sesSem); | 2004 | up(&pSesInfo->sesSem); |
2001 | if (!rc) | 2005 | if (!rc) |
2002 | atomic_inc(&srvTcp->socketUseCount); | 2006 | atomic_inc(&srvTcp->socketUseCount); |
2003 | } else | 2007 | } |
2004 | kfree(volume_info.password); | ||
2005 | } | 2008 | } |
2006 | 2009 | ||
2007 | /* search for existing tcon to this server share */ | 2010 | /* search for existing tcon to this server share */ |
@@ -2106,9 +2109,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
2106 | "", cifs_sb->local_nls, | 2109 | "", cifs_sb->local_nls, |
2107 | cifs_sb->mnt_cifs_flags & | 2110 | cifs_sb->mnt_cifs_flags & |
2108 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 2111 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
2109 | kfree(volume_info.UNC); | 2112 | rc = -ENODEV; |
2110 | FreeXid(xid); | 2113 | goto out; |
2111 | return -ENODEV; | ||
2112 | } else { | 2114 | } else { |
2113 | /* BB Do we need to wrap sesSem around | 2115 | /* BB Do we need to wrap sesSem around |
2114 | * this TCon call and Unix SetFS as | 2116 | * this TCon call and Unix SetFS as |
@@ -2231,6 +2233,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 | 2233 | (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 | 2234 | the password ptr is put in the new session structure (in which case the |
2233 | password will be freed at unmount time) */ | 2235 | password will be freed at unmount time) */ |
2236 | out: | ||
2237 | /* zero out password before freeing */ | ||
2238 | if (volume_info.password != NULL) { | ||
2239 | memset(volume_info.password, 0, strlen(volume_info.password)); | ||
2240 | kfree(volume_info.password); | ||
2241 | } | ||
2234 | kfree(volume_info.UNC); | 2242 | kfree(volume_info.UNC); |
2235 | kfree(volume_info.prepath); | 2243 | kfree(volume_info.prepath); |
2236 | FreeXid(xid); | 2244 | FreeXid(xid); |
@@ -2374,7 +2382,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
2374 | pSMB->req_no_secext.ByteCount = cpu_to_le16(count); | 2382 | pSMB->req_no_secext.ByteCount = cpu_to_le16(count); |
2375 | 2383 | ||
2376 | rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, | 2384 | rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, |
2377 | &bytes_returned, 1); | 2385 | &bytes_returned, CIFS_LONG_OP); |
2378 | if (rc) { | 2386 | if (rc) { |
2379 | /* rc = map_smb_to_linux_error(smb_buffer_response); now done in SendReceive */ | 2387 | /* rc = map_smb_to_linux_error(smb_buffer_response); now done in SendReceive */ |
2380 | } else if ((smb_buffer_response->WordCount == 3) | 2388 | } else if ((smb_buffer_response->WordCount == 3) |
@@ -2678,7 +2686,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, | |||
2678 | pSMB->req.ByteCount = cpu_to_le16(count); | 2686 | pSMB->req.ByteCount = cpu_to_le16(count); |
2679 | 2687 | ||
2680 | rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, | 2688 | rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, |
2681 | &bytes_returned, 1); | 2689 | &bytes_returned, CIFS_LONG_OP); |
2682 | 2690 | ||
2683 | if (smb_buffer_response->Status.CifsError == | 2691 | if (smb_buffer_response->Status.CifsError == |
2684 | cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED)) | 2692 | cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED)) |
@@ -3105,7 +3113,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
3105 | pSMB->req.ByteCount = cpu_to_le16(count); | 3113 | pSMB->req.ByteCount = cpu_to_le16(count); |
3106 | 3114 | ||
3107 | rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, | 3115 | rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, |
3108 | &bytes_returned, 1); | 3116 | &bytes_returned, CIFS_LONG_OP); |
3109 | if (rc) { | 3117 | if (rc) { |
3110 | /* rc = map_smb_to_linux_error(smb_buffer_response) done in SendReceive now */ | 3118 | /* rc = map_smb_to_linux_error(smb_buffer_response) done in SendReceive now */ |
3111 | } else if ((smb_buffer_response->WordCount == 3) || | 3119 | } else if ((smb_buffer_response->WordCount == 3) || |
@@ -3381,7 +3389,8 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, | |||
3381 | pSMB->hdr.smb_buf_length += count; | 3389 | pSMB->hdr.smb_buf_length += count; |
3382 | pSMB->ByteCount = cpu_to_le16(count); | 3390 | pSMB->ByteCount = cpu_to_le16(count); |
3383 | 3391 | ||
3384 | rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, 0); | 3392 | rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, |
3393 | CIFS_STD_OP); | ||
3385 | 3394 | ||
3386 | /* if (rc) rc = map_smb_to_linux_error(smb_buffer_response); */ | 3395 | /* if (rc) rc = map_smb_to_linux_error(smb_buffer_response); */ |
3387 | /* above now done in SendReceive */ | 3396 | /* above now done in SendReceive */ |