1 From: Steve French <sfrench@us.ibm.com>
2 Date: Tue, 13 Nov 2007 22:41:37 +0000 (+0000)
3 Subject: [CIFS] Fix buffer overflow if server sends corrupt response to small
4 Patch-mainline: 2.6.24?
5 X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Fsfrench%2Fcifs-2.6.git;a=commitdiff_plain;h=133672efbc1085f9af990bdc145e1822ea93bcf3
6 References: CVE-2007-5904, 342448
8 [CIFS] Fix buffer overflow if server sends corrupt response to small
11 In SendReceive() function in transport.c - it memcpy's
12 message payload into a buffer passed via out_buf param. The function
13 assumes that all buffers are of size (CIFSMaxBufSize +
14 MAX_CIFS_HDR_SIZE) , unfortunately it is also called with smaller
15 (MAX_CIFS_SMALL_BUFFER_SIZE) buffers. There are eight callers
16 (SMB worker functions) which are primarily affected by this change:
18 TreeDisconnect, uLogoff, Close, findClose, SetFileSize, SetFileTimes,
21 CC: Dave Kleikamp <shaggy@austin.ibm.com>
22 CC: Przemyslaw Wegrzyn <czajnik@czajsoft.pl>
23 Acked-by: Jeff Layton <jlayton@redhat.com>
24 Signed-off-by: Steve French <sfrench@us.ibm.com>
25 Acked-by: Jeff Mahoney <jeffm@suse.com>
26 Signed-off-by: Oliver Pinter <oliver.pntr@gmail.com>
30 fs/cifs/cifsglob.h | 11 +++++
31 fs/cifs/cifsproto.h | 4 +-
32 fs/cifs/cifssmb.c | 96 +++++++++++++++++++---------------------------------
33 fs/cifs/connect.c | 9 ++--
34 fs/cifs/file.c | 14 +++----
36 fs/cifs/transport.c | 88 ++++++++++++++++++++++++++++++++++++-----------
37 7 files changed, 132 insertions(+), 93 deletions(-)
39 --- a/fs/cifs/cifsglob.h 2007-11-16 17:54:37.000000000 -0500
40 +++ b/fs/cifs/cifsglob.h 2007-11-16 17:58:12.000000000 -0500
41 @@ -442,6 +442,17 @@ struct dir_notify_req {
42 #define CIFS_LARGE_BUFFER 2
43 #define CIFS_IOVEC 4 /* array of response buffers */
45 +/* Type of Request to SendReceive2 */
46 +#define CIFS_STD_OP 0 /* normal request timeout */
47 +#define CIFS_LONG_OP 1 /* long op (up to 45 sec, oplock time) */
48 +#define CIFS_VLONG_OP 2 /* sloow op - can take up to 180 seconds */
49 +#define CIFS_BLOCKING_OP 4 /* operation can block */
50 +#define CIFS_ASYNC_OP 8 /* do not wait for response */
51 +#define CIFS_TIMEOUT_MASK 0x00F /* only one of 5 above set in req */
52 +#define CIFS_LOG_ERROR 0x010 /* log NT STATUS if non-zero */
53 +#define CIFS_LARGE_BUF_OP 0x020 /* large request buffer */
54 +#define CIFS_NO_RESP 0x040 /* no response buffer required */
56 /* Security Flags: indicate type of session setup needed */
57 #define CIFSSEC_MAY_SIGN 0x00001
58 #define CIFSSEC_MAY_NTLM 0x00002
59 --- a/fs/cifs/cifsproto.h 2007-11-16 17:54:37.000000000 -0500
60 +++ b/fs/cifs/cifsproto.h 2007-11-16 17:58:12.000000000 -0500
61 @@ -48,9 +48,11 @@ extern int SendReceive(const unsigned in
62 struct smb_hdr * /* input */ ,
63 struct smb_hdr * /* out */ ,
64 int * /* bytes returned */ , const int long_op);
65 +extern int SendReceiveNoRsp(const unsigned int xid, struct cifsSesInfo *ses,
66 + struct smb_hdr *in_buf, int flags);
67 extern int SendReceive2(const unsigned int /* xid */ , struct cifsSesInfo *,
68 struct kvec *, int /* nvec to send */,
69 - int * /* type of buf returned */ , const int long_op);
70 + int * /* type of buf returned */ , const int flags);
71 extern int SendReceiveBlockingLock(const unsigned int /* xid */ ,
72 struct cifsTconInfo *,
73 struct smb_hdr * /* input */ ,
74 --- a/fs/cifs/cifssmb.c 2007-11-16 17:54:37.000000000 -0500
75 +++ b/fs/cifs/cifssmb.c 2007-11-16 17:58:12.000000000 -0500
76 @@ -660,9 +660,7 @@ int
77 CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
79 struct smb_hdr *smb_buffer;
80 - struct smb_hdr *smb_buffer_response; /* BB removeme BB */
84 cFYI(1, ("In tree disconnect"));
86 @@ -699,16 +697,12 @@ CIFSSMBTDis(const int xid, struct cifsTc
91 - smb_buffer_response = smb_buffer; /* BB removeme BB */
93 - rc = SendReceive(xid, tcon->ses, smb_buffer, smb_buffer_response,
96 + rc = SendReceiveNoRsp(xid, tcon->ses, smb_buffer, 0);
98 cFYI(1, ("Tree disconnect failed %d", rc));
101 - cifs_small_buf_release(smb_buffer);
104 /* No need to return error on this operation if tid invalidated and
105 @@ -722,10 +716,8 @@ CIFSSMBTDis(const int xid, struct cifsTc
107 CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
109 - struct smb_hdr *smb_buffer_response;
110 LOGOFF_ANDX_REQ *pSMB;
114 cFYI(1, ("In SMBLogoff for session disconnect"));
116 @@ -744,8 +736,6 @@ CIFSSMBLogoff(const int xid, struct cifs
120 - smb_buffer_response = (struct smb_hdr *)pSMB; /* BB removeme BB */
123 pSMB->hdr.Mid = GetNextMid(ses->server);
125 @@ -757,8 +747,7 @@ CIFSSMBLogoff(const int xid, struct cifs
126 pSMB->hdr.Uid = ses->Suid;
128 pSMB->AndXCommand = 0xFF;
129 - rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
130 - smb_buffer_response, &length, 0);
131 + rc = SendReceiveNoRsp(xid, ses, (struct smb_hdr *) pSMB, 0);
133 atomic_dec(&ses->server->socketUseCount);
134 if (atomic_read(&ses->server->socketUseCount) == 0) {
135 @@ -769,7 +758,6 @@ CIFSSMBLogoff(const int xid, struct cifs
139 - cifs_small_buf_release(pSMB);
141 /* if session dead then we do not need to do ulogoff,
142 since server closed smb session, no sense reporting
143 @@ -1143,7 +1131,7 @@ OldOpenRetry:
144 pSMB->ByteCount = cpu_to_le16(count);
145 /* long_op set to 1 to allow for oplock break timeouts */
146 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
147 - (struct smb_hdr *) pSMBr, &bytes_returned, 1);
148 + (struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP);
149 cifs_stats_inc(&tcon->num_opens);
151 cFYI(1, ("Error in Open = %d", rc));
152 @@ -1257,7 +1245,7 @@ openRetry:
153 pSMB->ByteCount = cpu_to_le16(count);
154 /* long_op set to 1 to allow for oplock break timeouts */
155 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
156 - (struct smb_hdr *) pSMBr, &bytes_returned, 1);
157 + (struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP);
158 cifs_stats_inc(&tcon->num_opens);
160 cFYI(1, ("Error in Open = %d", rc));
161 @@ -1337,7 +1325,7 @@ CIFSSMBRead(const int xid, struct cifsTc
162 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
163 rc = SendReceive2(xid, tcon->ses, iov,
165 - &resp_buf_type, 0);
166 + &resp_buf_type, CIFS_STD_OP | CIFS_LOG_ERROR);
167 cifs_stats_inc(&tcon->num_reads);
168 pSMBr = (READ_RSP *)iov[0].iov_base;
170 @@ -1596,7 +1584,7 @@ CIFSSMBLock(const int xid, struct cifsTc
174 - cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d",waitFlag,numLock));
175 + cFYI(1, ("CIFSSMBLock timeout %d numLock %d", waitFlag, numLock));
176 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
179 @@ -1605,10 +1593,10 @@ CIFSSMBLock(const int xid, struct cifsTc
180 pSMBr = (LOCK_RSP *)pSMB; /* BB removeme BB */
182 if(lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
183 - timeout = -1; /* no response expected */
184 + timeout = CIFS_ASYNC_OP; /* no response expected */
186 } else if (waitFlag == TRUE) {
187 - timeout = 3; /* blocking operation, no timeout */
188 + timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
189 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
192 @@ -1638,15 +1626,16 @@ CIFSSMBLock(const int xid, struct cifsTc
194 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
195 (struct smb_hdr *) pSMBr, &bytes_returned);
196 + cifs_small_buf_release(pSMB);
198 - rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
199 - (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
200 + rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *)pSMB,
202 + /* SMB buffer freed by function above */
204 cifs_stats_inc(&tcon->num_locks);
206 cFYI(1, ("Send error in Lock = %d", rc));
208 - cifs_small_buf_release(pSMB);
210 /* Note: On -EAGAIN error only caller can retry on handle based calls
211 since file handle passed in no longer valid */
212 @@ -1666,7 +1655,9 @@ CIFSSMBPosixLock(const int xid, struct c
215 int bytes_returned = 0;
216 + int resp_buf_type = 0;
217 __u16 params, param_offset, offset, byte_count, count;
218 + struct kvec iov[1];
220 cFYI(1, ("Posix Lock"));
222 @@ -1710,7 +1701,7 @@ CIFSSMBPosixLock(const int xid, struct c
224 parm_data->lock_type = cpu_to_le16(lock_type);
226 - timeout = 3; /* blocking operation, no timeout */
227 + timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */
228 parm_data->lock_flags = cpu_to_le16(1);
229 pSMB->Timeout = cpu_to_le32(-1);
231 @@ -1730,8 +1721,13 @@ CIFSSMBPosixLock(const int xid, struct c
232 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
233 (struct smb_hdr *) pSMBr, &bytes_returned);
235 - rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
236 - (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
237 + iov[0].iov_base = (char *)pSMB;
238 + iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
239 + rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
240 + &resp_buf_type, timeout);
241 + pSMB = NULL; /* request buf already freed by SendReceive2. Do
242 + not try to free it twice below on exit */
243 + pSMBr = (struct smb_com_transaction2_sfi_rsp *)iov[0].iov_base;
247 @@ -1766,6 +1762,11 @@ plk_err_exit:
249 cifs_small_buf_release(pSMB);
251 + if (resp_buf_type == CIFS_SMALL_BUFFER)
252 + cifs_small_buf_release(iov[0].iov_base);
253 + else if (resp_buf_type == CIFS_LARGE_BUFFER)
254 + cifs_buf_release(iov[0].iov_base);
256 /* Note: On -EAGAIN error only caller can retry on handle based calls
257 since file handle passed in no longer valid */
259 @@ -1778,8 +1779,6 @@ CIFSSMBClose(const int xid, struct cifsT
262 CLOSE_REQ *pSMB = NULL;
263 - CLOSE_RSP *pSMBr = NULL;
264 - int bytes_returned;
265 cFYI(1, ("In CIFSSMBClose"));
267 /* do not retry on dead session on close */
268 @@ -1789,13 +1788,10 @@ CIFSSMBClose(const int xid, struct cifsT
272 - pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
274 pSMB->FileID = (__u16) smb_file_id;
275 pSMB->LastWriteTime = 0xFFFFFFFF;
277 - rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
278 - (struct smb_hdr *) pSMBr, &bytes_returned, 0);
279 + rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
280 cifs_stats_inc(&tcon->num_closes);
283 @@ -1804,8 +1800,6 @@ CIFSSMBClose(const int xid, struct cifsT
287 - cifs_small_buf_release(pSMB);
289 /* Since session is dead, file will be closed on server already */
292 @@ -2989,7 +2983,8 @@ CIFSSMBGetCIFSACL(const int xid, struct
293 iov[0].iov_base = (char *)pSMB;
294 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
296 - rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type, 0);
297 + rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
299 cifs_stats_inc(&tcon->num_acl_get);
301 cFYI(1, ("Send error in QuerySecDesc = %d", rc));
302 @@ -3634,8 +3629,6 @@ CIFSFindClose(const int xid, struct cifs
305 FINDCLOSE_REQ *pSMB = NULL;
306 - CLOSE_RSP *pSMBr = NULL; /* BB removeme BB */
307 - int bytes_returned;
309 cFYI(1, ("In CIFSSMBFindClose"));
310 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
311 @@ -3647,16 +3640,13 @@ CIFSFindClose(const int xid, struct cifs
315 - pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
316 pSMB->FileID = searchHandle;
318 - rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
319 - (struct smb_hdr *) pSMBr, &bytes_returned, 0);
320 + rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
322 cERROR(1, ("Send error in FindClose = %d", rc));
324 cifs_stats_inc(&tcon->num_fclose);
325 - cifs_small_buf_release(pSMB);
327 /* Since session is dead, search handle closed on server already */
329 @@ -4571,11 +4561,9 @@ CIFSSMBSetFileSize(const int xid, struct
330 __u16 fid, __u32 pid_of_opener, int SetAllocation)
332 struct smb_com_transaction2_sfi_req *pSMB = NULL;
333 - struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
335 struct file_end_of_file_info *parm_data;
337 - int bytes_returned = 0;
338 __u16 params, param_offset, offset, byte_count, count;
340 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
341 @@ -4585,8 +4573,6 @@ CIFSSMBSetFileSize(const int xid, struct
345 - pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
347 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
348 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
350 @@ -4637,17 +4623,13 @@ CIFSSMBSetFileSize(const int xid, struct
352 pSMB->hdr.smb_buf_length += byte_count;
353 pSMB->ByteCount = cpu_to_le16(byte_count);
354 - rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
355 - (struct smb_hdr *) pSMBr, &bytes_returned, 0);
356 + rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
359 ("Send error in SetFileInfo (SetFileSize) = %d",
364 - cifs_small_buf_release(pSMB);
366 /* Note: On -EAGAIN error only caller can retry on handle based calls
367 since file handle passed in no longer valid */
369 @@ -4665,10 +4647,8 @@ CIFSSMBSetFileTimes(const int xid, struc
372 struct smb_com_transaction2_sfi_req *pSMB = NULL;
373 - struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
376 - int bytes_returned = 0;
377 __u16 params, param_offset, offset, byte_count, count;
379 cFYI(1, ("Set Times (via SetFileInfo)"));
380 @@ -4677,8 +4657,6 @@ CIFSSMBSetFileTimes(const int xid, struc
384 - pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
386 /* At this point there is no need to override the current pid
387 with the pid of the opener, but that could change if we someday
388 use an existing handle (rather than opening one on the fly) */
389 @@ -4718,14 +4696,11 @@ CIFSSMBSetFileTimes(const int xid, struc
390 pSMB->hdr.smb_buf_length += byte_count;
391 pSMB->ByteCount = cpu_to_le16(byte_count);
392 memcpy(data_offset,data,sizeof(FILE_BASIC_INFO));
393 - rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
394 - (struct smb_hdr *) pSMBr, &bytes_returned, 0);
395 + rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
397 cFYI(1,("Send error in Set Time (SetFileInfo) = %d",rc));
400 - cifs_small_buf_release(pSMB);
402 /* Note: On -EAGAIN error only caller can retry on handle based calls
403 since file handle passed in no longer valid */
405 @@ -5016,7 +4991,8 @@ int CIFSSMBNotify(const int xid, struct
408 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
409 - (struct smb_hdr *) pSMBr, &bytes_returned, -1);
410 + (struct smb_hdr *)pSMBr, &bytes_returned,
413 cFYI(1, ("Error in Notify = %d", rc));
415 --- a/fs/cifs/connect.c 2007-11-16 17:54:37.000000000 -0500
416 +++ b/fs/cifs/connect.c 2007-11-16 17:58:21.000000000 -0500
417 @@ -2273,7 +2273,7 @@ CIFSSessSetup(unsigned int xid, struct c
418 pSMB->req_no_secext.ByteCount = cpu_to_le16(count);
420 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
421 - &bytes_returned, 1);
422 + &bytes_returned, CIFS_LONG_OP);
424 /* rc = map_smb_to_linux_error(smb_buffer_response); now done in SendReceive */
425 } else if ((smb_buffer_response->WordCount == 3)
426 @@ -2559,7 +2559,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned i
427 pSMB->req.ByteCount = cpu_to_le16(count);
429 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
430 - &bytes_returned, 1);
431 + &bytes_returned, CIFS_LONG_OP);
433 if (smb_buffer_response->Status.CifsError ==
434 cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED))
435 @@ -2985,7 +2985,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xi
436 pSMB->req.ByteCount = cpu_to_le16(count);
438 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
439 - &bytes_returned, 1);
440 + &bytes_returned, CIFS_LONG_OP);
442 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
443 } else if ((smb_buffer_response->WordCount == 3)
444 @@ -3256,7 +3256,8 @@ CIFSTCon(unsigned int xid, struct cifsSe
445 pSMB->hdr.smb_buf_length += count;
446 pSMB->ByteCount = cpu_to_le16(count);
448 - rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, 0);
449 + rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length,
452 /* if (rc) rc = map_smb_to_linux_error(smb_buffer_response); */
453 /* above now done in SendReceive */
454 --- a/fs/cifs/file.c 2007-11-16 17:54:37.000000000 -0500
455 +++ b/fs/cifs/file.c 2007-11-16 17:58:12.000000000 -0500
456 @@ -809,9 +809,9 @@ ssize_t cifs_user_write(struct file *fil
459 if (*poffset > file->f_path.dentry->d_inode->i_size)
460 - long_op = 2; /* writes past end of file can take a long time */
461 + long_op = CIFS_VLONG_OP; /* writes past EOF take long time */
464 + long_op = CIFS_LONG_OP;
466 for (total_written = 0; write_size > total_written;
467 total_written += bytes_written) {
468 @@ -858,7 +858,7 @@ ssize_t cifs_user_write(struct file *fil
471 *poffset += bytes_written;
472 - long_op = FALSE; /* subsequent writes fast -
473 + long_op = CIFS_STD_OP; /* subsequent writes fast -
474 15 seconds is plenty */
477 @@ -908,9 +908,9 @@ static ssize_t cifs_write(struct file *f
480 if (*poffset > file->f_path.dentry->d_inode->i_size)
481 - long_op = 2; /* writes past end of file can take a long time */
482 + long_op = CIFS_VLONG_OP; /* writes past EOF can be slow */
485 + long_op = CIFS_LONG_OP;
487 for (total_written = 0; write_size > total_written;
488 total_written += bytes_written) {
489 @@ -976,7 +976,7 @@ static ssize_t cifs_write(struct file *f
492 *poffset += bytes_written;
493 - long_op = FALSE; /* subsequent writes fast -
494 + long_op = CIFS_STD_OP; /* subsequent writes fast -
495 15 seconds is plenty */
498 @@ -1276,7 +1276,7 @@ retry:
500 bytes_to_write, offset,
501 &bytes_written, iov, n_iov,
504 atomic_dec(&open_file->wrtPending);
505 if (rc || bytes_written < bytes_to_write) {
506 cERROR(1,("Write2 ret %d, written = %d",
507 --- a/fs/cifs/sess.c 2007-11-16 17:54:37.000000000 -0500
508 +++ b/fs/cifs/sess.c 2007-11-16 17:58:12.000000000 -0500
509 @@ -489,7 +489,8 @@ CIFS_SessSetup(unsigned int xid, struct
511 iov[1].iov_base = str_area;
512 iov[1].iov_len = count;
513 - rc = SendReceive2(xid, ses, iov, 2 /* num_iovecs */, &resp_buf_type, 0);
514 + rc = SendReceive2(xid, ses, iov, 2 /* num_iovecs */, &resp_buf_type,
515 + CIFS_STD_OP /* not long */ | CIFS_LOG_ERROR);
516 /* SMB request buf freed in SendReceive2 */
518 cFYI(1,("ssetup rc from sendrecv2 is %d",rc));
519 --- a/fs/cifs/transport.c 2007-11-16 17:54:37.000000000 -0500
520 +++ b/fs/cifs/transport.c 2007-11-16 18:04:35.000000000 -0500
521 @@ -308,7 +308,7 @@ smb_send2(struct socket *ssocket, struct
523 static int wait_for_free_request(struct cifsSesInfo *ses, const int long_op)
525 - if(long_op == -1) {
526 + if (long_op == CIFS_ASYNC_OP) {
527 /* oplock breaks must not be held up */
528 atomic_inc(&ses->server->inFlight);
530 @@ -337,7 +337,7 @@ static int wait_for_free_request(struct
531 they are allowed to block on server */
533 /* update # of requests on the wire to server */
535 + if (long_op != CIFS_BLOCKING_OP)
536 atomic_inc(&ses->server->inFlight);
537 spin_unlock(&GlobalMid_Lock);
539 @@ -416,17 +416,48 @@ static int wait_for_response(struct cifs
546 + * Send an SMB Request. No response info (other than return code)
547 + * needs to be parsed.
549 + * flags indicate the type of request buffer and how long to wait
550 + * and whether to log NT STATUS code (error) before mapping it to POSIX error
554 +SendReceiveNoRsp(const unsigned int xid, struct cifsSesInfo *ses,
555 + struct smb_hdr *in_buf, int flags)
558 + struct kvec iov[1];
561 + iov[0].iov_base = (char *)in_buf;
562 + iov[0].iov_len = in_buf->smb_buf_length + 4;
563 + flags |= CIFS_NO_RESP;
564 + rc = SendReceive2(xid, ses, iov, 1, &resp_buf_type, flags);
565 +#ifdef CONFIG_CIFS_DEBUG2
566 + cFYI(1, ("SendRcvNoR flags %d rc %d", flags, rc));
572 SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
573 struct kvec *iov, int n_vec, int * pRespBufType /* ret */,
579 unsigned int receive_len;
580 unsigned long timeout;
581 struct mid_q_entry *midQ;
582 struct smb_hdr *in_buf = iov[0].iov_base;
584 + long_op = flags & CIFS_TIMEOUT_MASK;
586 *pRespBufType = CIFS_NO_BUFFER; /* no response buf yet */
588 if ((ses == NULL) || (ses->server == NULL)) {
589 @@ -485,15 +516,22 @@ SendReceive2(const unsigned int xid, str
595 - else if (long_op == 2) /* writes past end of file can take loong time */
596 + if (long_op == CIFS_STD_OP)
598 + else if (long_op == CIFS_VLONG_OP) /* e.g. slow writes past EOF */
600 - else if (long_op == 1)
601 + else if (long_op == CIFS_LONG_OP)
602 timeout = 45 * HZ; /* should be greater than
603 servers oplock break timeout (about 43 seconds) */
606 + else if (long_op == CIFS_ASYNC_OP)
608 + else if (long_op == CIFS_BLOCKING_OP)
609 + timeout = 0x7FFFFFFF; /* large, but not so large as to wrap */
611 + cERROR(1, ("unknown timeout flag %d", long_op));
616 /* wait for 15 seconds or until woken up due to response arriving or
617 due to last connection to this server being unmounted */
618 @@ -578,8 +616,10 @@ SendReceive2(const unsigned int xid, str
619 (2 * midQ->resp_buf->WordCount) + 2 /* bcc */ )
620 BCC(midQ->resp_buf) =
621 le16_to_cpu(BCC_LE(midQ->resp_buf));
622 - midQ->resp_buf = NULL; /* mark it so will not be freed
623 - by DeleteMidQEntry */
624 + if ((flags & CIFS_NO_RESP) == 0)
625 + midQ->resp_buf = NULL; /* mark it so buf will
630 cFYI(1,("Bad MID state?"));
631 @@ -667,17 +707,25 @@ SendReceive(const unsigned int xid, stru
636 + if (long_op == CIFS_STD_OP)
638 + /* wait for 15 seconds or until woken up due to response arriving or
639 + due to last connection to this server being unmounted */
640 + else if (long_op == CIFS_ASYNC_OP)
642 - else if (long_op == 2) /* writes past end of file can take loong time */
643 + else if (long_op == CIFS_VLONG_OP) /* writes past EOF can be slow */
645 - else if (long_op == 1)
646 + else if (long_op == CIFS_LONG_OP)
647 timeout = 45 * HZ; /* should be greater than
648 servers oplock break timeout (about 43 seconds) */
651 - /* wait for 15 seconds or until woken up due to response arriving or
652 - due to last connection to this server being unmounted */
653 + else if (long_op == CIFS_BLOCKING_OP)
654 + timeout = 0x7FFFFFFF; /* large but no so large as to wrap */
656 + cERROR(1, ("unknown timeout flag %d", long_op));
661 if (signal_pending(current)) {
662 /* if signal pending do not hold up user for full smb timeout
663 but we still give response a chance to complete */
664 @@ -817,7 +865,7 @@ send_lock_cancel(const unsigned int xid,
665 pSMB->hdr.Mid = GetNextMid(ses->server);
667 return SendReceive(xid, ses, in_buf, out_buf,
668 - &bytes_returned, 0);
669 + &bytes_returned, CIFS_STD_OP);
673 @@ -849,7 +897,7 @@ SendReceiveBlockingLock(const unsigned i
674 to the same server. We may make this configurable later or
677 - rc = wait_for_free_request(ses, 3);
678 + rc = wait_for_free_request(ses, CIFS_BLOCKING_OP);