diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/cifs/CHANGES | 18 | ||||
-rw-r--r-- | fs/cifs/Makefile | 2 | ||||
-rw-r--r-- | fs/cifs/README | 7 | ||||
-rw-r--r-- | fs/cifs/cifsencrypt.c | 6 | ||||
-rw-r--r-- | fs/cifs/cifsfs.c | 5 | ||||
-rw-r--r-- | fs/cifs/cifsfs.h | 2 | ||||
-rw-r--r-- | fs/cifs/cifsglob.h | 11 | ||||
-rw-r--r-- | fs/cifs/cifspdu.h | 13 | ||||
-rw-r--r-- | fs/cifs/cifsproto.h | 15 | ||||
-rw-r--r-- | fs/cifs/cifssmb.c | 126 | ||||
-rw-r--r-- | fs/cifs/connect.c | 99 | ||||
-rw-r--r-- | fs/cifs/dir.c | 4 | ||||
-rw-r--r-- | fs/cifs/file.c | 94 | ||||
-rw-r--r-- | fs/cifs/inode.c | 7 | ||||
-rw-r--r-- | fs/cifs/link.c | 2 | ||||
-rw-r--r-- | fs/cifs/misc.c | 46 | ||||
-rw-r--r-- | fs/cifs/ntlmssp.c | 129 | ||||
-rw-r--r-- | fs/cifs/ntlmssp.h | 2 | ||||
-rw-r--r-- | fs/cifs/readdir.c | 7 | ||||
-rw-r--r-- | fs/cifs/transport.c | 22 |
20 files changed, 484 insertions, 133 deletions
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index d335015473a5..3e0fcc394810 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES @@ -1,3 +1,21 @@ +Version 1.42 +------------ +Fix slow oplock break when mounted to different servers at the same time and +the tids match and we try to find matching fid on wrong server. + +Version 1.41 +------------ +Fix NTLMv2 security (can be enabled in /proc/fs/cifs) so customers can +configure stronger authentication. Fix sfu symlinks so they can +be followed (not just recognized). Fix wraparound of bcc on +read responses when buffer size over 64K and also fix wrap of +max smb buffer size when CIFSMaxBufSize over 64K. Fix oops in +cifs_user_read and cifs_readpages (when EAGAIN on send of smb +on socket is returned over and over). Add POSIX (advisory) byte range +locking support (requires server with newest CIFS UNIX Extensions +to the protocol implemented). Slow down negprot slightly in port 139 +RFC1001 case to give session_init time on buggy servers. + Version 1.40 ------------ Use fsuid (fsgid) more consistently instead of uid (gid). Improve performance diff --git a/fs/cifs/Makefile b/fs/cifs/Makefile index 7384947a0f93..58c77254a23b 100644 --- a/fs/cifs/Makefile +++ b/fs/cifs/Makefile @@ -3,4 +3,4 @@ # obj-$(CONFIG_CIFS) += cifs.o -cifs-objs := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o md4.o md5.o cifs_unicode.o nterr.o xattr.o cifsencrypt.o fcntl.o readdir.o ioctl.o +cifs-objs := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o md4.o md5.o cifs_unicode.o nterr.o xattr.o cifsencrypt.o fcntl.o readdir.o ioctl.o ntlmssp.o diff --git a/fs/cifs/README b/fs/cifs/README index b0070d1b149d..b2b4d0803761 100644 --- a/fs/cifs/README +++ b/fs/cifs/README @@ -422,6 +422,13 @@ A partial list of the supported mount options follows: nomapchars Do not translate any of these seven characters (default). nocase Request case insensitive path name matching (case sensitive is the default if the server suports it). + posixpaths If CIFS Unix extensions are supported, attempt to + negotiate posix path name support which allows certain + characters forbidden in typical CIFS filenames, without + requiring remapping. (default) + noposixpaths If CIFS Unix extensions are supported, do not request + posix path name support (this may cause servers to + reject creatingfile with certain reserved characters). nobrl Do not send byte range lock requests to the server. This is necessary for certain applications that break with cifs style mandatory byte range locks (and most diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c index a2c24858d40f..c2cbe0ed98b3 100644 --- a/fs/cifs/cifsencrypt.c +++ b/fs/cifs/cifsencrypt.c @@ -1,7 +1,7 @@ /* * fs/cifs/cifsencrypt.c * - * Copyright (C) International Business Machines Corp., 2005 + * Copyright (C) International Business Machines Corp., 2005,2006 * Author(s): Steve French (sfrench@us.ibm.com) * * This library is free software; you can redistribute it and/or modify @@ -36,7 +36,8 @@ extern void mdfour(unsigned char *out, unsigned char *in, int n); extern void E_md4hash(const unsigned char *passwd, unsigned char *p16); -static int cifs_calculate_signature(const struct smb_hdr * cifs_pdu, const char * key, char * signature) +static int cifs_calculate_signature(const struct smb_hdr * cifs_pdu, + const char * key, char * signature) { struct MD5Context context; @@ -259,4 +260,5 @@ void CalcNTLMv2_response(const struct cifsSesInfo * ses,char * v2_session_respon /* hmac_md5_update(v2_session_response+16)client thing,8,&context); */ /* BB fix */ hmac_md5_final(v2_session_response,&context); + cifs_dump_mem("v2_sess_rsp: ", v2_session_response, 32); /* BB removeme BB */ } diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 79eeccd0437f..8219c02145a7 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -93,13 +93,10 @@ cifs_read_super(struct super_block *sb, void *data, int rc = 0; sb->s_flags |= MS_NODIRATIME; /* and probably even noatime */ - sb->s_fs_info = kmalloc(sizeof(struct cifs_sb_info),GFP_KERNEL); + sb->s_fs_info = kzalloc(sizeof(struct cifs_sb_info),GFP_KERNEL); cifs_sb = CIFS_SB(sb); if(cifs_sb == NULL) return -ENOMEM; - else - memset(cifs_sb,0,sizeof(struct cifs_sb_info)); - rc = cifs_mount(sb, cifs_sb, data, devname); diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index 821a8eb22559..b4dcdc2052a0 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h @@ -99,5 +99,5 @@ extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t); extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); extern int cifs_ioctl (struct inode * inode, struct file * filep, unsigned int command, unsigned long arg); -#define CIFS_VERSION "1.40" +#define CIFS_VERSION "1.42" #endif /* _CIFSFS_H */ diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 7bed27601ce5..006eb33bff5f 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -1,7 +1,7 @@ /* * fs/cifs/cifsglob.h * - * Copyright (C) International Business Machines Corp., 2002,2005 + * Copyright (C) International Business Machines Corp., 2002,2006 * Author(s): Steve French (sfrench@us.ibm.com) * * This library is free software; you can redistribute it and/or modify @@ -430,6 +430,15 @@ struct dir_notify_req { #define CIFS_LARGE_BUFFER 2 #define CIFS_IOVEC 4 /* array of response buffers */ +/* Type of session setup needed */ +#define CIFS_PLAINTEXT 0 +#define CIFS_LANMAN 1 +#define CIFS_NTLM 2 +#define CIFS_NTLMSSP_NEG 3 +#define CIFS_NTLMSSP_AUTH 4 +#define CIFS_SPNEGO_INIT 5 +#define CIFS_SPNEGO_TARG 6 + /* ***************************************************************** * All constants go here diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h index cc2471094ca5..b2233ac05bd2 100644 --- a/fs/cifs/cifspdu.h +++ b/fs/cifs/cifspdu.h @@ -859,7 +859,10 @@ typedef struct smb_com_lock_req { LOCKING_ANDX_RANGE Locks[1]; } __attribute__((packed)) LOCK_REQ; - +/* lock type */ +#define CIFS_RDLCK 0 +#define CIFS_WRLCK 1 +#define CIFS_UNLCK 2 typedef struct cifs_posix_lock { __le16 lock_type; /* 0 = Read, 1 = Write, 2 = Unlock */ __le16 lock_flags; /* 1 = Wait (only valid for setlock) */ @@ -1786,7 +1789,13 @@ typedef struct { #define CIFS_UNIX_POSIX_ACL_CAP 0x00000002 /* support getfacl/setfacl */ #define CIFS_UNIX_XATTR_CAP 0x00000004 /* support new namespace */ #define CIFS_UNIX_EXTATTR_CAP 0x00000008 /* support chattr/chflag */ -#define CIFS_UNIX_POSIX_PATHNAMES_CAP 0x00000010 /* Use POSIX pathnames on the wire. */ +#define CIFS_UNIX_POSIX_PATHNAMES_CAP 0x00000010 /* Allow POSIX path chars */ +#ifdef CONFIG_CIFS_POSIX +#define CIFS_UNIX_CAP_MASK 0x0000001b +#else +#define CIFS_UNIX_CAP_MASK 0x00000013 +#endif /* CONFIG_CIFS_POSIX */ + #define CIFS_POSIX_EXTENSIONS 0x00000010 /* support for new QFSInfo */ diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 7b25463d3c14..2879ba343ca7 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -1,7 +1,7 @@ /* * fs/cifs/cifsproto.h * - * Copyright (c) International Business Machines Corp., 2002,2005 + * Copyright (c) International Business Machines Corp., 2002,2006 * Author(s): Steve French (sfrench@us.ibm.com) * * This library is free software; you can redistribute it and/or modify @@ -64,6 +64,14 @@ extern int map_smb_to_linux_error(struct smb_hdr *smb); extern void header_assemble(struct smb_hdr *, char /* command */ , const struct cifsTconInfo *, int /* length of fixed section (word count) in two byte units */); +#ifdef CONFIG_CIFS_EXPERIMENTAL +extern int small_smb_init_no_tc(const int smb_cmd, const int wct, + struct cifsSesInfo *ses, + void ** request_buf); +extern int CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, + const int stage, int * pNTLMv2_flg, + const struct nls_table *nls_cp); +#endif extern __u16 GetNextMid(struct TCP_Server_Info *server); extern struct oplock_q_entry * AllocOplockQEntry(struct inode *, u16, struct cifsTconInfo *); @@ -257,7 +265,10 @@ extern int CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, const __u64 offset, const __u32 numUnlock, const __u32 numLock, const __u8 lockType, const int waitFlag); - +extern int CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon, + const __u16 smb_file_id, const int get_flag, + const __u64 len, const __u64 offset, + const __u16 lock_type, const int waitFlag); extern int CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon); extern int CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses); diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index b41e8b379652..3e89fbbd160f 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -1,7 +1,7 @@ /* * fs/cifs/cifssmb.c * - * Copyright (C) International Business Machines Corp., 2002,2005 + * Copyright (C) International Business Machines Corp., 2002,2006 * Author(s): Steve French (sfrench@us.ibm.com) * * Contains the routines for constructing the SMB PDUs themselves @@ -186,7 +186,35 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon, cifs_stats_inc(&tcon->num_smbs_sent); return rc; -} +} + +#ifdef CONFIG_CIFS_EXPERIMENTAL +int +small_smb_init_no_tc(const int smb_command, const int wct, + struct cifsSesInfo *ses, void **request_buf) +{ + int rc; + struct smb_hdr * buffer; + + rc = small_smb_init(smb_command, wct, NULL, request_buf); + if(rc) + return rc; + + buffer = (struct smb_hdr *)*request_buf; + buffer->Mid = GetNextMid(ses->server); + if (ses->capabilities & CAP_UNICODE) + buffer->Flags2 |= SMBFLG2_UNICODE; + if (ses->capabilities & CAP_STATUS32) + buffer->Flags2 |= SMBFLG2_ERR_STATUS; + + /* uid, tid can stay at zero as set in header assemble */ + + /* BB add support for turning on the signing when + this function is used after 1st of session setup requests */ + + return rc; +} +#endif /* CONFIG_CIFS_EXPERIMENTAL */ /* If the return code is zero, this function must fill in request_buf pointer */ static int @@ -1042,7 +1070,7 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, } } - cifs_small_buf_release(pSMB); +/* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */ if(*buf) { if(resp_buf_type == CIFS_SMALL_BUFFER) cifs_small_buf_release(iov[0].iov_base); @@ -1246,7 +1274,7 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon, *nbytes += le16_to_cpu(pSMBr->Count); } - cifs_small_buf_release(pSMB); +/* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */ if(resp_buf_type == CIFS_SMALL_BUFFER) cifs_small_buf_release(iov[0].iov_base); else if(resp_buf_type == CIFS_LARGE_BUFFER) @@ -1325,6 +1353,85 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, } int +CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon, + const __u16 smb_file_id, const int get_flag, const __u64 len, + const __u64 lkoffset, const __u16 lock_type, const int waitFlag) +{ + struct smb_com_transaction2_sfi_req *pSMB = NULL; + struct smb_com_transaction2_sfi_rsp *pSMBr = NULL; + char *data_offset; + struct cifs_posix_lock *parm_data; + int rc = 0; + int bytes_returned = 0; + __u16 params, param_offset, offset, byte_count, count; + + cFYI(1, ("Posix Lock")); + rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB); + + if (rc) + return rc; + + pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB; + + params = 6; + pSMB->MaxSetupCount = 0; + pSMB->Reserved = 0; + pSMB->Flags = 0; + pSMB->Timeout = 0; + pSMB->Reserved2 = 0; + param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4; + offset = param_offset + params; + + data_offset = (char *) (&pSMB->hdr.Protocol) + offset; + + count = sizeof(struct cifs_posix_lock); + pSMB->MaxParameterCount = cpu_to_le16(2); + pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */ + pSMB->SetupCount = 1; + pSMB->Reserved3 = 0; + if(get_flag) + pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION); + else + pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION); + byte_count = 3 /* pad */ + params + count; + pSMB->DataCount = cpu_to_le16(count); + pSMB->ParameterCount = cpu_to_le16(params); + pSMB->TotalDataCount = pSMB->DataCount; + pSMB->TotalParameterCount = pSMB->ParameterCount; + pSMB->ParameterOffset = cpu_to_le16(param_offset); + parm_data = (struct cifs_posix_lock *) + (((char *) &pSMB->hdr.Protocol) + offset); + + parm_data->lock_type = cpu_to_le16(lock_type); + if(waitFlag) + parm_data->lock_flags = 1; + parm_data->pid = cpu_to_le32(current->tgid); + parm_data->start = lkoffset; + parm_data->length = len; /* normalize negative numbers */ + + pSMB->DataOffset = cpu_to_le16(offset); + pSMB->Fid = smb_file_id; + pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK); + pSMB->Reserved4 = 0; + pSMB->hdr.smb_buf_length += byte_count; + pSMB->ByteCount = cpu_to_le16(byte_count); + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, + (struct smb_hdr *) pSMBr, &bytes_returned, 0); + if (rc) { + cFYI(1, ("Send error in Posix Lock = %d", rc)); + } + + if (pSMB) + cifs_small_buf_release(pSMB); + + /* Note: On -EAGAIN error only caller can retry on handle based calls + since file handle passed in no longer valid */ + + return rc; +} + + +int CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id) { int rc = 0; @@ -2578,7 +2685,7 @@ qsec_out: cifs_small_buf_release(iov[0].iov_base); else if(buf_type == CIFS_LARGE_BUFFER) cifs_buf_release(iov[0].iov_base); - cifs_small_buf_release(pSMB); +/* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */ return rc; } @@ -2998,6 +3105,7 @@ findFirstRetry: psrch_inf->unicode = FALSE; psrch_inf->ntwrk_buf_start = (char *)pSMBr; + psrch_inf->smallBuf = 0; psrch_inf->srch_entries_start = (char *) &pSMBr->hdr.Protocol + le16_to_cpu(pSMBr->t2.DataOffset); @@ -3118,9 +3226,14 @@ int CIFSFindNext(const int xid, struct cifsTconInfo *tcon, parms = (T2_FNEXT_RSP_PARMS *)response_data; response_data = (char *)&pSMBr->hdr.Protocol + le16_to_cpu(pSMBr->t2.DataOffset); - cifs_buf_release(psrch_inf->ntwrk_buf_start); + if(psrch_inf->smallBuf) + cifs_small_buf_release( + psrch_inf->ntwrk_buf_start); + else + cifs_buf_release(psrch_inf->ntwrk_buf_start); psrch_inf->srch_entries_start = response_data; psrch_inf->ntwrk_buf_start = (char *)pSMB; + psrch_inf->smallBuf = 0; if(parms->EndofSearch) psrch_inf->endOfSearch = TRUE; else @@ -3834,6 +3947,7 @@ CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap) cFYI(1, ("In SETFSUnixInfo")); SETFSUnixRetry: + /* BB switch to small buf init to save memory */ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, (void **) &pSMBr); if (rc) diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 2a0c1f4ca0ae..0b86d5ca9014 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -1,7 +1,7 @@ /* * fs/cifs/connect.c * - * Copyright (C) International Business Machines Corp., 2002,2005 + * Copyright (C) International Business Machines Corp., 2002,2006 * Author(s): Steve French (sfrench@us.ibm.com) * * This library is free software; you can redistribute it and/or modify @@ -564,7 +564,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) dump_smb(smb_buffer, length); - if (checkSMB (smb_buffer, smb_buffer->Mid, total_read+4)) { + if (checkSMB(smb_buffer, smb_buffer->Mid, total_read+4)) { cifs_dump_mem("Bad SMB: ", smb_buffer, 48); continue; } @@ -1476,6 +1476,14 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket, rc = smb_send(*csocket, smb_buf, 0x44, (struct sockaddr *)psin_server); kfree(ses_init_buf); + msleep(1); /* RFC1001 layer in at least one server + requires very short break before negprot + presumably because not expecting negprot + to follow so fast. This is a simple + solution that works without + complicating the code and causes no + significant slowing down on mount + for everyone else */ } /* else the negprot may still work without this even though malloc failed */ @@ -1920,27 +1928,34 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, cifs_sb->tcon = tcon; tcon->ses = pSesInfo; - /* do not care if following two calls succeed - informational only */ + /* do not care if following two calls succeed - informational */ CIFSSMBQFSDeviceInfo(xid, tcon); CIFSSMBQFSAttributeInfo(xid, tcon); + if (tcon->ses->capabilities & CAP_UNIX) { if(!CIFSSMBQFSUnixInfo(xid, tcon)) { - if(!volume_info.no_psx_acl) { - if(CIFS_UNIX_POSIX_ACL_CAP & - le64_to_cpu(tcon->fsUnixInfo.Capability)) - cFYI(1,("server negotiated posix acl support")); - sb->s_flags |= MS_POSIXACL; + __u64 cap = + le64_to_cpu(tcon->fsUnixInfo.Capability); + cap &= CIFS_UNIX_CAP_MASK; + if(volume_info.no_psx_acl) + cap &= ~CIFS_UNIX_POSIX_ACL_CAP; + else if(CIFS_UNIX_POSIX_ACL_CAP & cap) { + cFYI(1,("negotiated posix acl support")); + sb->s_flags |= MS_POSIXACL; } - /* Try and negotiate POSIX pathnames if we can. */ - if (volume_info.posix_paths && (CIFS_UNIX_POSIX_PATHNAMES_CAP & - le64_to_cpu(tcon->fsUnixInfo.Capability))) { - if (!CIFSSMBSetFSUnixInfo(xid, tcon, CIFS_UNIX_POSIX_PATHNAMES_CAP)) { - cFYI(1,("negotiated posix pathnames support")); - cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS; - } else { - cFYI(1,("posix pathnames support requested but not supported")); - } + if(volume_info.posix_paths == 0) + cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP; + else if(cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) { + cFYI(1,("negotiate posix pathnames")); + cifs_sb->mnt_cifs_flags |= + CIFS_MOUNT_POSIX_PATHS; + } + + cFYI(1,("Negotiate caps 0x%x",(int)cap)); + + if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) { + cFYI(1,("setting capabilities failed")); } } } @@ -2278,6 +2293,8 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses, smb_buffer->Mid = GetNextMid(ses->server); pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; pSMB->req.AndXCommand = 0xFF; + if(ses->server->maxBuf > 64*1024) + ses->server->maxBuf = (64*1023); pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf); pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq); @@ -2525,7 +2542,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, __u32 negotiate_flags, capabilities; __u16 count; - cFYI(1, ("In NTLMSSP sesssetup (negotiate) ")); + cFYI(1, ("In NTLMSSP sesssetup (negotiate)")); if(ses == NULL) return -EINVAL; domain = ses->domainName; @@ -2575,7 +2592,8 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, SecurityBlob->MessageType = NtLmNegotiate; negotiate_flags = NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM | - NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM | 0x80000000 | + NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM | + NTLMSSP_NEGOTIATE_56 | /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128; if(sign_CIFS_PDUs) negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN; @@ -2588,26 +2606,11 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, SecurityBlob->WorkstationName.Length = 0; SecurityBlob->WorkstationName.MaximumLength = 0; - if (domain == NULL) { - SecurityBlob->DomainName.Buffer = 0; - SecurityBlob->DomainName.Length = 0; - SecurityBlob->DomainName.MaximumLength = 0; - } else { - __u16 len; - negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED; - strncpy(bcc_ptr, domain, 63); - len = strnlen(domain, 64); - SecurityBlob->DomainName.MaximumLength = - cpu_to_le16(len); - SecurityBlob->DomainName.Buffer = - cpu_to_le32((long) &SecurityBlob-> - DomainString - - (long) &SecurityBlob->Signature); - bcc_ptr += len; - SecurityBlobLength += len; - SecurityBlob->DomainName.Length = - cpu_to_le16(len); - } + /* Domain not sent on first Sesssetup in NTLMSSP, instead it is sent + along with username on auth request (ie the response to challenge) */ + SecurityBlob->DomainName.Buffer = 0; + SecurityBlob->DomainName.Length = 0; + SecurityBlob->DomainName.MaximumLength = 0; if (ses->capabilities & CAP_UNICODE) { if ((long) bcc_ptr % 2) { *bcc_ptr = 0; @@ -2677,7 +2680,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, SecurityBlob2->MessageType)); } else if (ses) { ses->Suid = smb_buffer_response->Uid; /* UID left in le format */ - cFYI(1, ("UID = %d ", ses->Suid)); + cFYI(1, ("UID = %d", ses->Suid)); if ((pSMBr->resp.hdr.WordCount == 3) || ((pSMBr->resp.hdr.WordCount == 4) && (blob_len < @@ -2685,17 +2688,17 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, if (pSMBr->resp.hdr.WordCount == 4) { bcc_ptr += blob_len; - cFYI(1, - ("Security Blob Length %d ", + cFYI(1, ("Security Blob Length %d", blob_len)); } - cFYI(1, ("NTLMSSP Challenge rcvd ")); + cFYI(1, ("NTLMSSP Challenge rcvd")); memcpy(ses->server->cryptKey, SecurityBlob2->Challenge, CIFS_CRYPTO_KEY_SIZE); - if(SecurityBlob2->NegotiateFlags & cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2)) + if(SecurityBlob2->NegotiateFlags & + cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2)) *pNTLMv2_flag = TRUE; if((SecurityBlob2->NegotiateFlags & @@ -2818,7 +2821,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, bcc_ptr++; } else cFYI(1, - ("Variable field of length %d extends beyond end of smb ", + ("Variable field of length %d extends beyond end of smb", len)); } } else { @@ -2830,7 +2833,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, } } else { cERROR(1, - (" Invalid Word count %d: ", + (" Invalid Word count %d:", smb_buffer_response->WordCount)); rc = -EIO; } @@ -3447,7 +3450,7 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, if (extended_security && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY) && (pSesInfo->server->secType == NTLMSSP)) { - cFYI(1, ("New style sesssetup ")); + cFYI(1, ("New style sesssetup")); rc = CIFSSpnegoSessSetup(xid, pSesInfo, NULL /* security blob */, 0 /* blob length */, @@ -3455,7 +3458,7 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, } else if (extended_security && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY) && (pSesInfo->server->secType == RawNTLMSSP)) { - cFYI(1, ("NTLMSSP sesssetup ")); + cFYI(1, ("NTLMSSP sesssetup")); rc = CIFSNTLMSSPNegotiateSessSetup(xid, pSesInfo, &ntlmv2_flag, diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index fed55e3c53df..77e1fc01d747 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -255,12 +255,10 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, CIFSSMBClose(xid, pTcon, fileHandle); } else if(newinode) { pCifsFile = - kmalloc(sizeof (struct cifsFileInfo), GFP_KERNEL); + kzalloc(sizeof (struct cifsFileInfo), GFP_KERNEL); if(pCifsFile == NULL) goto cifs_create_out; - memset((char *)pCifsFile, 0, - sizeof (struct cifsFileInfo)); pCifsFile->netfid = fileHandle; pCifsFile->pid = current->tgid; pCifsFile->pInode = newinode; diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 675bd2568297..2c093de26225 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -555,7 +555,10 @@ int cifs_closedir(struct inode *inode, struct file *file) if (ptmp) { cFYI(1, ("closedir free smb buf in srch struct")); pCFileStruct->srch_inf.ntwrk_buf_start = NULL; - cifs_buf_release(ptmp); + if(pCFileStruct->srch_inf.smallBuf) + cifs_small_buf_release(ptmp); + else + cifs_buf_release(ptmp); } ptmp = pCFileStruct->search_resume_name; if (ptmp) { @@ -574,13 +577,14 @@ int cifs_closedir(struct inode *inode, struct file *file) int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) { int rc, xid; - __u32 lockType = LOCKING_ANDX_LARGE_FILES; __u32 numLock = 0; __u32 numUnlock = 0; __u64 length; int wait_flag = FALSE; struct cifs_sb_info *cifs_sb; struct cifsTconInfo *pTcon; + __u16 netfid; + __u8 lockType = LOCKING_ANDX_LARGE_FILES; length = 1 + pfLock->fl_end - pfLock->fl_start; rc = -EACCES; @@ -592,11 +596,11 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) pfLock->fl_end)); if (pfLock->fl_flags & FL_POSIX) - cFYI(1, ("Posix ")); + cFYI(1, ("Posix")); if (pfLock->fl_flags & FL_FLOCK) - cFYI(1, ("Flock ")); + cFYI(1, ("Flock")); if (pfLock->fl_flags & FL_SLEEP) { - cFYI(1, ("Blocking lock ")); + cFYI(1, ("Blocking lock")); wait_flag = TRUE; } if (pfLock->fl_flags & FL_ACCESS) @@ -612,21 +616,23 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) cFYI(1, ("F_WRLCK ")); numLock = 1; } else if (pfLock->fl_type == F_UNLCK) { - cFYI(1, ("F_UNLCK ")); + cFYI(1, ("F_UNLCK")); numUnlock = 1; + /* Check if unlock includes more than + one lock range */ } else if (pfLock->fl_type == F_RDLCK) { - cFYI(1, ("F_RDLCK ")); + cFYI(1, ("F_RDLCK")); lockType |= LOCKING_ANDX_SHARED_LOCK; numLock = 1; } else if (pfLock->fl_type == F_EXLCK) { - cFYI(1, ("F_EXLCK ")); + cFYI(1, ("F_EXLCK")); numLock = 1; } else if (pfLock->fl_type == F_SHLCK) { - cFYI(1, ("F_SHLCK ")); + cFYI(1, ("F_SHLCK")); lockType |= LOCKING_ANDX_SHARED_LOCK; numLock = 1; } else - cFYI(1, ("Unknown type of lock ")); + cFYI(1, ("Unknown type of lock")); cifs_sb = CIFS_SB(file->f_dentry->d_sb); pTcon = cifs_sb->tcon; @@ -635,27 +641,41 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) FreeXid(xid); return -EBADF; } + netfid = ((struct cifsFileInfo *)file->private_data)->netfid; + + /* BB add code here to normalize offset and length to + account for negative length which we can not accept over the + wire */ if (IS_GETLK(cmd)) { - rc = CIFSSMBLock(xid, pTcon, - ((struct cifsFileInfo *)file-> - private_data)->netfid, - length, - pfLock->fl_start, 0, 1, lockType, - 0 /* wait flag */ ); + if(experimEnabled && + (cifs_sb->tcon->ses->capabilities & CAP_UNIX) && + (CIFS_UNIX_FCNTL_CAP & + le64_to_cpu(cifs_sb->tcon->fsUnixInfo.Capability))) { + int posix_lock_type; + if(lockType & LOCKING_ANDX_SHARED_LOCK) + posix_lock_type = CIFS_RDLCK; + else + posix_lock_type = CIFS_WRLCK; + rc = CIFSSMBPosixLock(xid, pTcon, netfid, 1 /* get */, + length, pfLock->fl_start, + posix_lock_type, wait_flag); + FreeXid(xid); + return rc; + } + + /* BB we could chain these into one lock request BB */ + rc = CIFSSMBLock(xid, pTcon, netfid, length, pfLock->fl_start, + 0, 1, lockType, 0 /* wait flag */ ); if (rc == 0) { - rc = CIFSSMBLock(xid, pTcon, - ((struct cifsFileInfo *) file-> - private_data)->netfid, - length, + rc = CIFSSMBLock(xid, pTcon, netfid, length, pfLock->fl_start, 1 /* numUnlock */ , 0 /* numLock */ , lockType, 0 /* wait flag */ ); pfLock->fl_type = F_UNLCK; if (rc != 0) cERROR(1, ("Error unlocking previously locked " - "range %d during test of lock ", - rc)); + "range %d during test of lock", rc)); rc = 0; } else { @@ -667,12 +687,30 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) FreeXid(xid); return rc; } - - rc = CIFSSMBLock(xid, pTcon, - ((struct cifsFileInfo *) file->private_data)-> - netfid, length, - pfLock->fl_start, numUnlock, numLock, lockType, - wait_flag); + if (experimEnabled && + (cifs_sb->tcon->ses->capabilities & CAP_UNIX) && + (CIFS_UNIX_FCNTL_CAP & + le64_to_cpu(cifs_sb->tcon->fsUnixInfo.Capability))) { + int posix_lock_type; + if(lockType & LOCKING_ANDX_SHARED_LOCK) + posix_lock_type = CIFS_RDLCK; + else + posix_lock_type = CIFS_WRLCK; + + if(numUnlock == 1) + posix_lock_type = CIFS_UNLCK; + else if(numLock == 0) { + /* if no lock or unlock then nothing + to do since we do not know what it is */ + FreeXid(xid); + return -EOPNOTSUPP; + } + rc = CIFSSMBPosixLock(xid, pTcon, netfid, 0 /* set */, + length, pfLock->fl_start, + posix_lock_type, wait_flag); + } else + rc = CIFSSMBLock(xid, pTcon, netfid, length, pfLock->fl_start, + numUnlock, numLock, lockType, wait_flag); if (pfLock->fl_flags & FL_POSIX) posix_lock_file_wait(file, pfLock); FreeXid(xid); diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 59359911f481..b21038b99fc2 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -609,9 +609,8 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry) } } else if (rc == -EACCES) { /* try only if r/o attribute set in local lookup data? */ - pinfo_buf = kmalloc(sizeof(FILE_BASIC_INFO), GFP_KERNEL); + pinfo_buf = kzalloc(sizeof(FILE_BASIC_INFO), GFP_KERNEL); if (pinfo_buf) { - memset(pinfo_buf, 0, sizeof(FILE_BASIC_INFO)); /* ATTRS set to normal clears r/o bit */ pinfo_buf->Attributes = cpu_to_le32(ATTR_NORMAL); if (!(pTcon->ses->flags & CIFS_SES_NT4)) @@ -1167,7 +1166,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) nfid, npid, FALSE); atomic_dec(&open_file->wrtPending); cFYI(1,("SetFSize for attrs rc = %d", rc)); - if(rc == -EINVAL) { + if((rc == -EINVAL) || (rc == -EOPNOTSUPP)) { int bytes_written; rc = CIFSSMBWrite(xid, pTcon, nfid, 0, attrs->ia_size, @@ -1189,7 +1188,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); cFYI(1, ("SetEOF by path (setattrs) rc = %d", rc)); - if(rc == -EINVAL) { + if((rc == -EINVAL) || (rc == -EOPNOTSUPP)) { __u16 netfid; int oplock = FALSE; diff --git a/fs/cifs/link.c b/fs/cifs/link.c index 0f99aae33162..ce86ec69fe01 100644 --- a/fs/cifs/link.c +++ b/fs/cifs/link.c @@ -67,7 +67,7 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode, cifs_sb_target->local_nls, cifs_sb_target->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); - if(rc == -EIO) + if((rc == -EIO) || (rc == -EINVAL)) rc = -EOPNOTSUPP; } diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index 432ba15e2c2d..fafd056426e4 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c @@ -72,10 +72,9 @@ sesInfoAlloc(void) struct cifsSesInfo *ret_buf; ret_buf = - (struct cifsSesInfo *) kmalloc(sizeof (struct cifsSesInfo), + (struct cifsSesInfo *) kzalloc(sizeof (struct cifsSesInfo), GFP_KERNEL); if (ret_buf) { - memset(ret_buf, 0, sizeof (struct cifsSesInfo)); write_lock(&GlobalSMBSeslock); atomic_inc(&sesInfoAllocCount); ret_buf->status = CifsNew; @@ -110,10 +109,9 @@ tconInfoAlloc(void) { struct cifsTconInfo *ret_buf; ret_buf = - (struct cifsTconInfo *) kmalloc(sizeof (struct cifsTconInfo), + (struct cifsTconInfo *) kzalloc(sizeof (struct cifsTconInfo), GFP_KERNEL); if (ret_buf) { - memset(ret_buf, 0, sizeof (struct cifsTconInfo)); write_lock(&GlobalSMBSeslock); atomic_inc(&tconInfoAllocCount); list_add(&ret_buf->cifsConnectionList, @@ -423,9 +421,7 @@ checkSMB(struct smb_hdr *smb, __u16 mid, int length) { __u32 len = smb->smb_buf_length; __u32 clc_len; /* calculated length */ - cFYI(0, - ("Entering checkSMB with Length: %x, smb_buf_length: %x", - length, len)); + cFYI(0, ("checkSMB Length: 0x%x, smb_buf_length: 0x%x", length, len)); if (((unsigned int)length < 2 + sizeof (struct smb_hdr)) || (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4)) { if ((unsigned int)length < 2 + sizeof (struct smb_hdr)) { @@ -433,29 +429,36 @@ checkSMB(struct smb_hdr *smb, __u16 mid, int length) sizeof (struct smb_hdr) - 1) && (smb->Status.CifsError != 0)) { smb->WordCount = 0; - return 0; /* some error cases do not return wct and bcc */ + /* some error cases do not return wct and bcc */ + return 0; } else { cERROR(1, ("Length less than smb header size")); } - } if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) - cERROR(1, - ("smb_buf_length greater than MaxBufSize")); - cERROR(1, - ("bad smb detected. Illegal length. mid=%d", - smb->Mid)); + cERROR(1, ("smb length greater than MaxBufSize, mid=%d", + smb->Mid)); return 1; } if (checkSMBhdr(smb, mid)) return 1; clc_len = smbCalcSize_LE(smb); - if ((4 + len != clc_len) - || (4 + len != (unsigned int)length)) { - cERROR(1, ("Calculated size 0x%x vs actual length 0x%x", - clc_len, 4 + len)); - cERROR(1, ("bad smb size detected for Mid=%d", smb->Mid)); + + if(4 + len != (unsigned int)length) { + cERROR(1, ("Length read does not match RFC1001 length %d",len)); + return 1; + } + + if (4 + len != clc_len) { + /* check if bcc wrapped around for large read responses */ + if((len > 64 * 1024) && (len > clc_len)) { + /* check if lengths match mod 64K */ + if(((4 + len) & 0xFFFF) == (clc_len & 0xFFFF)) + return 0; /* bcc wrapped */ + } + cFYI(1, ("Calculated size %d vs length %d mismatch for mid %d", + clc_len, 4 + len, smb->Mid)); /* Windows XP can return a few bytes too much, presumably an illegal pad, at the end of byte range lock responses so we allow for that three byte pad, as long as actual @@ -469,8 +472,11 @@ checkSMB(struct smb_hdr *smb, __u16 mid, int length) wct and bcc to minimum size and drop the t2 parms and data */ if((4+len > clc_len) && (len <= clc_len + 512)) return 0; - else + else { + cERROR(1, ("RFC1001 size %d bigger than SMB for Mid=%d", + len, smb->Mid)); return 1; + } } return 0; } diff --git a/fs/cifs/ntlmssp.c b/fs/cifs/ntlmssp.c new file mode 100644 index 000000000000..78866f925747 --- /dev/null +++ b/fs/cifs/ntlmssp.c @@ -0,0 +1,129 @@ +/* + * fs/cifs/ntlmssp.h + * + * Copyright (c) International Business Machines Corp., 2006 + * Author(s): Steve French (sfrench@us.ibm.com) + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "cifspdu.h" +#include "cifsglob.h" +#include "cifsproto.h" +#include "cifs_unicode.h" +#include "cifs_debug.h" +#include "ntlmssp.h" +#include "nterr.h" + +#ifdef CONFIG_CIFS_EXPERIMENTAL +static __u32 cifs_ssetup_hdr(struct cifsSesInfo *ses, SESSION_SETUP_ANDX *pSMB) +{ + __u32 capabilities = 0; + + /* init fields common to all four types of SessSetup */ + /* note that header is initialized to zero in header_assemble */ + pSMB->req.AndXCommand = 0xFF; + pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf); + pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq); + + /* Now no need to set SMBFLG_CASELESS or obsolete CANONICAL PATH */ + + /* BB verify whether signing required on neg or just on auth frame + (and NTLM case) */ + + capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS | + CAP_LARGE_WRITE_X | CAP_LARGE_READ_X; + + if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) + pSMB->req.hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE; + + if (ses->capabilities & CAP_UNICODE) { + pSMB->req.hdr.Flags2 |= SMBFLG2_UNICODE; + capabilities |= CAP_UNICODE; + } + if (ses->capabilities & CAP_STATUS32) { + pSMB->req.hdr.Flags2 |= SMBFLG2_ERR_STATUS; + capabilities |= CAP_STATUS32; + } + if (ses->capabilities & CAP_DFS) { + pSMB->req.hdr.Flags2 |= SMBFLG2_DFS; + capabilities |= CAP_DFS; + } + + /* BB check whether to init vcnum BB */ + return capabilities; +} +int +CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, const int type, + int * pNTLMv2_flg, const struct nls_table *nls_cp) +{ + int rc = 0; + int wct; + struct smb_hdr *smb_buffer; + char *bcc_ptr; + SESSION_SETUP_ANDX *pSMB; + __u32 capabilities; + + if(ses == NULL) + return -EINVAL; + + cFYI(1,("SStp type: %d",type)); + if(type < CIFS_NTLM) { +#ifndef CONFIG_CIFS_WEAK_PW_HASH + /* LANMAN and plaintext are less secure and off by default. + So we make this explicitly be turned on in kconfig (in the + build) and turned on at runtime (changed from the default) + in proc/fs/cifs or via mount parm. Unfortunately this is + needed for old Win (e.g. Win95), some obscure NAS and OS/2 */ + return -EOPNOTSUPP; +#endif + wct = 10; /* lanman 2 style sessionsetup */ + } else if(type < CIFS_NTLMSSP_NEG) + wct = 13; /* old style NTLM sessionsetup */ + else /* same size for negotiate or auth, NTLMSSP or extended security */ + wct = 12; + + rc = small_smb_init_no_tc(SMB_COM_SESSION_SETUP_ANDX, wct, ses, + (void **)&smb_buffer); + if(rc) + return rc; + + pSMB = (SESSION_SETUP_ANDX *)smb_buffer; + + capabilities = cifs_ssetup_hdr(ses, pSMB); + bcc_ptr = pByteArea(smb_buffer); + if(type > CIFS_NTLM) { + pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; + capabilities |= CAP_EXTENDED_SECURITY; + pSMB->req.Capabilities = cpu_to_le32(capabilities); + /* BB set password lengths */ + } else if(type < CIFS_NTLM) /* lanman */ { + /* no capabilities flags in old lanman negotiation */ + /* pSMB->old_req.PasswordLength = */ /* BB fixme BB */ + } else /* type CIFS_NTLM */ { + pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities); + pSMB->req_no_secext.CaseInsensitivePasswordLength = + cpu_to_le16(CIFS_SESSION_KEY_SIZE); + pSMB->req_no_secext.CaseSensitivePasswordLength = + cpu_to_le16(CIFS_SESSION_KEY_SIZE); + } + + +/* rc = SendReceive2(xid, ses, iov, num_iovecs, &resp_buf_type, 0); */ + /* SMB request buf freed in SendReceive2 */ + + return rc; +} +#endif /* CONFIG_CIFS_EXPERIMENTAL */ diff --git a/fs/cifs/ntlmssp.h b/fs/cifs/ntlmssp.h index 803389b64a2c..d39b712a11c5 100644 --- a/fs/cifs/ntlmssp.h +++ b/fs/cifs/ntlmssp.h @@ -1,7 +1,7 @@ /* * fs/cifs/ntlmssp.h * - * Copyright (c) International Business Machines Corp., 2002 + * Copyright (c) International Business Machines Corp., 2002,2006 * Author(s): Steve French (sfrench@us.ibm.com) * * This library is free software; you can redistribute it and/or modify diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index 288cc048d37f..405d4b7ec3ac 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c @@ -604,7 +604,12 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon, cifsFile->search_resume_name = NULL; if(cifsFile->srch_inf.ntwrk_buf_start) { cFYI(1,("freeing SMB ff cache buf on search rewind")); - cifs_buf_release(cifsFile->srch_inf.ntwrk_buf_start); + if(cifsFile->srch_inf.smallBuf) + cifs_small_buf_release(cifsFile->srch_inf. + ntwrk_buf_start); + else + cifs_buf_release(cifsFile->srch_inf. + ntwrk_buf_start); } rc = initiate_cifs_search(xid,file); if(rc) { diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index b12cb8a7da7c..3da80409466c 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c @@ -309,17 +309,16 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, *pRespBufType = CIFS_NO_BUFFER; /* no response buf yet */ - if (ses == NULL) { - cERROR(1,("Null smb session")); - return -EIO; - } - if(ses->server == NULL) { - cERROR(1,("Null tcp session")); + if ((ses == NULL) || (ses->server == NULL)) { + cifs_small_buf_release(in_buf); + cERROR(1,("Null session")); return -EIO; } - if(ses->server->tcpStatus == CifsExiting) + if(ses->server->tcpStatus == CifsExiting) { + cifs_small_buf_release(in_buf); return -ENOENT; + } /* Ensure that we do not send more than 50 overlapping requests to the same server. We may make this configurable later or @@ -346,6 +345,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, } else { if(ses->server->tcpStatus == CifsExiting) { spin_unlock(&GlobalMid_Lock); + cifs_small_buf_release(in_buf); return -ENOENT; } @@ -385,6 +385,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, midQ = AllocMidQEntry(in_buf, ses); if (midQ == NULL) { up(&ses->server->tcpSem); + cifs_small_buf_release(in_buf); /* If not lock req, update # of requests on wire to server */ if(long_op < 3) { atomic_dec(&ses->server->inFlight); @@ -408,14 +409,18 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, if(rc < 0) { DeleteMidQEntry(midQ); up(&ses->server->tcpSem); + cifs_small_buf_release(in_buf); /* If not lock req, update # of requests on wire to server */ if(long_op < 3) { atomic_dec(&ses->server->inFlight); wake_up(&ses->server->request_q); } return rc; - } else + } else { up(&ses->server->tcpSem); + cifs_small_buf_release(in_buf); + } + if (long_op == -1) goto cifs_no_response_exit2; else if (long_op == 2) /* writes past end of file can take loong time */ @@ -543,6 +548,7 @@ cifs_no_response_exit2: out_unlock2: up(&ses->server->tcpSem); + cifs_small_buf_release(in_buf); /* If not lock req, update # of requests on wire to server */ if(long_op < 3) { atomic_dec(&ses->server->inFlight); |