diff options
Diffstat (limited to 'fs/cifs/cifssmb.c')
-rw-r--r-- | fs/cifs/cifssmb.c | 228 |
1 files changed, 147 insertions, 81 deletions
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index f0d9a485d095..9409524e4bf8 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
@@ -647,8 +647,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) | |||
647 | count - 16, | 647 | count - 16, |
648 | &server->secType); | 648 | &server->secType); |
649 | if (rc == 1) { | 649 | if (rc == 1) { |
650 | /* BB Need to fill struct for sessetup here */ | 650 | rc = 0; |
651 | rc = -EOPNOTSUPP; | ||
652 | } else { | 651 | } else { |
653 | rc = -EINVAL; | 652 | rc = -EINVAL; |
654 | } | 653 | } |
@@ -699,9 +698,7 @@ int | |||
699 | CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon) | 698 | CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon) |
700 | { | 699 | { |
701 | struct smb_hdr *smb_buffer; | 700 | struct smb_hdr *smb_buffer; |
702 | struct smb_hdr *smb_buffer_response; /* BB removeme BB */ | ||
703 | int rc = 0; | 701 | int rc = 0; |
704 | int length; | ||
705 | 702 | ||
706 | cFYI(1, ("In tree disconnect")); | 703 | cFYI(1, ("In tree disconnect")); |
707 | /* | 704 | /* |
@@ -738,16 +735,12 @@ CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon) | |||
738 | if (rc) { | 735 | if (rc) { |
739 | up(&tcon->tconSem); | 736 | up(&tcon->tconSem); |
740 | return rc; | 737 | return rc; |
741 | } else { | ||
742 | smb_buffer_response = smb_buffer; /* BB removeme BB */ | ||
743 | } | 738 | } |
744 | rc = SendReceive(xid, tcon->ses, smb_buffer, smb_buffer_response, | 739 | |
745 | &length, 0); | 740 | rc = SendReceiveNoRsp(xid, tcon->ses, smb_buffer, 0); |
746 | if (rc) | 741 | if (rc) |
747 | cFYI(1, ("Tree disconnect failed %d", rc)); | 742 | cFYI(1, ("Tree disconnect failed %d", rc)); |
748 | 743 | ||
749 | if (smb_buffer) | ||
750 | cifs_small_buf_release(smb_buffer); | ||
751 | up(&tcon->tconSem); | 744 | up(&tcon->tconSem); |
752 | 745 | ||
753 | /* No need to return error on this operation if tid invalidated and | 746 | /* No need to return error on this operation if tid invalidated and |
@@ -761,10 +754,8 @@ CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon) | |||
761 | int | 754 | int |
762 | CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses) | 755 | CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses) |
763 | { | 756 | { |
764 | struct smb_hdr *smb_buffer_response; | ||
765 | LOGOFF_ANDX_REQ *pSMB; | 757 | LOGOFF_ANDX_REQ *pSMB; |
766 | int rc = 0; | 758 | int rc = 0; |
767 | int length; | ||
768 | 759 | ||
769 | cFYI(1, ("In SMBLogoff for session disconnect")); | 760 | cFYI(1, ("In SMBLogoff for session disconnect")); |
770 | if (ses) | 761 | if (ses) |
@@ -783,8 +774,6 @@ CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses) | |||
783 | return rc; | 774 | return rc; |
784 | } | 775 | } |
785 | 776 | ||
786 | smb_buffer_response = (struct smb_hdr *)pSMB; /* BB removeme BB */ | ||
787 | |||
788 | if (ses->server) { | 777 | if (ses->server) { |
789 | pSMB->hdr.Mid = GetNextMid(ses->server); | 778 | pSMB->hdr.Mid = GetNextMid(ses->server); |
790 | 779 | ||
@@ -796,8 +785,7 @@ CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses) | |||
796 | pSMB->hdr.Uid = ses->Suid; | 785 | pSMB->hdr.Uid = ses->Suid; |
797 | 786 | ||
798 | pSMB->AndXCommand = 0xFF; | 787 | pSMB->AndXCommand = 0xFF; |
799 | rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB, | 788 | rc = SendReceiveNoRsp(xid, ses, (struct smb_hdr *) pSMB, 0); |
800 | smb_buffer_response, &length, 0); | ||
801 | if (ses->server) { | 789 | if (ses->server) { |
802 | atomic_dec(&ses->server->socketUseCount); | 790 | atomic_dec(&ses->server->socketUseCount); |
803 | if (atomic_read(&ses->server->socketUseCount) == 0) { | 791 | if (atomic_read(&ses->server->socketUseCount) == 0) { |
@@ -808,7 +796,6 @@ CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses) | |||
808 | } | 796 | } |
809 | } | 797 | } |
810 | up(&ses->sesSem); | 798 | up(&ses->sesSem); |
811 | cifs_small_buf_release(pSMB); | ||
812 | 799 | ||
813 | /* if session dead then we do not need to do ulogoff, | 800 | /* if session dead then we do not need to do ulogoff, |
814 | since server closed smb session, no sense reporting | 801 | since server closed smb session, no sense reporting |
@@ -1256,7 +1243,7 @@ OldOpenRetry: | |||
1256 | pSMB->ByteCount = cpu_to_le16(count); | 1243 | pSMB->ByteCount = cpu_to_le16(count); |
1257 | /* long_op set to 1 to allow for oplock break timeouts */ | 1244 | /* long_op set to 1 to allow for oplock break timeouts */ |
1258 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 1245 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
1259 | (struct smb_hdr *) pSMBr, &bytes_returned, 1); | 1246 | (struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP); |
1260 | cifs_stats_inc(&tcon->num_opens); | 1247 | cifs_stats_inc(&tcon->num_opens); |
1261 | if (rc) { | 1248 | if (rc) { |
1262 | cFYI(1, ("Error in Open = %d", rc)); | 1249 | cFYI(1, ("Error in Open = %d", rc)); |
@@ -1369,7 +1356,7 @@ openRetry: | |||
1369 | pSMB->ByteCount = cpu_to_le16(count); | 1356 | pSMB->ByteCount = cpu_to_le16(count); |
1370 | /* long_op set to 1 to allow for oplock break timeouts */ | 1357 | /* long_op set to 1 to allow for oplock break timeouts */ |
1371 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 1358 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
1372 | (struct smb_hdr *) pSMBr, &bytes_returned, 1); | 1359 | (struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP); |
1373 | cifs_stats_inc(&tcon->num_opens); | 1360 | cifs_stats_inc(&tcon->num_opens); |
1374 | if (rc) { | 1361 | if (rc) { |
1375 | cFYI(1, ("Error in Open = %d", rc)); | 1362 | cFYI(1, ("Error in Open = %d", rc)); |
@@ -1447,7 +1434,7 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid, | |||
1447 | iov[0].iov_base = (char *)pSMB; | 1434 | iov[0].iov_base = (char *)pSMB; |
1448 | iov[0].iov_len = pSMB->hdr.smb_buf_length + 4; | 1435 | iov[0].iov_len = pSMB->hdr.smb_buf_length + 4; |
1449 | rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */, | 1436 | rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */, |
1450 | &resp_buf_type, 0 /* not long op */, 1 /* log err */ ); | 1437 | &resp_buf_type, CIFS_STD_OP | CIFS_LOG_ERROR); |
1451 | cifs_stats_inc(&tcon->num_reads); | 1438 | cifs_stats_inc(&tcon->num_reads); |
1452 | pSMBr = (READ_RSP *)iov[0].iov_base; | 1439 | pSMBr = (READ_RSP *)iov[0].iov_base; |
1453 | if (rc) { | 1440 | if (rc) { |
@@ -1666,7 +1653,7 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon, | |||
1666 | 1653 | ||
1667 | 1654 | ||
1668 | rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type, | 1655 | rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type, |
1669 | long_op, 0 /* do not log STATUS code */ ); | 1656 | long_op); |
1670 | cifs_stats_inc(&tcon->num_writes); | 1657 | cifs_stats_inc(&tcon->num_writes); |
1671 | if (rc) { | 1658 | if (rc) { |
1672 | cFYI(1, ("Send error Write2 = %d", rc)); | 1659 | cFYI(1, ("Send error Write2 = %d", rc)); |
@@ -1708,7 +1695,7 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, | |||
1708 | int timeout = 0; | 1695 | int timeout = 0; |
1709 | __u16 count; | 1696 | __u16 count; |
1710 | 1697 | ||
1711 | cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d", waitFlag, numLock)); | 1698 | cFYI(1, ("CIFSSMBLock timeout %d numLock %d", waitFlag, numLock)); |
1712 | rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB); | 1699 | rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB); |
1713 | 1700 | ||
1714 | if (rc) | 1701 | if (rc) |
@@ -1717,10 +1704,10 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, | |||
1717 | pSMBr = (LOCK_RSP *)pSMB; /* BB removeme BB */ | 1704 | pSMBr = (LOCK_RSP *)pSMB; /* BB removeme BB */ |
1718 | 1705 | ||
1719 | if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) { | 1706 | if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) { |
1720 | timeout = -1; /* no response expected */ | 1707 | timeout = CIFS_ASYNC_OP; /* no response expected */ |
1721 | pSMB->Timeout = 0; | 1708 | pSMB->Timeout = 0; |
1722 | } else if (waitFlag == TRUE) { | 1709 | } else if (waitFlag == TRUE) { |
1723 | timeout = 3; /* blocking operation, no timeout */ | 1710 | timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */ |
1724 | pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */ | 1711 | pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */ |
1725 | } else { | 1712 | } else { |
1726 | pSMB->Timeout = 0; | 1713 | pSMB->Timeout = 0; |
@@ -1750,15 +1737,16 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, | |||
1750 | if (waitFlag) { | 1737 | if (waitFlag) { |
1751 | rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB, | 1738 | rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB, |
1752 | (struct smb_hdr *) pSMBr, &bytes_returned); | 1739 | (struct smb_hdr *) pSMBr, &bytes_returned); |
1740 | cifs_small_buf_release(pSMB); | ||
1753 | } else { | 1741 | } else { |
1754 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 1742 | rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *)pSMB, |
1755 | (struct smb_hdr *) pSMBr, &bytes_returned, timeout); | 1743 | timeout); |
1744 | /* SMB buffer freed by function above */ | ||
1756 | } | 1745 | } |
1757 | cifs_stats_inc(&tcon->num_locks); | 1746 | cifs_stats_inc(&tcon->num_locks); |
1758 | if (rc) { | 1747 | if (rc) { |
1759 | cFYI(1, ("Send error in Lock = %d", rc)); | 1748 | cFYI(1, ("Send error in Lock = %d", rc)); |
1760 | } | 1749 | } |
1761 | cifs_small_buf_release(pSMB); | ||
1762 | 1750 | ||
1763 | /* Note: On -EAGAIN error only caller can retry on handle based calls | 1751 | /* Note: On -EAGAIN error only caller can retry on handle based calls |
1764 | since file handle passed in no longer valid */ | 1752 | since file handle passed in no longer valid */ |
@@ -1777,7 +1765,9 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon, | |||
1777 | int rc = 0; | 1765 | int rc = 0; |
1778 | int timeout = 0; | 1766 | int timeout = 0; |
1779 | int bytes_returned = 0; | 1767 | int bytes_returned = 0; |
1768 | int resp_buf_type = 0; | ||
1780 | __u16 params, param_offset, offset, byte_count, count; | 1769 | __u16 params, param_offset, offset, byte_count, count; |
1770 | struct kvec iov[1]; | ||
1781 | 1771 | ||
1782 | cFYI(1, ("Posix Lock")); | 1772 | cFYI(1, ("Posix Lock")); |
1783 | 1773 | ||
@@ -1819,7 +1809,7 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon, | |||
1819 | 1809 | ||
1820 | parm_data->lock_type = cpu_to_le16(lock_type); | 1810 | parm_data->lock_type = cpu_to_le16(lock_type); |
1821 | if (waitFlag) { | 1811 | if (waitFlag) { |
1822 | timeout = 3; /* blocking operation, no timeout */ | 1812 | timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */ |
1823 | parm_data->lock_flags = cpu_to_le16(1); | 1813 | parm_data->lock_flags = cpu_to_le16(1); |
1824 | pSMB->Timeout = cpu_to_le32(-1); | 1814 | pSMB->Timeout = cpu_to_le32(-1); |
1825 | } else | 1815 | } else |
@@ -1839,8 +1829,13 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon, | |||
1839 | rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB, | 1829 | rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB, |
1840 | (struct smb_hdr *) pSMBr, &bytes_returned); | 1830 | (struct smb_hdr *) pSMBr, &bytes_returned); |
1841 | } else { | 1831 | } else { |
1842 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 1832 | iov[0].iov_base = (char *)pSMB; |
1843 | (struct smb_hdr *) pSMBr, &bytes_returned, timeout); | 1833 | iov[0].iov_len = pSMB->hdr.smb_buf_length + 4; |
1834 | rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */, | ||
1835 | &resp_buf_type, timeout); | ||
1836 | pSMB = NULL; /* request buf already freed by SendReceive2. Do | ||
1837 | not try to free it twice below on exit */ | ||
1838 | pSMBr = (struct smb_com_transaction2_sfi_rsp *)iov[0].iov_base; | ||
1844 | } | 1839 | } |
1845 | 1840 | ||
1846 | if (rc) { | 1841 | if (rc) { |
@@ -1875,6 +1870,11 @@ plk_err_exit: | |||
1875 | if (pSMB) | 1870 | if (pSMB) |
1876 | cifs_small_buf_release(pSMB); | 1871 | cifs_small_buf_release(pSMB); |
1877 | 1872 | ||
1873 | if (resp_buf_type == CIFS_SMALL_BUFFER) | ||
1874 | cifs_small_buf_release(iov[0].iov_base); | ||
1875 | else if (resp_buf_type == CIFS_LARGE_BUFFER) | ||
1876 | cifs_buf_release(iov[0].iov_base); | ||
1877 | |||
1878 | /* Note: On -EAGAIN error only caller can retry on handle based calls | 1878 | /* Note: On -EAGAIN error only caller can retry on handle based calls |
1879 | since file handle passed in no longer valid */ | 1879 | since file handle passed in no longer valid */ |
1880 | 1880 | ||
@@ -1887,8 +1887,6 @@ CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id) | |||
1887 | { | 1887 | { |
1888 | int rc = 0; | 1888 | int rc = 0; |
1889 | CLOSE_REQ *pSMB = NULL; | 1889 | CLOSE_REQ *pSMB = NULL; |
1890 | CLOSE_RSP *pSMBr = NULL; | ||
1891 | int bytes_returned; | ||
1892 | cFYI(1, ("In CIFSSMBClose")); | 1890 | cFYI(1, ("In CIFSSMBClose")); |
1893 | 1891 | ||
1894 | /* do not retry on dead session on close */ | 1892 | /* do not retry on dead session on close */ |
@@ -1898,13 +1896,10 @@ CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id) | |||
1898 | if (rc) | 1896 | if (rc) |
1899 | return rc; | 1897 | return rc; |
1900 | 1898 | ||
1901 | pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */ | ||
1902 | |||
1903 | pSMB->FileID = (__u16) smb_file_id; | 1899 | pSMB->FileID = (__u16) smb_file_id; |
1904 | pSMB->LastWriteTime = 0xFFFFFFFF; | 1900 | pSMB->LastWriteTime = 0xFFFFFFFF; |
1905 | pSMB->ByteCount = 0; | 1901 | pSMB->ByteCount = 0; |
1906 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 1902 | rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); |
1907 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | ||
1908 | cifs_stats_inc(&tcon->num_closes); | 1903 | cifs_stats_inc(&tcon->num_closes); |
1909 | if (rc) { | 1904 | if (rc) { |
1910 | if (rc != -EINTR) { | 1905 | if (rc != -EINTR) { |
@@ -1913,8 +1908,6 @@ CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id) | |||
1913 | } | 1908 | } |
1914 | } | 1909 | } |
1915 | 1910 | ||
1916 | cifs_small_buf_release(pSMB); | ||
1917 | |||
1918 | /* Since session is dead, file will be closed on server already */ | 1911 | /* Since session is dead, file will be closed on server already */ |
1919 | if (rc == -EAGAIN) | 1912 | if (rc == -EAGAIN) |
1920 | rc = 0; | 1913 | rc = 0; |
@@ -2486,6 +2479,7 @@ querySymLinkRetry: | |||
2486 | return rc; | 2479 | return rc; |
2487 | } | 2480 | } |
2488 | 2481 | ||
2482 | #ifdef CONFIG_CIFS_EXPERIMENTAL | ||
2489 | /* Initialize NT TRANSACT SMB into small smb request buffer. | 2483 | /* Initialize NT TRANSACT SMB into small smb request buffer. |
2490 | This assumes that all NT TRANSACTS that we init here have | 2484 | This assumes that all NT TRANSACTS that we init here have |
2491 | total parm and data under about 400 bytes (to fit in small cifs | 2485 | total parm and data under about 400 bytes (to fit in small cifs |
@@ -2494,7 +2488,7 @@ querySymLinkRetry: | |||
2494 | MaxSetupCount (size of returned setup area) and | 2488 | MaxSetupCount (size of returned setup area) and |
2495 | MaxParameterCount (returned parms size) must be set by caller */ | 2489 | MaxParameterCount (returned parms size) must be set by caller */ |
2496 | static int | 2490 | static int |
2497 | smb_init_ntransact(const __u16 sub_command, const int setup_count, | 2491 | smb_init_nttransact(const __u16 sub_command, const int setup_count, |
2498 | const int parm_len, struct cifsTconInfo *tcon, | 2492 | const int parm_len, struct cifsTconInfo *tcon, |
2499 | void **ret_buf) | 2493 | void **ret_buf) |
2500 | { | 2494 | { |
@@ -2525,12 +2519,15 @@ smb_init_ntransact(const __u16 sub_command, const int setup_count, | |||
2525 | 2519 | ||
2526 | static int | 2520 | static int |
2527 | validate_ntransact(char *buf, char **ppparm, char **ppdata, | 2521 | validate_ntransact(char *buf, char **ppparm, char **ppdata, |
2528 | int *pdatalen, int *pparmlen) | 2522 | __u32 *pparmlen, __u32 *pdatalen) |
2529 | { | 2523 | { |
2530 | char *end_of_smb; | 2524 | char *end_of_smb; |
2531 | __u32 data_count, data_offset, parm_count, parm_offset; | 2525 | __u32 data_count, data_offset, parm_count, parm_offset; |
2532 | struct smb_com_ntransact_rsp *pSMBr; | 2526 | struct smb_com_ntransact_rsp *pSMBr; |
2533 | 2527 | ||
2528 | *pdatalen = 0; | ||
2529 | *pparmlen = 0; | ||
2530 | |||
2534 | if (buf == NULL) | 2531 | if (buf == NULL) |
2535 | return -EINVAL; | 2532 | return -EINVAL; |
2536 | 2533 | ||
@@ -2567,8 +2564,11 @@ validate_ntransact(char *buf, char **ppparm, char **ppdata, | |||
2567 | cFYI(1, ("parm count and data count larger than SMB")); | 2564 | cFYI(1, ("parm count and data count larger than SMB")); |
2568 | return -EINVAL; | 2565 | return -EINVAL; |
2569 | } | 2566 | } |
2567 | *pdatalen = data_count; | ||
2568 | *pparmlen = parm_count; | ||
2570 | return 0; | 2569 | return 0; |
2571 | } | 2570 | } |
2571 | #endif /* CIFS_EXPERIMENTAL */ | ||
2572 | 2572 | ||
2573 | int | 2573 | int |
2574 | CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon, | 2574 | CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon, |
@@ -3067,8 +3067,7 @@ GetExtAttrOut: | |||
3067 | /* Get Security Descriptor (by handle) from remote server for a file or dir */ | 3067 | /* Get Security Descriptor (by handle) from remote server for a file or dir */ |
3068 | int | 3068 | int |
3069 | CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid, | 3069 | CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid, |
3070 | /* BB fix up return info */ char *acl_inf, const int buflen, | 3070 | struct cifs_ntsd **acl_inf, __u32 *pbuflen) |
3071 | const int acl_type) | ||
3072 | { | 3071 | { |
3073 | int rc = 0; | 3072 | int rc = 0; |
3074 | int buf_type = 0; | 3073 | int buf_type = 0; |
@@ -3077,7 +3076,10 @@ CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid, | |||
3077 | 3076 | ||
3078 | cFYI(1, ("GetCifsACL")); | 3077 | cFYI(1, ("GetCifsACL")); |
3079 | 3078 | ||
3080 | rc = smb_init_ntransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0, | 3079 | *pbuflen = 0; |
3080 | *acl_inf = NULL; | ||
3081 | |||
3082 | rc = smb_init_nttransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0, | ||
3081 | 8 /* parm len */, tcon, (void **) &pSMB); | 3083 | 8 /* parm len */, tcon, (void **) &pSMB); |
3082 | if (rc) | 3084 | if (rc) |
3083 | return rc; | 3085 | return rc; |
@@ -3094,39 +3096,57 @@ CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid, | |||
3094 | iov[0].iov_len = pSMB->hdr.smb_buf_length + 4; | 3096 | iov[0].iov_len = pSMB->hdr.smb_buf_length + 4; |
3095 | 3097 | ||
3096 | rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type, | 3098 | rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type, |
3097 | 0 /* not long op */, 0 /* do not log STATUS codes */ ); | 3099 | CIFS_STD_OP); |
3098 | cifs_stats_inc(&tcon->num_acl_get); | 3100 | cifs_stats_inc(&tcon->num_acl_get); |
3099 | if (rc) { | 3101 | if (rc) { |
3100 | cFYI(1, ("Send error in QuerySecDesc = %d", rc)); | 3102 | cFYI(1, ("Send error in QuerySecDesc = %d", rc)); |
3101 | } else { /* decode response */ | 3103 | } else { /* decode response */ |
3102 | struct cifs_ntsd *psec_desc; | ||
3103 | __le32 * parm; | 3104 | __le32 * parm; |
3104 | int parm_len; | 3105 | __u32 parm_len; |
3105 | int data_len; | 3106 | __u32 acl_len; |
3106 | int acl_len; | ||
3107 | struct smb_com_ntransact_rsp *pSMBr; | 3107 | struct smb_com_ntransact_rsp *pSMBr; |
3108 | char *pdata; | ||
3108 | 3109 | ||
3109 | /* validate_nttransact */ | 3110 | /* validate_nttransact */ |
3110 | rc = validate_ntransact(iov[0].iov_base, (char **)&parm, | 3111 | rc = validate_ntransact(iov[0].iov_base, (char **)&parm, |
3111 | (char **)&psec_desc, | 3112 | &pdata, &parm_len, pbuflen); |
3112 | &parm_len, &data_len); | ||
3113 | if (rc) | 3113 | if (rc) |
3114 | goto qsec_out; | 3114 | goto qsec_out; |
3115 | pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base; | 3115 | pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base; |
3116 | 3116 | ||
3117 | cFYI(1, ("smb %p parm %p data %p", pSMBr, parm, psec_desc)); | 3117 | cFYI(1, ("smb %p parm %p data %p", pSMBr, parm, *acl_inf)); |
3118 | 3118 | ||
3119 | if (le32_to_cpu(pSMBr->ParameterCount) != 4) { | 3119 | if (le32_to_cpu(pSMBr->ParameterCount) != 4) { |
3120 | rc = -EIO; /* bad smb */ | 3120 | rc = -EIO; /* bad smb */ |
3121 | *pbuflen = 0; | ||
3121 | goto qsec_out; | 3122 | goto qsec_out; |
3122 | } | 3123 | } |
3123 | 3124 | ||
3124 | /* BB check that data area is minimum length and as big as acl_len */ | 3125 | /* BB check that data area is minimum length and as big as acl_len */ |
3125 | 3126 | ||
3126 | acl_len = le32_to_cpu(*parm); | 3127 | acl_len = le32_to_cpu(*parm); |
3127 | /* BB check if (acl_len > bufsize) */ | 3128 | if (acl_len != *pbuflen) { |
3129 | cERROR(1, ("acl length %d does not match %d", | ||
3130 | acl_len, *pbuflen)); | ||
3131 | if (*pbuflen > acl_len) | ||
3132 | *pbuflen = acl_len; | ||
3133 | } | ||
3128 | 3134 | ||
3129 | parse_sec_desc(psec_desc, acl_len); | 3135 | /* check if buffer is big enough for the acl |
3136 | header followed by the smallest SID */ | ||
3137 | if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) || | ||
3138 | (*pbuflen >= 64 * 1024)) { | ||
3139 | cERROR(1, ("bad acl length %d", *pbuflen)); | ||
3140 | rc = -EINVAL; | ||
3141 | *pbuflen = 0; | ||
3142 | } else { | ||
3143 | *acl_inf = kmalloc(*pbuflen, GFP_KERNEL); | ||
3144 | if (*acl_inf == NULL) { | ||
3145 | *pbuflen = 0; | ||
3146 | rc = -ENOMEM; | ||
3147 | } | ||
3148 | memcpy(*acl_inf, pdata, *pbuflen); | ||
3149 | } | ||
3130 | } | 3150 | } |
3131 | qsec_out: | 3151 | qsec_out: |
3132 | if (buf_type == CIFS_SMALL_BUFFER) | 3152 | if (buf_type == CIFS_SMALL_BUFFER) |
@@ -3136,6 +3156,71 @@ qsec_out: | |||
3136 | /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */ | 3156 | /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */ |
3137 | return rc; | 3157 | return rc; |
3138 | } | 3158 | } |
3159 | |||
3160 | int | ||
3161 | CIFSSMBSetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid, | ||
3162 | struct cifs_ntsd *pntsd, __u32 acllen) | ||
3163 | { | ||
3164 | __u16 byte_count, param_count, data_count, param_offset, data_offset; | ||
3165 | int rc = 0; | ||
3166 | int bytes_returned = 0; | ||
3167 | SET_SEC_DESC_REQ *pSMB = NULL; | ||
3168 | NTRANSACT_RSP *pSMBr = NULL; | ||
3169 | |||
3170 | setCifsAclRetry: | ||
3171 | rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB, | ||
3172 | (void **) &pSMBr); | ||
3173 | if (rc) | ||
3174 | return (rc); | ||
3175 | |||
3176 | pSMB->MaxSetupCount = 0; | ||
3177 | pSMB->Reserved = 0; | ||
3178 | |||
3179 | param_count = 8; | ||
3180 | param_offset = offsetof(struct smb_com_transaction_ssec_req, Fid) - 4; | ||
3181 | data_count = acllen; | ||
3182 | data_offset = param_offset + param_count; | ||
3183 | byte_count = 3 /* pad */ + param_count; | ||
3184 | |||
3185 | pSMB->DataCount = cpu_to_le32(data_count); | ||
3186 | pSMB->TotalDataCount = pSMB->DataCount; | ||
3187 | pSMB->MaxParameterCount = cpu_to_le32(4); | ||
3188 | pSMB->MaxDataCount = cpu_to_le32(16384); | ||
3189 | pSMB->ParameterCount = cpu_to_le32(param_count); | ||
3190 | pSMB->ParameterOffset = cpu_to_le32(param_offset); | ||
3191 | pSMB->TotalParameterCount = pSMB->ParameterCount; | ||
3192 | pSMB->DataOffset = cpu_to_le32(data_offset); | ||
3193 | pSMB->SetupCount = 0; | ||
3194 | pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_SET_SECURITY_DESC); | ||
3195 | pSMB->ByteCount = cpu_to_le16(byte_count+data_count); | ||
3196 | |||
3197 | pSMB->Fid = fid; /* file handle always le */ | ||
3198 | pSMB->Reserved2 = 0; | ||
3199 | pSMB->AclFlags = cpu_to_le32(CIFS_ACL_DACL); | ||
3200 | |||
3201 | if (pntsd && acllen) { | ||
3202 | memcpy((char *) &pSMBr->hdr.Protocol + data_offset, | ||
3203 | (char *) pntsd, | ||
3204 | acllen); | ||
3205 | pSMB->hdr.smb_buf_length += (byte_count + data_count); | ||
3206 | |||
3207 | } else | ||
3208 | pSMB->hdr.smb_buf_length += byte_count; | ||
3209 | |||
3210 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | ||
3211 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | ||
3212 | |||
3213 | cFYI(1, ("SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned, rc)); | ||
3214 | if (rc) | ||
3215 | cFYI(1, ("Set CIFS ACL returned %d", rc)); | ||
3216 | cifs_buf_release(pSMB); | ||
3217 | |||
3218 | if (rc == -EAGAIN) | ||
3219 | goto setCifsAclRetry; | ||
3220 | |||
3221 | return (rc); | ||
3222 | } | ||
3223 | |||
3139 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ | 3224 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ |
3140 | 3225 | ||
3141 | /* Legacy Query Path Information call for lookup to old servers such | 3226 | /* Legacy Query Path Information call for lookup to old servers such |
@@ -3381,7 +3466,7 @@ UnixQPathInfoRetry: | |||
3381 | memcpy((char *) pFindData, | 3466 | memcpy((char *) pFindData, |
3382 | (char *) &pSMBr->hdr.Protocol + | 3467 | (char *) &pSMBr->hdr.Protocol + |
3383 | data_offset, | 3468 | data_offset, |
3384 | sizeof (FILE_UNIX_BASIC_INFO)); | 3469 | sizeof(FILE_UNIX_BASIC_INFO)); |
3385 | } | 3470 | } |
3386 | } | 3471 | } |
3387 | cifs_buf_release(pSMB); | 3472 | cifs_buf_release(pSMB); |
@@ -3649,7 +3734,7 @@ int CIFSFindNext(const int xid, struct cifsTconInfo *tcon, | |||
3649 | pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT); | 3734 | pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT); |
3650 | pSMB->SearchHandle = searchHandle; /* always kept as le */ | 3735 | pSMB->SearchHandle = searchHandle; /* always kept as le */ |
3651 | pSMB->SearchCount = | 3736 | pSMB->SearchCount = |
3652 | cpu_to_le16(CIFSMaxBufSize / sizeof (FILE_UNIX_INFO)); | 3737 | cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO)); |
3653 | pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level); | 3738 | pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level); |
3654 | pSMB->ResumeKey = psrch_inf->resume_key; | 3739 | pSMB->ResumeKey = psrch_inf->resume_key; |
3655 | pSMB->SearchFlags = | 3740 | pSMB->SearchFlags = |
@@ -3737,8 +3822,6 @@ CIFSFindClose(const int xid, struct cifsTconInfo *tcon, | |||
3737 | { | 3822 | { |
3738 | int rc = 0; | 3823 | int rc = 0; |
3739 | FINDCLOSE_REQ *pSMB = NULL; | 3824 | FINDCLOSE_REQ *pSMB = NULL; |
3740 | CLOSE_RSP *pSMBr = NULL; /* BB removeme BB */ | ||
3741 | int bytes_returned; | ||
3742 | 3825 | ||
3743 | cFYI(1, ("In CIFSSMBFindClose")); | 3826 | cFYI(1, ("In CIFSSMBFindClose")); |
3744 | rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB); | 3827 | rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB); |
@@ -3750,16 +3833,13 @@ CIFSFindClose(const int xid, struct cifsTconInfo *tcon, | |||
3750 | if (rc) | 3833 | if (rc) |
3751 | return rc; | 3834 | return rc; |
3752 | 3835 | ||
3753 | pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */ | ||
3754 | pSMB->FileID = searchHandle; | 3836 | pSMB->FileID = searchHandle; |
3755 | pSMB->ByteCount = 0; | 3837 | pSMB->ByteCount = 0; |
3756 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 3838 | rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); |
3757 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | ||
3758 | if (rc) { | 3839 | if (rc) { |
3759 | cERROR(1, ("Send error in FindClose = %d", rc)); | 3840 | cERROR(1, ("Send error in FindClose = %d", rc)); |
3760 | } | 3841 | } |
3761 | cifs_stats_inc(&tcon->num_fclose); | 3842 | cifs_stats_inc(&tcon->num_fclose); |
3762 | cifs_small_buf_release(pSMB); | ||
3763 | 3843 | ||
3764 | /* Since session is dead, search handle closed on server already */ | 3844 | /* Since session is dead, search handle closed on server already */ |
3765 | if (rc == -EAGAIN) | 3845 | if (rc == -EAGAIN) |
@@ -4331,7 +4411,7 @@ QFSDeviceRetry: | |||
4331 | } else { /* decode response */ | 4411 | } else { /* decode response */ |
4332 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 4412 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
4333 | 4413 | ||
4334 | if (rc || (pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO))) | 4414 | if (rc || (pSMBr->ByteCount < sizeof(FILE_SYSTEM_DEVICE_INFO))) |
4335 | rc = -EIO; /* bad smb */ | 4415 | rc = -EIO; /* bad smb */ |
4336 | else { | 4416 | else { |
4337 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); | 4417 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); |
@@ -4681,11 +4761,9 @@ CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size, | |||
4681 | __u16 fid, __u32 pid_of_opener, int SetAllocation) | 4761 | __u16 fid, __u32 pid_of_opener, int SetAllocation) |
4682 | { | 4762 | { |
4683 | struct smb_com_transaction2_sfi_req *pSMB = NULL; | 4763 | struct smb_com_transaction2_sfi_req *pSMB = NULL; |
4684 | struct smb_com_transaction2_sfi_rsp *pSMBr = NULL; | ||
4685 | char *data_offset; | 4764 | char *data_offset; |
4686 | struct file_end_of_file_info *parm_data; | 4765 | struct file_end_of_file_info *parm_data; |
4687 | int rc = 0; | 4766 | int rc = 0; |
4688 | int bytes_returned = 0; | ||
4689 | __u16 params, param_offset, offset, byte_count, count; | 4767 | __u16 params, param_offset, offset, byte_count, count; |
4690 | 4768 | ||
4691 | cFYI(1, ("SetFileSize (via SetFileInfo) %lld", | 4769 | cFYI(1, ("SetFileSize (via SetFileInfo) %lld", |
@@ -4695,8 +4773,6 @@ CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size, | |||
4695 | if (rc) | 4773 | if (rc) |
4696 | return rc; | 4774 | return rc; |
4697 | 4775 | ||
4698 | pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB; | ||
4699 | |||
4700 | pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener); | 4776 | pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener); |
4701 | pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16)); | 4777 | pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16)); |
4702 | 4778 | ||
@@ -4747,17 +4823,13 @@ CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size, | |||
4747 | pSMB->Reserved4 = 0; | 4823 | pSMB->Reserved4 = 0; |
4748 | pSMB->hdr.smb_buf_length += byte_count; | 4824 | pSMB->hdr.smb_buf_length += byte_count; |
4749 | pSMB->ByteCount = cpu_to_le16(byte_count); | 4825 | pSMB->ByteCount = cpu_to_le16(byte_count); |
4750 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 4826 | rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); |
4751 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | ||
4752 | if (rc) { | 4827 | if (rc) { |
4753 | cFYI(1, | 4828 | cFYI(1, |
4754 | ("Send error in SetFileInfo (SetFileSize) = %d", | 4829 | ("Send error in SetFileInfo (SetFileSize) = %d", |
4755 | rc)); | 4830 | rc)); |
4756 | } | 4831 | } |
4757 | 4832 | ||
4758 | if (pSMB) | ||
4759 | cifs_small_buf_release(pSMB); | ||
4760 | |||
4761 | /* Note: On -EAGAIN error only caller can retry on handle based calls | 4833 | /* Note: On -EAGAIN error only caller can retry on handle based calls |
4762 | since file handle passed in no longer valid */ | 4834 | since file handle passed in no longer valid */ |
4763 | 4835 | ||
@@ -4775,10 +4847,8 @@ CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, | |||
4775 | const FILE_BASIC_INFO *data, __u16 fid) | 4847 | const FILE_BASIC_INFO *data, __u16 fid) |
4776 | { | 4848 | { |
4777 | struct smb_com_transaction2_sfi_req *pSMB = NULL; | 4849 | struct smb_com_transaction2_sfi_req *pSMB = NULL; |
4778 | struct smb_com_transaction2_sfi_rsp *pSMBr = NULL; | ||
4779 | char *data_offset; | 4850 | char *data_offset; |
4780 | int rc = 0; | 4851 | int rc = 0; |
4781 | int bytes_returned = 0; | ||
4782 | __u16 params, param_offset, offset, byte_count, count; | 4852 | __u16 params, param_offset, offset, byte_count, count; |
4783 | 4853 | ||
4784 | cFYI(1, ("Set Times (via SetFileInfo)")); | 4854 | cFYI(1, ("Set Times (via SetFileInfo)")); |
@@ -4787,8 +4857,6 @@ CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, | |||
4787 | if (rc) | 4857 | if (rc) |
4788 | return rc; | 4858 | return rc; |
4789 | 4859 | ||
4790 | pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB; | ||
4791 | |||
4792 | /* At this point there is no need to override the current pid | 4860 | /* At this point there is no need to override the current pid |
4793 | with the pid of the opener, but that could change if we someday | 4861 | with the pid of the opener, but that could change if we someday |
4794 | use an existing handle (rather than opening one on the fly) */ | 4862 | use an existing handle (rather than opening one on the fly) */ |
@@ -4828,14 +4896,11 @@ CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, | |||
4828 | pSMB->hdr.smb_buf_length += byte_count; | 4896 | pSMB->hdr.smb_buf_length += byte_count; |
4829 | pSMB->ByteCount = cpu_to_le16(byte_count); | 4897 | pSMB->ByteCount = cpu_to_le16(byte_count); |
4830 | memcpy(data_offset, data, sizeof(FILE_BASIC_INFO)); | 4898 | memcpy(data_offset, data, sizeof(FILE_BASIC_INFO)); |
4831 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 4899 | rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); |
4832 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | ||
4833 | if (rc) { | 4900 | if (rc) { |
4834 | cFYI(1, ("Send error in Set Time (SetFileInfo) = %d", rc)); | 4901 | cFYI(1, ("Send error in Set Time (SetFileInfo) = %d", rc)); |
4835 | } | 4902 | } |
4836 | 4903 | ||
4837 | cifs_small_buf_release(pSMB); | ||
4838 | |||
4839 | /* Note: On -EAGAIN error only caller can retry on handle based calls | 4904 | /* Note: On -EAGAIN error only caller can retry on handle based calls |
4840 | since file handle passed in no longer valid */ | 4905 | since file handle passed in no longer valid */ |
4841 | 4906 | ||
@@ -5126,7 +5191,8 @@ int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon, | |||
5126 | pSMB->ByteCount = 0; | 5191 | pSMB->ByteCount = 0; |
5127 | 5192 | ||
5128 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 5193 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
5129 | (struct smb_hdr *) pSMBr, &bytes_returned, -1); | 5194 | (struct smb_hdr *)pSMBr, &bytes_returned, |
5195 | CIFS_ASYNC_OP); | ||
5130 | if (rc) { | 5196 | if (rc) { |
5131 | cFYI(1, ("Error in Notify = %d", rc)); | 5197 | cFYI(1, ("Error in Notify = %d", rc)); |
5132 | } else { | 5198 | } else { |
@@ -5498,7 +5564,7 @@ SetEARetry: | |||
5498 | else | 5564 | else |
5499 | name_len = strnlen(ea_name, 255); | 5565 | name_len = strnlen(ea_name, 255); |
5500 | 5566 | ||
5501 | count = sizeof(*parm_data) + ea_value_len + name_len + 1; | 5567 | count = sizeof(*parm_data) + ea_value_len + name_len; |
5502 | pSMB->MaxParameterCount = cpu_to_le16(2); | 5568 | pSMB->MaxParameterCount = cpu_to_le16(2); |
5503 | pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */ | 5569 | pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */ |
5504 | pSMB->MaxSetupCount = 0; | 5570 | pSMB->MaxSetupCount = 0; |