.. | .. |
---|
42 | 42 | #include "cifsproto.h" |
---|
43 | 43 | #include "cifs_unicode.h" |
---|
44 | 44 | #include "cifs_debug.h" |
---|
| 45 | +#include "smb2proto.h" |
---|
45 | 46 | #include "fscache.h" |
---|
46 | 47 | #include "smbdirect.h" |
---|
| 48 | +#ifdef CONFIG_CIFS_DFS_UPCALL |
---|
| 49 | +#include "dfs_cache.h" |
---|
| 50 | +#endif |
---|
47 | 51 | |
---|
48 | 52 | #ifdef CONFIG_CIFS_POSIX |
---|
49 | 53 | static struct { |
---|
.. | .. |
---|
109 | 113 | |
---|
110 | 114 | mutex_lock(&tcon->crfid.fid_mutex); |
---|
111 | 115 | tcon->crfid.is_valid = false; |
---|
| 116 | + /* cached handle is not valid, so SMB2_CLOSE won't be sent below */ |
---|
| 117 | + close_shroot_lease_locked(&tcon->crfid); |
---|
112 | 118 | memset(tcon->crfid.fid, 0, sizeof(struct cifs_fid)); |
---|
113 | 119 | mutex_unlock(&tcon->crfid.fid_mutex); |
---|
114 | 120 | |
---|
.. | .. |
---|
126 | 132 | struct cifs_ses *ses; |
---|
127 | 133 | struct TCP_Server_Info *server; |
---|
128 | 134 | struct nls_table *nls_codepage; |
---|
| 135 | + int retries; |
---|
129 | 136 | |
---|
130 | 137 | /* |
---|
131 | 138 | * SMBs NegProt, SessSetup, uLogoff do not have tcon yet so check for |
---|
.. | .. |
---|
152 | 159 | } |
---|
153 | 160 | } |
---|
154 | 161 | |
---|
| 162 | + retries = server->nr_targets; |
---|
| 163 | + |
---|
155 | 164 | /* |
---|
156 | | - * Give demultiplex thread up to 10 seconds to reconnect, should be |
---|
157 | | - * greater than cifs socket timeout which is 7 seconds |
---|
| 165 | + * Give demultiplex thread up to 10 seconds to each target available for |
---|
| 166 | + * reconnect -- should be greater than cifs socket timeout which is 7 |
---|
| 167 | + * seconds. |
---|
158 | 168 | */ |
---|
159 | 169 | while (server->tcpStatus == CifsNeedReconnect) { |
---|
160 | 170 | rc = wait_event_interruptible_timeout(server->response_q, |
---|
161 | 171 | (server->tcpStatus != CifsNeedReconnect), |
---|
162 | 172 | 10 * HZ); |
---|
163 | 173 | if (rc < 0) { |
---|
164 | | - cifs_dbg(FYI, "%s: aborting reconnect due to a received" |
---|
165 | | - " signal by the process\n", __func__); |
---|
| 174 | + cifs_dbg(FYI, "%s: aborting reconnect due to a received signal by the process\n", |
---|
| 175 | + __func__); |
---|
166 | 176 | return -ERESTARTSYS; |
---|
167 | 177 | } |
---|
168 | 178 | |
---|
169 | 179 | /* are we still trying to reconnect? */ |
---|
170 | 180 | if (server->tcpStatus != CifsNeedReconnect) |
---|
171 | 181 | break; |
---|
| 182 | + |
---|
| 183 | + if (retries && --retries) |
---|
| 184 | + continue; |
---|
172 | 185 | |
---|
173 | 186 | /* |
---|
174 | 187 | * on "soft" mounts we wait once. Hard mounts keep |
---|
.. | .. |
---|
179 | 192 | cifs_dbg(FYI, "gave up waiting on reconnect in smb_init\n"); |
---|
180 | 193 | return -EHOSTDOWN; |
---|
181 | 194 | } |
---|
| 195 | + retries = server->nr_targets; |
---|
182 | 196 | } |
---|
183 | 197 | |
---|
184 | 198 | if (!ses->need_reconnect && !tcon->need_reconnect) |
---|
.. | .. |
---|
214 | 228 | } |
---|
215 | 229 | |
---|
216 | 230 | cifs_mark_open_files_invalid(tcon); |
---|
217 | | - rc = CIFSTCon(0, ses, tcon->treeName, tcon, nls_codepage); |
---|
| 231 | + rc = cifs_tree_connect(0, tcon, nls_codepage); |
---|
218 | 232 | mutex_unlock(&ses->session_mutex); |
---|
219 | 233 | cifs_dbg(FYI, "reconnect tcon rc = %d\n", rc); |
---|
220 | 234 | |
---|
221 | 235 | if (rc) { |
---|
222 | | - printk_once(KERN_WARNING "reconnect tcon failed rc = %d\n", rc); |
---|
| 236 | + pr_warn_once("reconnect tcon failed rc = %d\n", rc); |
---|
223 | 237 | goto out; |
---|
224 | 238 | } |
---|
225 | 239 | |
---|
226 | 240 | atomic_inc(&tconInfoReconnectCount); |
---|
227 | 241 | |
---|
228 | 242 | /* tell server Unix caps we support */ |
---|
229 | | - if (ses->capabilities & CAP_UNIX) |
---|
| 243 | + if (cap_unix(ses)) |
---|
230 | 244 | reset_cifs_unix_caps(0, tcon, NULL, NULL); |
---|
231 | 245 | |
---|
232 | 246 | /* |
---|
.. | .. |
---|
452 | 466 | /* If server requires signing, does client allow it? */ |
---|
453 | 467 | if (srv_sign_required) { |
---|
454 | 468 | if (!mnt_sign_enabled) { |
---|
455 | | - cifs_dbg(VFS, "Server requires signing, but it's disabled in SecurityFlags!"); |
---|
| 469 | + cifs_dbg(VFS, "Server requires signing, but it's disabled in SecurityFlags!\n"); |
---|
456 | 470 | return -ENOTSUPP; |
---|
457 | 471 | } |
---|
458 | 472 | server->sign = true; |
---|
.. | .. |
---|
461 | 475 | /* If client requires signing, does server allow it? */ |
---|
462 | 476 | if (mnt_sign_required) { |
---|
463 | 477 | if (!srv_sign_enabled) { |
---|
464 | | - cifs_dbg(VFS, "Server does not support signing!"); |
---|
| 478 | + cifs_dbg(VFS, "Server does not support signing!\n"); |
---|
465 | 479 | return -ENOTSUPP; |
---|
466 | 480 | } |
---|
467 | 481 | server->sign = true; |
---|
468 | 482 | } |
---|
469 | 483 | |
---|
470 | 484 | if (cifs_rdma_enabled(server) && server->sign) |
---|
471 | | - cifs_dbg(VFS, "Signing is enabled, and RDMA read/write will be disabled"); |
---|
| 485 | + cifs_dbg(VFS, "Signing is enabled, and RDMA read/write will be disabled\n"); |
---|
472 | 486 | |
---|
473 | 487 | return 0; |
---|
474 | 488 | } |
---|
.. | .. |
---|
489 | 503 | cifs_max_pending); |
---|
490 | 504 | set_credits(server, server->maxReq); |
---|
491 | 505 | server->maxBuf = le16_to_cpu(rsp->MaxBufSize); |
---|
| 506 | + /* set up max_read for readpages check */ |
---|
| 507 | + server->max_read = server->maxBuf; |
---|
492 | 508 | /* even though we do not use raw we might as well set this |
---|
493 | 509 | accurately, in case we ever find a need for it */ |
---|
494 | 510 | if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) { |
---|
.. | .. |
---|
565 | 581 | if (global_secflags & |
---|
566 | 582 | (CIFSSEC_MAY_KRB5 | CIFSSEC_MAY_NTLMSSP)) |
---|
567 | 583 | return true; |
---|
568 | | - /* Fallthrough */ |
---|
| 584 | + fallthrough; |
---|
569 | 585 | default: |
---|
570 | 586 | return false; |
---|
571 | 587 | } |
---|
.. | .. |
---|
596 | 612 | pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS); |
---|
597 | 613 | |
---|
598 | 614 | if (should_set_ext_sec_flag(ses->sectype)) { |
---|
599 | | - cifs_dbg(FYI, "Requesting extended security."); |
---|
| 615 | + cifs_dbg(FYI, "Requesting extended security\n"); |
---|
600 | 616 | pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC; |
---|
601 | 617 | } |
---|
602 | 618 | |
---|
.. | .. |
---|
650 | 666 | set_credits(server, server->maxReq); |
---|
651 | 667 | /* probably no need to store and check maxvcs */ |
---|
652 | 668 | server->maxBuf = le32_to_cpu(pSMBr->MaxBufferSize); |
---|
| 669 | + /* set up max_read for readpages check */ |
---|
| 670 | + server->max_read = server->maxBuf; |
---|
653 | 671 | server->max_rw = le32_to_cpu(pSMBr->MaxRawSize); |
---|
654 | 672 | cifs_dbg(NOISY, "Max buf = %d\n", ses->server->maxBuf); |
---|
655 | 673 | server->capabilities = le32_to_cpu(pSMBr->Capabilities); |
---|
.. | .. |
---|
731 | 749 | cifs_echo_callback(struct mid_q_entry *mid) |
---|
732 | 750 | { |
---|
733 | 751 | struct TCP_Server_Info *server = mid->callback_data; |
---|
| 752 | + struct cifs_credits credits = { .value = 1, .instance = 0 }; |
---|
734 | 753 | |
---|
735 | 754 | DeleteMidQEntry(mid); |
---|
736 | | - add_credits(server, 1, CIFS_ECHO_OP); |
---|
| 755 | + add_credits(server, &credits, CIFS_ECHO_OP); |
---|
737 | 756 | } |
---|
738 | 757 | |
---|
739 | 758 | int |
---|
.. | .. |
---|
768 | 787 | iov[1].iov_base = (char *)smb + 4; |
---|
769 | 788 | |
---|
770 | 789 | rc = cifs_call_async(server, &rqst, NULL, cifs_echo_callback, NULL, |
---|
771 | | - server, CIFS_ASYNC_OP | CIFS_ECHO_OP); |
---|
| 790 | + server, CIFS_NON_BLOCKING | CIFS_ECHO_OP, NULL); |
---|
772 | 791 | if (rc) |
---|
773 | 792 | cifs_dbg(FYI, "Echo request failed: %d\n", rc); |
---|
774 | 793 | |
---|
.. | .. |
---|
850 | 869 | PATH_MAX, nls_codepage, remap); |
---|
851 | 870 | name_len++; /* trailing null */ |
---|
852 | 871 | name_len *= 2; |
---|
853 | | - } else { /* BB add path length overrun check */ |
---|
854 | | - name_len = strnlen(fileName, PATH_MAX); |
---|
855 | | - name_len++; /* trailing null */ |
---|
856 | | - strncpy(pSMB->FileName, fileName, name_len); |
---|
| 872 | + } else { |
---|
| 873 | + name_len = copy_path_name(pSMB->FileName, fileName); |
---|
857 | 874 | } |
---|
858 | 875 | |
---|
859 | 876 | params = 6 + name_len; |
---|
.. | .. |
---|
923 | 940 | remap); |
---|
924 | 941 | name_len++; /* trailing null */ |
---|
925 | 942 | name_len *= 2; |
---|
926 | | - } else { /* BB improve check for buffer overruns BB */ |
---|
927 | | - name_len = strnlen(name, PATH_MAX); |
---|
928 | | - name_len++; /* trailing null */ |
---|
929 | | - strncpy(pSMB->fileName, name, name_len); |
---|
| 943 | + } else { |
---|
| 944 | + name_len = copy_path_name(pSMB->fileName, name); |
---|
930 | 945 | } |
---|
931 | 946 | pSMB->SearchAttributes = |
---|
932 | 947 | cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM); |
---|
.. | .. |
---|
970 | 985 | remap); |
---|
971 | 986 | name_len++; /* trailing null */ |
---|
972 | 987 | name_len *= 2; |
---|
973 | | - } else { /* BB improve check for buffer overruns BB */ |
---|
974 | | - name_len = strnlen(name, PATH_MAX); |
---|
975 | | - name_len++; /* trailing null */ |
---|
976 | | - strncpy(pSMB->DirName, name, name_len); |
---|
| 988 | + } else { |
---|
| 989 | + name_len = copy_path_name(pSMB->DirName, name); |
---|
977 | 990 | } |
---|
978 | 991 | |
---|
979 | 992 | pSMB->BufferFormat = 0x04; |
---|
.. | .. |
---|
992 | 1005 | } |
---|
993 | 1006 | |
---|
994 | 1007 | int |
---|
995 | | -CIFSSMBMkDir(const unsigned int xid, struct cifs_tcon *tcon, const char *name, |
---|
| 1008 | +CIFSSMBMkDir(const unsigned int xid, struct inode *inode, umode_t mode, |
---|
| 1009 | + struct cifs_tcon *tcon, const char *name, |
---|
996 | 1010 | struct cifs_sb_info *cifs_sb) |
---|
997 | 1011 | { |
---|
998 | 1012 | int rc = 0; |
---|
.. | .. |
---|
1015 | 1029 | remap); |
---|
1016 | 1030 | name_len++; /* trailing null */ |
---|
1017 | 1031 | name_len *= 2; |
---|
1018 | | - } else { /* BB improve check for buffer overruns BB */ |
---|
1019 | | - name_len = strnlen(name, PATH_MAX); |
---|
1020 | | - name_len++; /* trailing null */ |
---|
1021 | | - strncpy(pSMB->DirName, name, name_len); |
---|
| 1032 | + } else { |
---|
| 1033 | + name_len = copy_path_name(pSMB->DirName, name); |
---|
1022 | 1034 | } |
---|
1023 | 1035 | |
---|
1024 | 1036 | pSMB->BufferFormat = 0x04; |
---|
.. | .. |
---|
1065 | 1077 | PATH_MAX, nls_codepage, remap); |
---|
1066 | 1078 | name_len++; /* trailing null */ |
---|
1067 | 1079 | name_len *= 2; |
---|
1068 | | - } else { /* BB improve the check for buffer overruns BB */ |
---|
1069 | | - name_len = strnlen(name, PATH_MAX); |
---|
1070 | | - name_len++; /* trailing null */ |
---|
1071 | | - strncpy(pSMB->FileName, name, name_len); |
---|
| 1080 | + } else { |
---|
| 1081 | + name_len = copy_path_name(pSMB->FileName, name); |
---|
1072 | 1082 | } |
---|
1073 | 1083 | |
---|
1074 | 1084 | params = 6 + name_len; |
---|
.. | .. |
---|
1232 | 1242 | fileName, PATH_MAX, nls_codepage, remap); |
---|
1233 | 1243 | name_len++; /* trailing null */ |
---|
1234 | 1244 | name_len *= 2; |
---|
1235 | | - } else { /* BB improve check for buffer overruns BB */ |
---|
| 1245 | + } else { |
---|
1236 | 1246 | count = 0; /* no pad */ |
---|
1237 | | - name_len = strnlen(fileName, PATH_MAX); |
---|
1238 | | - name_len++; /* trailing null */ |
---|
1239 | | - strncpy(pSMB->fileName, fileName, name_len); |
---|
| 1247 | + name_len = copy_path_name(pSMB->fileName, fileName); |
---|
1240 | 1248 | } |
---|
1241 | 1249 | if (*pOplock & REQ_OPLOCK) |
---|
1242 | 1250 | pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK); |
---|
.. | .. |
---|
1313 | 1321 | CIFS_open(const unsigned int xid, struct cifs_open_parms *oparms, int *oplock, |
---|
1314 | 1322 | FILE_ALL_INFO *buf) |
---|
1315 | 1323 | { |
---|
1316 | | - int rc = -EACCES; |
---|
| 1324 | + int rc; |
---|
1317 | 1325 | OPEN_REQ *req = NULL; |
---|
1318 | 1326 | OPEN_RSP *rsp = NULL; |
---|
1319 | 1327 | int bytes_returned; |
---|
.. | .. |
---|
1350 | 1358 | /* BB improve check for buffer overruns BB */ |
---|
1351 | 1359 | /* no pad */ |
---|
1352 | 1360 | count = 0; |
---|
1353 | | - name_len = strnlen(path, PATH_MAX); |
---|
1354 | | - /* trailing null */ |
---|
1355 | | - name_len++; |
---|
| 1361 | + name_len = copy_path_name(req->fileName, path); |
---|
1356 | 1362 | req->NameLength = cpu_to_le16(name_len); |
---|
1357 | | - strncpy(req->fileName, path, name_len); |
---|
1358 | 1363 | } |
---|
1359 | 1364 | |
---|
1360 | 1365 | if (*oplock & REQ_OPLOCK) |
---|
.. | .. |
---|
1411 | 1416 | *oplock = rsp->OplockLevel; |
---|
1412 | 1417 | /* cifs fid stays in le */ |
---|
1413 | 1418 | oparms->fid->netfid = rsp->Fid; |
---|
| 1419 | + oparms->fid->access = desired_access; |
---|
1414 | 1420 | |
---|
1415 | 1421 | /* Let caller know file was created so we can set the mode. */ |
---|
1416 | 1422 | /* Do we care about the CreateAction in any other cases? */ |
---|
.. | .. |
---|
1445 | 1451 | while (remaining > 0) { |
---|
1446 | 1452 | int length; |
---|
1447 | 1453 | |
---|
1448 | | - length = cifs_read_from_socket(server, server->bigbuf, |
---|
1449 | | - min_t(unsigned int, remaining, |
---|
1450 | | - CIFSMaxBufSize + MAX_HEADER_SIZE(server))); |
---|
| 1454 | + length = cifs_discard_from_socket(server, |
---|
| 1455 | + min_t(size_t, remaining, |
---|
| 1456 | + CIFSMaxBufSize + MAX_HEADER_SIZE(server))); |
---|
1451 | 1457 | if (length < 0) |
---|
1452 | 1458 | return length; |
---|
1453 | 1459 | server->total_read += length; |
---|
.. | .. |
---|
1509 | 1515 | if (server->ops->is_session_expired && |
---|
1510 | 1516 | server->ops->is_session_expired(buf)) { |
---|
1511 | 1517 | cifs_reconnect(server); |
---|
1512 | | - wake_up(&server->response_q); |
---|
1513 | 1518 | return -1; |
---|
1514 | 1519 | } |
---|
1515 | 1520 | |
---|
1516 | 1521 | if (server->ops->is_status_pending && |
---|
1517 | | - server->ops->is_status_pending(buf, server, 0)) { |
---|
| 1522 | + server->ops->is_status_pending(buf, server)) { |
---|
1518 | 1523 | cifs_discard_remaining_data(server); |
---|
1519 | 1524 | return -1; |
---|
1520 | 1525 | } |
---|
.. | .. |
---|
1619 | 1624 | struct smb_rqst rqst = { .rq_iov = rdata->iov, |
---|
1620 | 1625 | .rq_nvec = 2, |
---|
1621 | 1626 | .rq_pages = rdata->pages, |
---|
| 1627 | + .rq_offset = rdata->page_offset, |
---|
1622 | 1628 | .rq_npages = rdata->nr_pages, |
---|
1623 | 1629 | .rq_pagesz = rdata->pagesz, |
---|
1624 | 1630 | .rq_tailsz = rdata->tailsz }; |
---|
| 1631 | + struct cifs_credits credits = { .value = 1, .instance = 0 }; |
---|
1625 | 1632 | |
---|
1626 | 1633 | cifs_dbg(FYI, "%s: mid=%llu state=%d result=%d bytes=%u\n", |
---|
1627 | 1634 | __func__, mid->mid, mid->mid_state, rdata->result, |
---|
.. | .. |
---|
1659 | 1666 | |
---|
1660 | 1667 | queue_work(cifsiod_wq, &rdata->work); |
---|
1661 | 1668 | DeleteMidQEntry(mid); |
---|
1662 | | - add_credits(server, 1, 0); |
---|
| 1669 | + add_credits(server, &credits, 0); |
---|
1663 | 1670 | } |
---|
1664 | 1671 | |
---|
1665 | 1672 | /* cifs_async_readv - send an async write, and set up mid to handle result */ |
---|
.. | .. |
---|
1718 | 1725 | |
---|
1719 | 1726 | kref_get(&rdata->refcount); |
---|
1720 | 1727 | rc = cifs_call_async(tcon->ses->server, &rqst, cifs_readv_receive, |
---|
1721 | | - cifs_readv_callback, NULL, rdata, 0); |
---|
| 1728 | + cifs_readv_callback, NULL, rdata, 0, NULL); |
---|
1722 | 1729 | |
---|
1723 | 1730 | if (rc == 0) |
---|
1724 | 1731 | cifs_stats_inc(&tcon->stats.cifs_stats.num_reads); |
---|
.. | .. |
---|
2032 | 2039 | wdata2->tailsz = tailsz; |
---|
2033 | 2040 | wdata2->bytes = cur_len; |
---|
2034 | 2041 | |
---|
2035 | | - wdata2->cfile = find_writable_file(CIFS_I(inode), false); |
---|
| 2042 | + rc = cifs_get_writable_file(CIFS_I(inode), FIND_WR_ANY, |
---|
| 2043 | + &wdata2->cfile); |
---|
2036 | 2044 | if (!wdata2->cfile) { |
---|
2037 | | - cifs_dbg(VFS, "No writable handle to retry writepages\n"); |
---|
2038 | | - rc = -EBADF; |
---|
| 2045 | + cifs_dbg(VFS, "No writable handle to retry writepages rc=%d\n", |
---|
| 2046 | + rc); |
---|
| 2047 | + if (!is_retryable_error(rc)) |
---|
| 2048 | + rc = -EBADF; |
---|
2039 | 2049 | } else { |
---|
2040 | 2050 | wdata2->pid = wdata2->cfile->pid; |
---|
2041 | 2051 | rc = server->ops->async_writev(wdata2, |
---|
.. | .. |
---|
2144 | 2154 | struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink); |
---|
2145 | 2155 | unsigned int written; |
---|
2146 | 2156 | WRITE_RSP *smb = (WRITE_RSP *)mid->resp_buf; |
---|
| 2157 | + struct cifs_credits credits = { .value = 1, .instance = 0 }; |
---|
2147 | 2158 | |
---|
2148 | 2159 | switch (mid->mid_state) { |
---|
2149 | 2160 | case MID_RESPONSE_RECEIVED: |
---|
.. | .. |
---|
2179 | 2190 | |
---|
2180 | 2191 | queue_work(cifsiod_wq, &wdata->work); |
---|
2181 | 2192 | DeleteMidQEntry(mid); |
---|
2182 | | - add_credits(tcon->ses->server, 1, 0); |
---|
| 2193 | + add_credits(tcon->ses->server, &credits, 0); |
---|
2183 | 2194 | } |
---|
2184 | 2195 | |
---|
2185 | 2196 | /* cifs_async_writev - send an async write, and set up mid to handle result */ |
---|
.. | .. |
---|
2232 | 2243 | rqst.rq_iov = iov; |
---|
2233 | 2244 | rqst.rq_nvec = 2; |
---|
2234 | 2245 | rqst.rq_pages = wdata->pages; |
---|
| 2246 | + rqst.rq_offset = wdata->page_offset; |
---|
2235 | 2247 | rqst.rq_npages = wdata->nr_pages; |
---|
2236 | 2248 | rqst.rq_pagesz = wdata->pagesz; |
---|
2237 | 2249 | rqst.rq_tailsz = wdata->tailsz; |
---|
.. | .. |
---|
2256 | 2268 | |
---|
2257 | 2269 | kref_get(&wdata->refcount); |
---|
2258 | 2270 | rc = cifs_call_async(tcon->ses->server, &rqst, NULL, |
---|
2259 | | - cifs_writev_callback, NULL, wdata, 0); |
---|
| 2271 | + cifs_writev_callback, NULL, wdata, 0, NULL); |
---|
2260 | 2272 | |
---|
2261 | 2273 | if (rc == 0) |
---|
2262 | 2274 | cifs_stats_inc(&tcon->stats.cifs_stats.num_writes); |
---|
.. | .. |
---|
2272 | 2284 | CIFSSMBWrite2(const unsigned int xid, struct cifs_io_parms *io_parms, |
---|
2273 | 2285 | unsigned int *nbytes, struct kvec *iov, int n_vec) |
---|
2274 | 2286 | { |
---|
2275 | | - int rc = -EACCES; |
---|
| 2287 | + int rc; |
---|
2276 | 2288 | WRITE_REQ *pSMB = NULL; |
---|
2277 | 2289 | int wct; |
---|
2278 | 2290 | int smb_hdr_len; |
---|
.. | .. |
---|
2409 | 2421 | iov[1].iov_len = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE); |
---|
2410 | 2422 | |
---|
2411 | 2423 | cifs_stats_inc(&tcon->stats.cifs_stats.num_locks); |
---|
2412 | | - rc = SendReceive2(xid, tcon->ses, iov, 2, &resp_buf_type, CIFS_NO_RESP, |
---|
2413 | | - &rsp_iov); |
---|
| 2424 | + rc = SendReceive2(xid, tcon->ses, iov, 2, &resp_buf_type, |
---|
| 2425 | + CIFS_NO_RSP_BUF, &rsp_iov); |
---|
2414 | 2426 | cifs_small_buf_release(pSMB); |
---|
2415 | 2427 | if (rc) |
---|
2416 | 2428 | cifs_dbg(FYI, "Send error in cifs_lockv = %d\n", rc); |
---|
.. | .. |
---|
2441 | 2453 | |
---|
2442 | 2454 | if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) { |
---|
2443 | 2455 | /* no response expected */ |
---|
2444 | | - flags = CIFS_ASYNC_OP | CIFS_OBREAK_OP; |
---|
| 2456 | + flags = CIFS_NO_SRV_RSP | CIFS_NON_BLOCKING | CIFS_OBREAK_OP; |
---|
2445 | 2457 | pSMB->Timeout = 0; |
---|
2446 | 2458 | } else if (waitFlag) { |
---|
2447 | 2459 | flags = CIFS_BLOCKING_OP; /* blocking operation, no timeout */ |
---|
.. | .. |
---|
2713 | 2725 | remap); |
---|
2714 | 2726 | name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ; |
---|
2715 | 2727 | name_len2 *= 2; /* convert to bytes */ |
---|
2716 | | - } else { /* BB improve the check for buffer overruns BB */ |
---|
2717 | | - name_len = strnlen(from_name, PATH_MAX); |
---|
2718 | | - name_len++; /* trailing null */ |
---|
2719 | | - strncpy(pSMB->OldFileName, from_name, name_len); |
---|
2720 | | - name_len2 = strnlen(to_name, PATH_MAX); |
---|
2721 | | - name_len2++; /* trailing null */ |
---|
| 2728 | + } else { |
---|
| 2729 | + name_len = copy_path_name(pSMB->OldFileName, from_name); |
---|
| 2730 | + name_len2 = copy_path_name(pSMB->OldFileName+name_len+1, to_name); |
---|
2722 | 2731 | pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */ |
---|
2723 | | - strncpy(&pSMB->OldFileName[name_len + 1], to_name, name_len2); |
---|
2724 | | - name_len2++; /* trailing null */ |
---|
2725 | 2732 | name_len2++; /* signature byte */ |
---|
2726 | 2733 | } |
---|
2727 | 2734 | |
---|
.. | .. |
---|
2863 | 2870 | toName, PATH_MAX, nls_codepage, remap); |
---|
2864 | 2871 | name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ; |
---|
2865 | 2872 | name_len2 *= 2; /* convert to bytes */ |
---|
2866 | | - } else { /* BB improve the check for buffer overruns BB */ |
---|
2867 | | - name_len = strnlen(fromName, PATH_MAX); |
---|
2868 | | - name_len++; /* trailing null */ |
---|
2869 | | - strncpy(pSMB->OldFileName, fromName, name_len); |
---|
2870 | | - name_len2 = strnlen(toName, PATH_MAX); |
---|
2871 | | - name_len2++; /* trailing null */ |
---|
| 2873 | + } else { |
---|
| 2874 | + name_len = copy_path_name(pSMB->OldFileName, fromName); |
---|
2872 | 2875 | pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */ |
---|
2873 | | - strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2); |
---|
2874 | | - name_len2++; /* trailing null */ |
---|
| 2876 | + name_len2 = copy_path_name(pSMB->OldFileName+name_len+1, toName); |
---|
2875 | 2877 | name_len2++; /* signature byte */ |
---|
2876 | 2878 | } |
---|
2877 | 2879 | |
---|
.. | .. |
---|
2922 | 2924 | name_len++; /* trailing null */ |
---|
2923 | 2925 | name_len *= 2; |
---|
2924 | 2926 | |
---|
2925 | | - } else { /* BB improve the check for buffer overruns BB */ |
---|
2926 | | - name_len = strnlen(fromName, PATH_MAX); |
---|
2927 | | - name_len++; /* trailing null */ |
---|
2928 | | - strncpy(pSMB->FileName, fromName, name_len); |
---|
| 2927 | + } else { |
---|
| 2928 | + name_len = copy_path_name(pSMB->FileName, fromName); |
---|
2929 | 2929 | } |
---|
2930 | 2930 | params = 6 + name_len; |
---|
2931 | 2931 | pSMB->MaxSetupCount = 0; |
---|
.. | .. |
---|
2945 | 2945 | PATH_MAX, nls_codepage, remap); |
---|
2946 | 2946 | name_len_target++; /* trailing null */ |
---|
2947 | 2947 | name_len_target *= 2; |
---|
2948 | | - } else { /* BB improve the check for buffer overruns BB */ |
---|
2949 | | - name_len_target = strnlen(toName, PATH_MAX); |
---|
2950 | | - name_len_target++; /* trailing null */ |
---|
2951 | | - strncpy(data_offset, toName, name_len_target); |
---|
| 2948 | + } else { |
---|
| 2949 | + name_len_target = copy_path_name(data_offset, toName); |
---|
2952 | 2950 | } |
---|
2953 | 2951 | |
---|
2954 | 2952 | pSMB->MaxParameterCount = cpu_to_le16(2); |
---|
.. | .. |
---|
3010 | 3008 | name_len++; /* trailing null */ |
---|
3011 | 3009 | name_len *= 2; |
---|
3012 | 3010 | |
---|
3013 | | - } else { /* BB improve the check for buffer overruns BB */ |
---|
3014 | | - name_len = strnlen(toName, PATH_MAX); |
---|
3015 | | - name_len++; /* trailing null */ |
---|
3016 | | - strncpy(pSMB->FileName, toName, name_len); |
---|
| 3011 | + } else { |
---|
| 3012 | + name_len = copy_path_name(pSMB->FileName, toName); |
---|
3017 | 3013 | } |
---|
3018 | 3014 | params = 6 + name_len; |
---|
3019 | 3015 | pSMB->MaxSetupCount = 0; |
---|
.. | .. |
---|
3032 | 3028 | PATH_MAX, nls_codepage, remap); |
---|
3033 | 3029 | name_len_target++; /* trailing null */ |
---|
3034 | 3030 | name_len_target *= 2; |
---|
3035 | | - } else { /* BB improve the check for buffer overruns BB */ |
---|
3036 | | - name_len_target = strnlen(fromName, PATH_MAX); |
---|
3037 | | - name_len_target++; /* trailing null */ |
---|
3038 | | - strncpy(data_offset, fromName, name_len_target); |
---|
| 3031 | + } else { |
---|
| 3032 | + name_len_target = copy_path_name(data_offset, fromName); |
---|
3039 | 3033 | } |
---|
3040 | 3034 | |
---|
3041 | 3035 | pSMB->MaxParameterCount = cpu_to_le16(2); |
---|
.. | .. |
---|
3114 | 3108 | remap); |
---|
3115 | 3109 | name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ; |
---|
3116 | 3110 | name_len2 *= 2; /* convert to bytes */ |
---|
3117 | | - } else { /* BB improve the check for buffer overruns BB */ |
---|
3118 | | - name_len = strnlen(from_name, PATH_MAX); |
---|
3119 | | - name_len++; /* trailing null */ |
---|
3120 | | - strncpy(pSMB->OldFileName, from_name, name_len); |
---|
3121 | | - name_len2 = strnlen(to_name, PATH_MAX); |
---|
3122 | | - name_len2++; /* trailing null */ |
---|
| 3111 | + } else { |
---|
| 3112 | + name_len = copy_path_name(pSMB->OldFileName, from_name); |
---|
3123 | 3113 | pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */ |
---|
3124 | | - strncpy(&pSMB->OldFileName[name_len + 1], to_name, name_len2); |
---|
3125 | | - name_len2++; /* trailing null */ |
---|
| 3114 | + name_len2 = copy_path_name(pSMB->OldFileName+name_len+1, to_name); |
---|
3126 | 3115 | name_len2++; /* signature byte */ |
---|
3127 | 3116 | } |
---|
3128 | 3117 | |
---|
.. | .. |
---|
3172 | 3161 | remap); |
---|
3173 | 3162 | name_len++; /* trailing null */ |
---|
3174 | 3163 | name_len *= 2; |
---|
3175 | | - } else { /* BB improve the check for buffer overruns BB */ |
---|
3176 | | - name_len = strnlen(searchName, PATH_MAX); |
---|
3177 | | - name_len++; /* trailing null */ |
---|
3178 | | - strncpy(pSMB->FileName, searchName, name_len); |
---|
| 3164 | + } else { |
---|
| 3165 | + name_len = copy_path_name(pSMB->FileName, searchName); |
---|
3179 | 3166 | } |
---|
3180 | 3167 | |
---|
3181 | 3168 | params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ; |
---|
.. | .. |
---|
3501 | 3488 | return size; |
---|
3502 | 3489 | } |
---|
3503 | 3490 | |
---|
3504 | | -static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace, |
---|
| 3491 | +static void convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace, |
---|
3505 | 3492 | const struct posix_acl_xattr_entry *local_ace) |
---|
3506 | 3493 | { |
---|
3507 | | - __u16 rc = 0; /* 0 = ACL converted ok */ |
---|
3508 | | - |
---|
3509 | 3494 | cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm); |
---|
3510 | 3495 | cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag); |
---|
3511 | 3496 | /* BB is there a better way to handle the large uid? */ |
---|
.. | .. |
---|
3518 | 3503 | cifs_dbg(FYI, "perm %d tag %d id %d\n", |
---|
3519 | 3504 | ace->e_perm, ace->e_tag, ace->e_id); |
---|
3520 | 3505 | */ |
---|
3521 | | - return rc; |
---|
3522 | 3506 | } |
---|
3523 | 3507 | |
---|
3524 | 3508 | /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */ |
---|
.. | .. |
---|
3554 | 3538 | cifs_dbg(FYI, "unknown ACL type %d\n", acl_type); |
---|
3555 | 3539 | return 0; |
---|
3556 | 3540 | } |
---|
3557 | | - for (i = 0; i < count; i++) { |
---|
3558 | | - rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i], &ace[i]); |
---|
3559 | | - if (rc != 0) { |
---|
3560 | | - /* ACE not converted */ |
---|
3561 | | - break; |
---|
3562 | | - } |
---|
3563 | | - } |
---|
| 3541 | + for (i = 0; i < count; i++) |
---|
| 3542 | + convert_ace_to_cifs_ace(&cifs_acl->ace_array[i], &ace[i]); |
---|
3564 | 3543 | if (rc == 0) { |
---|
3565 | 3544 | rc = (__u16)(count * sizeof(struct cifs_posix_ace)); |
---|
3566 | 3545 | rc += sizeof(struct cifs_posix_acl); |
---|
.. | .. |
---|
3600 | 3579 | name_len *= 2; |
---|
3601 | 3580 | pSMB->FileName[name_len] = 0; |
---|
3602 | 3581 | pSMB->FileName[name_len+1] = 0; |
---|
3603 | | - } else { /* BB improve the check for buffer overruns BB */ |
---|
3604 | | - name_len = strnlen(searchName, PATH_MAX); |
---|
3605 | | - name_len++; /* trailing null */ |
---|
3606 | | - strncpy(pSMB->FileName, searchName, name_len); |
---|
| 3582 | + } else { |
---|
| 3583 | + name_len = copy_path_name(pSMB->FileName, searchName); |
---|
3607 | 3584 | } |
---|
3608 | 3585 | |
---|
3609 | 3586 | params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ; |
---|
.. | .. |
---|
3685 | 3662 | PATH_MAX, nls_codepage, remap); |
---|
3686 | 3663 | name_len++; /* trailing null */ |
---|
3687 | 3664 | name_len *= 2; |
---|
3688 | | - } else { /* BB improve the check for buffer overruns BB */ |
---|
3689 | | - name_len = strnlen(fileName, PATH_MAX); |
---|
3690 | | - name_len++; /* trailing null */ |
---|
3691 | | - strncpy(pSMB->FileName, fileName, name_len); |
---|
| 3665 | + } else { |
---|
| 3666 | + name_len = copy_path_name(pSMB->FileName, fileName); |
---|
3692 | 3667 | } |
---|
3693 | 3668 | params = 6 + name_len; |
---|
3694 | 3669 | pSMB->MaxParameterCount = cpu_to_le16(2); |
---|
.. | .. |
---|
3802 | 3777 | struct file_chattr_info *pfinfo; |
---|
3803 | 3778 | /* BB Do we need a cast or hash here ? */ |
---|
3804 | 3779 | if (count != 16) { |
---|
3805 | | - cifs_dbg(FYI, "Illegal size ret in GetExtAttr\n"); |
---|
| 3780 | + cifs_dbg(FYI, "Invalid size ret in GetExtAttr\n"); |
---|
3806 | 3781 | rc = -EIO; |
---|
3807 | 3782 | goto GetExtAttrOut; |
---|
3808 | 3783 | } |
---|
.. | .. |
---|
3821 | 3796 | |
---|
3822 | 3797 | #endif /* CONFIG_POSIX */ |
---|
3823 | 3798 | |
---|
3824 | | -#ifdef CONFIG_CIFS_ACL |
---|
3825 | 3799 | /* |
---|
3826 | 3800 | * Initialize NT TRANSACT SMB into small smb request buffer. This assumes that |
---|
3827 | 3801 | * all NT TRANSACTS that we init here have total parm and data under about 400 |
---|
.. | .. |
---|
4065 | 4039 | return (rc); |
---|
4066 | 4040 | } |
---|
4067 | 4041 | |
---|
4068 | | -#endif /* CONFIG_CIFS_ACL */ |
---|
4069 | 4042 | |
---|
4070 | 4043 | /* Legacy Query Path Information call for lookup to old servers such |
---|
4071 | 4044 | as Win9x/WinME */ |
---|
.. | .. |
---|
4095 | 4068 | name_len++; /* trailing null */ |
---|
4096 | 4069 | name_len *= 2; |
---|
4097 | 4070 | } else { |
---|
4098 | | - name_len = strnlen(search_name, PATH_MAX); |
---|
4099 | | - name_len++; /* trailing null */ |
---|
4100 | | - strncpy(pSMB->FileName, search_name, name_len); |
---|
| 4071 | + name_len = copy_path_name(pSMB->FileName, search_name); |
---|
4101 | 4072 | } |
---|
4102 | 4073 | pSMB->BufferFormat = 0x04; |
---|
4103 | 4074 | name_len++; /* account for buffer type byte */ |
---|
.. | .. |
---|
4182 | 4153 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
---|
4183 | 4154 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
---|
4184 | 4155 | if (rc) { |
---|
4185 | | - cifs_dbg(FYI, "Send error in QFileInfo = %d", rc); |
---|
| 4156 | + cifs_dbg(FYI, "Send error in QFileInfo = %d\n", rc); |
---|
4186 | 4157 | } else { /* decode response */ |
---|
4187 | 4158 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
---|
4188 | 4159 | |
---|
.. | .. |
---|
4232 | 4203 | PATH_MAX, nls_codepage, remap); |
---|
4233 | 4204 | name_len++; /* trailing null */ |
---|
4234 | 4205 | name_len *= 2; |
---|
4235 | | - } else { /* BB improve the check for buffer overruns BB */ |
---|
4236 | | - name_len = strnlen(search_name, PATH_MAX); |
---|
4237 | | - name_len++; /* trailing null */ |
---|
4238 | | - strncpy(pSMB->FileName, search_name, name_len); |
---|
| 4206 | + } else { |
---|
| 4207 | + name_len = copy_path_name(pSMB->FileName, search_name); |
---|
4239 | 4208 | } |
---|
4240 | 4209 | |
---|
4241 | 4210 | params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */; |
---|
.. | .. |
---|
4351 | 4320 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
---|
4352 | 4321 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
---|
4353 | 4322 | if (rc) { |
---|
4354 | | - cifs_dbg(FYI, "Send error in UnixQFileInfo = %d", rc); |
---|
| 4323 | + cifs_dbg(FYI, "Send error in UnixQFileInfo = %d\n", rc); |
---|
4355 | 4324 | } else { /* decode response */ |
---|
4356 | 4325 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
---|
4357 | 4326 | |
---|
.. | .. |
---|
4401 | 4370 | PATH_MAX, nls_codepage, remap); |
---|
4402 | 4371 | name_len++; /* trailing null */ |
---|
4403 | 4372 | name_len *= 2; |
---|
4404 | | - } else { /* BB improve the check for buffer overruns BB */ |
---|
4405 | | - name_len = strnlen(searchName, PATH_MAX); |
---|
4406 | | - name_len++; /* trailing null */ |
---|
4407 | | - strncpy(pSMB->FileName, searchName, name_len); |
---|
| 4373 | + } else { |
---|
| 4374 | + name_len = copy_path_name(pSMB->FileName, searchName); |
---|
4408 | 4375 | } |
---|
4409 | 4376 | |
---|
4410 | 4377 | params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */; |
---|
.. | .. |
---|
4435 | 4402 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
---|
4436 | 4403 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
---|
4437 | 4404 | if (rc) { |
---|
4438 | | - cifs_dbg(FYI, "Send error in UnixQPathInfo = %d", rc); |
---|
| 4405 | + cifs_dbg(FYI, "Send error in UnixQPathInfo = %d\n", rc); |
---|
4439 | 4406 | } else { /* decode response */ |
---|
4440 | 4407 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
---|
4441 | 4408 | |
---|
.. | .. |
---|
4504 | 4471 | pSMB->FileName[name_len+1] = 0; |
---|
4505 | 4472 | name_len += 2; |
---|
4506 | 4473 | } |
---|
4507 | | - } else { /* BB add check for overrun of SMB buf BB */ |
---|
4508 | | - name_len = strnlen(searchName, PATH_MAX); |
---|
4509 | | -/* BB fix here and in unicode clause above ie |
---|
4510 | | - if (name_len > buffersize-header) |
---|
4511 | | - free buffer exit; BB */ |
---|
4512 | | - strncpy(pSMB->FileName, searchName, name_len); |
---|
| 4474 | + } else { |
---|
| 4475 | + name_len = copy_path_name(pSMB->FileName, searchName); |
---|
4513 | 4476 | if (msearch) { |
---|
4514 | | - pSMB->FileName[name_len] = CIFS_DIR_SEP(cifs_sb); |
---|
4515 | | - pSMB->FileName[name_len+1] = '*'; |
---|
4516 | | - pSMB->FileName[name_len+2] = 0; |
---|
4517 | | - name_len += 3; |
---|
| 4477 | + if (WARN_ON_ONCE(name_len > PATH_MAX-2)) |
---|
| 4478 | + name_len = PATH_MAX-2; |
---|
| 4479 | + /* overwrite nul byte */ |
---|
| 4480 | + pSMB->FileName[name_len-1] = CIFS_DIR_SEP(cifs_sb); |
---|
| 4481 | + pSMB->FileName[name_len] = '*'; |
---|
| 4482 | + pSMB->FileName[name_len+1] = 0; |
---|
| 4483 | + name_len += 2; |
---|
4518 | 4484 | } |
---|
4519 | 4485 | } |
---|
4520 | 4486 | |
---|
.. | .. |
---|
4577 | 4543 | psrch_inf->unicode = false; |
---|
4578 | 4544 | |
---|
4579 | 4545 | psrch_inf->ntwrk_buf_start = (char *)pSMBr; |
---|
4580 | | - psrch_inf->smallBuf = 0; |
---|
| 4546 | + psrch_inf->smallBuf = false; |
---|
4581 | 4547 | psrch_inf->srch_entries_start = |
---|
4582 | 4548 | (char *) &pSMBr->hdr.Protocol + |
---|
4583 | 4549 | le16_to_cpu(pSMBr->t2.DataOffset); |
---|
.. | .. |
---|
4711 | 4677 | cifs_buf_release(psrch_inf->ntwrk_buf_start); |
---|
4712 | 4678 | psrch_inf->srch_entries_start = response_data; |
---|
4713 | 4679 | psrch_inf->ntwrk_buf_start = (char *)pSMB; |
---|
4714 | | - psrch_inf->smallBuf = 0; |
---|
| 4680 | + psrch_inf->smallBuf = false; |
---|
4715 | 4681 | if (parms->EndofSearch) |
---|
4716 | 4682 | psrch_inf->endOfSearch = true; |
---|
4717 | 4683 | else |
---|
.. | .. |
---|
4809 | 4775 | remap); |
---|
4810 | 4776 | name_len++; /* trailing null */ |
---|
4811 | 4777 | name_len *= 2; |
---|
4812 | | - } else { /* BB improve the check for buffer overruns BB */ |
---|
4813 | | - name_len = strnlen(search_name, PATH_MAX); |
---|
4814 | | - name_len++; /* trailing null */ |
---|
4815 | | - strncpy(pSMB->FileName, search_name, name_len); |
---|
| 4778 | + } else { |
---|
| 4779 | + name_len = copy_path_name(pSMB->FileName, search_name); |
---|
4816 | 4780 | } |
---|
4817 | 4781 | |
---|
4818 | 4782 | params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ; |
---|
.. | .. |
---|
4858 | 4822 | struct file_internal_info *pfinfo; |
---|
4859 | 4823 | /* BB Do we need a cast or hash here ? */ |
---|
4860 | 4824 | if (count < 8) { |
---|
4861 | | - cifs_dbg(FYI, "Illegal size ret in QryIntrnlInf\n"); |
---|
| 4825 | + cifs_dbg(FYI, "Invalid size ret in QryIntrnlInf\n"); |
---|
4862 | 4826 | rc = -EIO; |
---|
4863 | 4827 | goto GetInodeNumOut; |
---|
4864 | 4828 | } |
---|
.. | .. |
---|
4895 | 4859 | return -ENODEV; |
---|
4896 | 4860 | |
---|
4897 | 4861 | getDFSRetry: |
---|
4898 | | - rc = smb_init(SMB_COM_TRANSACTION2, 15, ses->tcon_ipc, (void **) &pSMB, |
---|
4899 | | - (void **) &pSMBr); |
---|
| 4862 | + /* |
---|
| 4863 | + * Use smb_init_no_reconnect() instead of smb_init() as |
---|
| 4864 | + * CIFSGetDFSRefer() may be called from cifs_reconnect_tcon() and thus |
---|
| 4865 | + * causing an infinite recursion. |
---|
| 4866 | + */ |
---|
| 4867 | + rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, ses->tcon_ipc, |
---|
| 4868 | + (void **)&pSMB, (void **)&pSMBr); |
---|
4900 | 4869 | if (rc) |
---|
4901 | 4870 | return rc; |
---|
4902 | 4871 | |
---|
.. | .. |
---|
4919 | 4888 | name_len++; /* trailing null */ |
---|
4920 | 4889 | name_len *= 2; |
---|
4921 | 4890 | } else { /* BB improve the check for buffer overruns BB */ |
---|
4922 | | - name_len = strnlen(search_name, PATH_MAX); |
---|
4923 | | - name_len++; /* trailing null */ |
---|
4924 | | - strncpy(pSMB->RequestFileName, search_name, name_len); |
---|
| 4891 | + name_len = copy_path_name(pSMB->RequestFileName, search_name); |
---|
4925 | 4892 | } |
---|
4926 | 4893 | |
---|
4927 | 4894 | if (ses->server->sign) |
---|
.. | .. |
---|
5049 | 5016 | le16_to_cpu(response_data->BytesPerSector) * |
---|
5050 | 5017 | le32_to_cpu(response_data-> |
---|
5051 | 5018 | SectorsPerAllocationUnit); |
---|
| 5019 | + /* |
---|
| 5020 | + * much prefer larger but if server doesn't report |
---|
| 5021 | + * a valid size than 4K is a reasonable minimum |
---|
| 5022 | + */ |
---|
| 5023 | + if (FSData->f_bsize < 512) |
---|
| 5024 | + FSData->f_bsize = 4096; |
---|
| 5025 | + |
---|
5052 | 5026 | FSData->f_blocks = |
---|
5053 | 5027 | le32_to_cpu(response_data->TotalAllocationUnits); |
---|
5054 | 5028 | FSData->f_bfree = FSData->f_bavail = |
---|
.. | .. |
---|
5129 | 5103 | le32_to_cpu(response_data->BytesPerSector) * |
---|
5130 | 5104 | le32_to_cpu(response_data-> |
---|
5131 | 5105 | SectorsPerAllocationUnit); |
---|
| 5106 | + /* |
---|
| 5107 | + * much prefer larger but if server doesn't report |
---|
| 5108 | + * a valid size than 4K is a reasonable minimum |
---|
| 5109 | + */ |
---|
| 5110 | + if (FSData->f_bsize < 512) |
---|
| 5111 | + FSData->f_bsize = 4096; |
---|
| 5112 | + |
---|
5132 | 5113 | FSData->f_blocks = |
---|
5133 | 5114 | le64_to_cpu(response_data->TotalAllocationUnits); |
---|
5134 | 5115 | FSData->f_bfree = FSData->f_bavail = |
---|
.. | .. |
---|
5492 | 5473 | data_offset); |
---|
5493 | 5474 | FSData->f_bsize = |
---|
5494 | 5475 | le32_to_cpu(response_data->BlockSize); |
---|
| 5476 | + /* |
---|
| 5477 | + * much prefer larger but if server doesn't report |
---|
| 5478 | + * a valid size than 4K is a reasonable minimum |
---|
| 5479 | + */ |
---|
| 5480 | + if (FSData->f_bsize < 512) |
---|
| 5481 | + FSData->f_bsize = 4096; |
---|
| 5482 | + |
---|
5495 | 5483 | FSData->f_blocks = |
---|
5496 | 5484 | le64_to_cpu(response_data->TotalBlocks); |
---|
5497 | 5485 | FSData->f_bfree = |
---|
.. | .. |
---|
5553 | 5541 | PATH_MAX, cifs_sb->local_nls, remap); |
---|
5554 | 5542 | name_len++; /* trailing null */ |
---|
5555 | 5543 | name_len *= 2; |
---|
5556 | | - } else { /* BB improve the check for buffer overruns BB */ |
---|
5557 | | - name_len = strnlen(file_name, PATH_MAX); |
---|
5558 | | - name_len++; /* trailing null */ |
---|
5559 | | - strncpy(pSMB->FileName, file_name, name_len); |
---|
| 5544 | + } else { |
---|
| 5545 | + name_len = copy_path_name(pSMB->FileName, file_name); |
---|
5560 | 5546 | } |
---|
5561 | 5547 | params = 6 + name_len; |
---|
5562 | 5548 | data_count = sizeof(struct file_end_of_file_info); |
---|
.. | .. |
---|
5822 | 5808 | return rc; |
---|
5823 | 5809 | } |
---|
5824 | 5810 | |
---|
| 5811 | +static int |
---|
| 5812 | +CIFSSMBSetPathInfoFB(const unsigned int xid, struct cifs_tcon *tcon, |
---|
| 5813 | + const char *fileName, const FILE_BASIC_INFO *data, |
---|
| 5814 | + const struct nls_table *nls_codepage, |
---|
| 5815 | + struct cifs_sb_info *cifs_sb) |
---|
| 5816 | +{ |
---|
| 5817 | + int oplock = 0; |
---|
| 5818 | + struct cifs_open_parms oparms; |
---|
| 5819 | + struct cifs_fid fid; |
---|
| 5820 | + int rc; |
---|
| 5821 | + |
---|
| 5822 | + oparms.tcon = tcon; |
---|
| 5823 | + oparms.cifs_sb = cifs_sb; |
---|
| 5824 | + oparms.desired_access = GENERIC_WRITE; |
---|
| 5825 | + oparms.create_options = cifs_create_options(cifs_sb, 0); |
---|
| 5826 | + oparms.disposition = FILE_OPEN; |
---|
| 5827 | + oparms.path = fileName; |
---|
| 5828 | + oparms.fid = &fid; |
---|
| 5829 | + oparms.reconnect = false; |
---|
| 5830 | + |
---|
| 5831 | + rc = CIFS_open(xid, &oparms, &oplock, NULL); |
---|
| 5832 | + if (rc) |
---|
| 5833 | + goto out; |
---|
| 5834 | + |
---|
| 5835 | + rc = CIFSSMBSetFileInfo(xid, tcon, data, fid.netfid, current->tgid); |
---|
| 5836 | + CIFSSMBClose(xid, tcon, fid.netfid); |
---|
| 5837 | +out: |
---|
| 5838 | + |
---|
| 5839 | + return rc; |
---|
| 5840 | +} |
---|
| 5841 | + |
---|
5825 | 5842 | int |
---|
5826 | 5843 | CIFSSMBSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon, |
---|
5827 | 5844 | const char *fileName, const FILE_BASIC_INFO *data, |
---|
5828 | | - const struct nls_table *nls_codepage, int remap) |
---|
| 5845 | + const struct nls_table *nls_codepage, |
---|
| 5846 | + struct cifs_sb_info *cifs_sb) |
---|
5829 | 5847 | { |
---|
5830 | 5848 | TRANSACTION2_SPI_REQ *pSMB = NULL; |
---|
5831 | 5849 | TRANSACTION2_SPI_RSP *pSMBr = NULL; |
---|
.. | .. |
---|
5834 | 5852 | int bytes_returned = 0; |
---|
5835 | 5853 | char *data_offset; |
---|
5836 | 5854 | __u16 params, param_offset, offset, byte_count, count; |
---|
| 5855 | + int remap = cifs_remap(cifs_sb); |
---|
5837 | 5856 | |
---|
5838 | 5857 | cifs_dbg(FYI, "In SetTimes\n"); |
---|
5839 | 5858 | |
---|
.. | .. |
---|
5849 | 5868 | PATH_MAX, nls_codepage, remap); |
---|
5850 | 5869 | name_len++; /* trailing null */ |
---|
5851 | 5870 | name_len *= 2; |
---|
5852 | | - } else { /* BB improve the check for buffer overruns BB */ |
---|
5853 | | - name_len = strnlen(fileName, PATH_MAX); |
---|
5854 | | - name_len++; /* trailing null */ |
---|
5855 | | - strncpy(pSMB->FileName, fileName, name_len); |
---|
| 5871 | + } else { |
---|
| 5872 | + name_len = copy_path_name(pSMB->FileName, fileName); |
---|
5856 | 5873 | } |
---|
5857 | 5874 | |
---|
5858 | 5875 | params = 6 + name_len; |
---|
.. | .. |
---|
5898 | 5915 | if (rc == -EAGAIN) |
---|
5899 | 5916 | goto SetTimesRetry; |
---|
5900 | 5917 | |
---|
| 5918 | + if (rc == -EOPNOTSUPP) |
---|
| 5919 | + return CIFSSMBSetPathInfoFB(xid, tcon, fileName, data, |
---|
| 5920 | + nls_codepage, cifs_sb); |
---|
| 5921 | + |
---|
5901 | 5922 | return rc; |
---|
5902 | 5923 | } |
---|
5903 | 5924 | |
---|
.. | .. |
---|
5930 | 5951 | PATH_MAX, nls_codepage); |
---|
5931 | 5952 | name_len++; /* trailing null */ |
---|
5932 | 5953 | name_len *= 2; |
---|
5933 | | - } else { /* BB improve the check for buffer overruns BB */ |
---|
5934 | | - name_len = strnlen(fileName, PATH_MAX); |
---|
5935 | | - name_len++; /* trailing null */ |
---|
5936 | | - strncpy(pSMB->fileName, fileName, name_len); |
---|
| 5954 | + } else { |
---|
| 5955 | + name_len = copy_path_name(pSMB->fileName, fileName); |
---|
5937 | 5956 | } |
---|
5938 | 5957 | pSMB->attr = cpu_to_le16(dos_attrs); |
---|
5939 | 5958 | pSMB->BufferFormat = 0x04; |
---|
.. | .. |
---|
6093 | 6112 | PATH_MAX, nls_codepage, remap); |
---|
6094 | 6113 | name_len++; /* trailing null */ |
---|
6095 | 6114 | name_len *= 2; |
---|
6096 | | - } else { /* BB improve the check for buffer overruns BB */ |
---|
6097 | | - name_len = strnlen(file_name, PATH_MAX); |
---|
6098 | | - name_len++; /* trailing null */ |
---|
6099 | | - strncpy(pSMB->FileName, file_name, name_len); |
---|
| 6115 | + } else { |
---|
| 6116 | + name_len = copy_path_name(pSMB->FileName, file_name); |
---|
6100 | 6117 | } |
---|
6101 | 6118 | |
---|
6102 | 6119 | params = 6 + name_len; |
---|
.. | .. |
---|
6188 | 6205 | PATH_MAX, nls_codepage, remap); |
---|
6189 | 6206 | list_len++; /* trailing null */ |
---|
6190 | 6207 | list_len *= 2; |
---|
6191 | | - } else { /* BB improve the check for buffer overruns BB */ |
---|
6192 | | - list_len = strnlen(searchName, PATH_MAX); |
---|
6193 | | - list_len++; /* trailing null */ |
---|
6194 | | - strncpy(pSMB->FileName, searchName, list_len); |
---|
| 6208 | + } else { |
---|
| 6209 | + list_len = copy_path_name(pSMB->FileName, searchName); |
---|
6195 | 6210 | } |
---|
6196 | 6211 | |
---|
6197 | 6212 | params = 2 /* level */ + 4 /* reserved */ + list_len /* includes NUL */; |
---|
.. | .. |
---|
6370 | 6385 | PATH_MAX, nls_codepage, remap); |
---|
6371 | 6386 | name_len++; /* trailing null */ |
---|
6372 | 6387 | name_len *= 2; |
---|
6373 | | - } else { /* BB improve the check for buffer overruns BB */ |
---|
6374 | | - name_len = strnlen(fileName, PATH_MAX); |
---|
6375 | | - name_len++; /* trailing null */ |
---|
6376 | | - strncpy(pSMB->FileName, fileName, name_len); |
---|
| 6388 | + } else { |
---|
| 6389 | + name_len = copy_path_name(pSMB->FileName, fileName); |
---|
6377 | 6390 | } |
---|
6378 | 6391 | |
---|
6379 | 6392 | params = 6 + name_len; |
---|
.. | .. |
---|
6447 | 6460 | return rc; |
---|
6448 | 6461 | } |
---|
6449 | 6462 | #endif |
---|
6450 | | - |
---|
6451 | | -#ifdef CONFIG_CIFS_DNOTIFY_EXPERIMENTAL /* BB unused temporarily */ |
---|
6452 | | -/* |
---|
6453 | | - * Years ago the kernel added a "dnotify" function for Samba server, |
---|
6454 | | - * to allow network clients (such as Windows) to display updated |
---|
6455 | | - * lists of files in directory listings automatically when |
---|
6456 | | - * files are added by one user when another user has the |
---|
6457 | | - * same directory open on their desktop. The Linux cifs kernel |
---|
6458 | | - * client hooked into the kernel side of this interface for |
---|
6459 | | - * the same reason, but ironically when the VFS moved from |
---|
6460 | | - * "dnotify" to "inotify" it became harder to plug in Linux |
---|
6461 | | - * network file system clients (the most obvious use case |
---|
6462 | | - * for notify interfaces is when multiple users can update |
---|
6463 | | - * the contents of the same directory - exactly what network |
---|
6464 | | - * file systems can do) although the server (Samba) could |
---|
6465 | | - * still use it. For the short term we leave the worker |
---|
6466 | | - * function ifdeffed out (below) until inotify is fixed |
---|
6467 | | - * in the VFS to make it easier to plug in network file |
---|
6468 | | - * system clients. If inotify turns out to be permanently |
---|
6469 | | - * incompatible for network fs clients, we could instead simply |
---|
6470 | | - * expose this config flag by adding a future cifs (and smb2) notify ioctl. |
---|
6471 | | - */ |
---|
6472 | | -int CIFSSMBNotify(const unsigned int xid, struct cifs_tcon *tcon, |
---|
6473 | | - const int notify_subdirs, const __u16 netfid, |
---|
6474 | | - __u32 filter, struct file *pfile, int multishot, |
---|
6475 | | - const struct nls_table *nls_codepage) |
---|
6476 | | -{ |
---|
6477 | | - int rc = 0; |
---|
6478 | | - struct smb_com_transaction_change_notify_req *pSMB = NULL; |
---|
6479 | | - struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL; |
---|
6480 | | - struct dir_notify_req *dnotify_req; |
---|
6481 | | - int bytes_returned; |
---|
6482 | | - |
---|
6483 | | - cifs_dbg(FYI, "In CIFSSMBNotify for file handle %d\n", (int)netfid); |
---|
6484 | | - rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB, |
---|
6485 | | - (void **) &pSMBr); |
---|
6486 | | - if (rc) |
---|
6487 | | - return rc; |
---|
6488 | | - |
---|
6489 | | - pSMB->TotalParameterCount = 0 ; |
---|
6490 | | - pSMB->TotalDataCount = 0; |
---|
6491 | | - pSMB->MaxParameterCount = cpu_to_le32(2); |
---|
6492 | | - pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00); |
---|
6493 | | - pSMB->MaxSetupCount = 4; |
---|
6494 | | - pSMB->Reserved = 0; |
---|
6495 | | - pSMB->ParameterOffset = 0; |
---|
6496 | | - pSMB->DataCount = 0; |
---|
6497 | | - pSMB->DataOffset = 0; |
---|
6498 | | - pSMB->SetupCount = 4; /* single byte does not need le conversion */ |
---|
6499 | | - pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE); |
---|
6500 | | - pSMB->ParameterCount = pSMB->TotalParameterCount; |
---|
6501 | | - if (notify_subdirs) |
---|
6502 | | - pSMB->WatchTree = 1; /* one byte - no le conversion needed */ |
---|
6503 | | - pSMB->Reserved2 = 0; |
---|
6504 | | - pSMB->CompletionFilter = cpu_to_le32(filter); |
---|
6505 | | - pSMB->Fid = netfid; /* file handle always le */ |
---|
6506 | | - pSMB->ByteCount = 0; |
---|
6507 | | - |
---|
6508 | | - rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
---|
6509 | | - (struct smb_hdr *)pSMBr, &bytes_returned, |
---|
6510 | | - CIFS_ASYNC_OP); |
---|
6511 | | - if (rc) { |
---|
6512 | | - cifs_dbg(FYI, "Error in Notify = %d\n", rc); |
---|
6513 | | - } else { |
---|
6514 | | - /* Add file to outstanding requests */ |
---|
6515 | | - /* BB change to kmem cache alloc */ |
---|
6516 | | - dnotify_req = kmalloc( |
---|
6517 | | - sizeof(struct dir_notify_req), |
---|
6518 | | - GFP_KERNEL); |
---|
6519 | | - if (dnotify_req) { |
---|
6520 | | - dnotify_req->Pid = pSMB->hdr.Pid; |
---|
6521 | | - dnotify_req->PidHigh = pSMB->hdr.PidHigh; |
---|
6522 | | - dnotify_req->Mid = pSMB->hdr.Mid; |
---|
6523 | | - dnotify_req->Tid = pSMB->hdr.Tid; |
---|
6524 | | - dnotify_req->Uid = pSMB->hdr.Uid; |
---|
6525 | | - dnotify_req->netfid = netfid; |
---|
6526 | | - dnotify_req->pfile = pfile; |
---|
6527 | | - dnotify_req->filter = filter; |
---|
6528 | | - dnotify_req->multishot = multishot; |
---|
6529 | | - spin_lock(&GlobalMid_Lock); |
---|
6530 | | - list_add_tail(&dnotify_req->lhead, |
---|
6531 | | - &GlobalDnotifyReqList); |
---|
6532 | | - spin_unlock(&GlobalMid_Lock); |
---|
6533 | | - } else |
---|
6534 | | - rc = -ENOMEM; |
---|
6535 | | - } |
---|
6536 | | - cifs_buf_release(pSMB); |
---|
6537 | | - return rc; |
---|
6538 | | -} |
---|
6539 | | -#endif /* was needed for dnotify, and will be needed for inotify when VFS fix */ |
---|