v2.6.22.21-op1
[linux-2.6.22.y-op-patches.git] / release-2.6.22.y / 2.6.22.21-op1 / cifs-fix-buffer-overflow-with-corrupt-response.patch
bloba9294332e90a45255141d17baed70c51edb31239
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
9 request
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,
19 Lock and PosixLock
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>
28 ---
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 +++----
35 fs/cifs/sess.c | 3 +
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 */
81 int rc = 0;
82 - int length;
84 cFYI(1, ("In tree disconnect"));
86 @@ -699,16 +697,12 @@ CIFSSMBTDis(const int xid, struct cifsTc
87 if (rc) {
88 up(&tcon->tconSem);
89 return rc;
90 - } else {
91 - smb_buffer_response = smb_buffer; /* BB removeme BB */
93 - rc = SendReceive(xid, tcon->ses, smb_buffer, smb_buffer_response,
94 - &length, 0);
96 + rc = SendReceiveNoRsp(xid, tcon->ses, smb_buffer, 0);
97 if (rc)
98 cFYI(1, ("Tree disconnect failed %d", rc));
100 - if (smb_buffer)
101 - cifs_small_buf_release(smb_buffer);
102 up(&tcon->tconSem);
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;
111 int rc = 0;
112 - int length;
114 cFYI(1, ("In SMBLogoff for session disconnect"));
115 if (ses)
116 @@ -744,8 +736,6 @@ CIFSSMBLogoff(const int xid, struct cifs
117 return rc;
120 - smb_buffer_response = (struct smb_hdr *)pSMB; /* BB removeme BB */
122 if(ses->server) {
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);
132 if (ses->server) {
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
138 up(&ses->sesSem);
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);
150 if (rc) {
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);
159 if (rc) {
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,
164 1 /* num iovecs */,
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;
169 if (rc) {
170 @@ -1596,7 +1584,7 @@ CIFSSMBLock(const int xid, struct cifsTc
171 int timeout = 0;
172 __u16 count;
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);
178 if (rc)
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 */
185 pSMB->Timeout = 0;
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 */
190 } else {
191 pSMB->Timeout = 0;
192 @@ -1638,15 +1626,16 @@ CIFSSMBLock(const int xid, struct cifsTc
193 if (waitFlag) {
194 rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
195 (struct smb_hdr *) pSMBr, &bytes_returned);
196 + cifs_small_buf_release(pSMB);
197 } else {
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,
201 + timeout);
202 + /* SMB buffer freed by function above */
204 cifs_stats_inc(&tcon->num_locks);
205 if (rc) {
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
213 int rc = 0;
214 int timeout = 0;
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);
225 if(waitFlag) {
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);
230 } else
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);
234 } else {
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;
246 if (rc) {
247 @@ -1766,6 +1762,11 @@ plk_err_exit:
248 if (pSMB)
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
261 int rc = 0;
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
269 if (rc)
270 return rc;
272 - pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
274 pSMB->FileID = (__u16) smb_file_id;
275 pSMB->LastWriteTime = 0xFFFFFFFF;
276 pSMB->ByteCount = 0;
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);
281 if (rc) {
282 if(rc!=-EINTR) {
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 */
290 if(rc == -EAGAIN)
291 rc = 0;
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,
298 + CIFS_STD_OP);
299 cifs_stats_inc(&tcon->num_acl_get);
300 if (rc) {
301 cFYI(1, ("Send error in QuerySecDesc = %d", rc));
302 @@ -3634,8 +3629,6 @@ CIFSFindClose(const int xid, struct cifs
304 int rc = 0;
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
312 if (rc)
313 return rc;
315 - pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
316 pSMB->FileID = searchHandle;
317 pSMB->ByteCount = 0;
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);
321 if (rc) {
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 */
328 if (rc == -EAGAIN)
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;
334 char *data_offset;
335 struct file_end_of_file_info *parm_data;
336 int rc = 0;
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
342 if (rc)
343 return rc;
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
351 pSMB->Reserved4 = 0;
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);
357 if (rc) {
358 cFYI(1,
359 ("Send error in SetFileInfo (SetFileSize) = %d",
360 rc));
363 - if (pSMB)
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
370 __u16 fid)
372 struct smb_com_transaction2_sfi_req *pSMB = NULL;
373 - struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
374 char *data_offset;
375 int rc = 0;
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
381 if (rc)
382 return rc;
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);
396 if (rc) {
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
406 pSMB->ByteCount = 0;
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,
411 + CIFS_ASYNC_OP);
412 if (rc) {
413 cFYI(1, ("Error in Notify = %d", rc));
414 } else {
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);
423 if (rc) {
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);
441 if (rc) {
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,
450 + CIFS_STD_OP);
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
457 xid = GetXid();
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 */
462 else
463 - long_op = 1;
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
470 } else
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
478 xid = GetXid();
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 */
483 else
484 - long_op = 1;
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
491 } else
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:
499 open_file->netfid,
500 bytes_to_write, offset,
501 &bytes_written, iov, n_iov,
502 - 1);
503 + CIFS_LONG_OP);
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);
529 } else {
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 */
534 - if (long_op < 3)
535 + if (long_op != CIFS_BLOCKING_OP)
536 atomic_inc(&ses->server->inFlight);
537 spin_unlock(&GlobalMid_Lock);
538 break;
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
552 + */
553 +int
554 +SendReceiveNoRsp(const unsigned int xid, struct cifsSesInfo *ses,
555 + struct smb_hdr *in_buf, int flags)
557 + int rc;
558 + struct kvec iov[1];
559 + int resp_buf_type;
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));
567 +#endif
568 + return rc;
572 SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
573 struct kvec *iov, int n_vec, int * pRespBufType /* ret */,
574 - const int long_op)
575 + const int flags)
577 int rc = 0;
578 + int long_op;
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
590 if(rc < 0)
591 goto out;
593 - if (long_op == -1)
594 - goto out;
595 - else if (long_op == 2) /* writes past end of file can take loong time */
596 + if (long_op == CIFS_STD_OP)
597 + timeout = 15 * HZ;
598 + else if (long_op == CIFS_VLONG_OP) /* e.g. slow writes past EOF */
599 timeout = 180 * HZ;
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) */
604 - else
605 - timeout = 15 * HZ;
606 + else if (long_op == CIFS_ASYNC_OP)
607 + goto out;
608 + else if (long_op == CIFS_BLOCKING_OP)
609 + timeout = 0x7FFFFFFF; /* large, but not so large as to wrap */
610 + else {
611 + cERROR(1, ("unknown timeout flag %d", long_op));
612 + rc = -EIO;
613 + goto out;
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
626 + not be freed by
627 + DeleteMidQEntry */
628 } else {
629 rc = -EIO;
630 cFYI(1,("Bad MID state?"));
631 @@ -667,17 +707,25 @@ SendReceive(const unsigned int xid, stru
632 if(rc < 0)
633 goto out;
635 - if (long_op == -1)
636 + if (long_op == CIFS_STD_OP)
637 + timeout = 15 * HZ;
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)
641 goto out;
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 */
644 timeout = 180 * HZ;
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) */
649 - else
650 - timeout = 15 * HZ;
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 */
655 + else {
656 + cERROR(1, ("unknown timeout flag %d", long_op));
657 + rc = -EIO;
658 + goto out;
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
675 use ses->maxReq */
677 - rc = wait_for_free_request(ses, 3);
678 + rc = wait_for_free_request(ses, CIFS_BLOCKING_OP);
679 if (rc)
680 return rc;