Merge master.kernel.org:/pub/scm/linux/kernel/git/sfrench/cifs-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/sfrench/cifs-2.6: [CIFS] Fix typo in earlier cifs_unlink change and protect one [CIFS] Incorrect signature sent on SMB Read [CIFS] Fix unlink oops when indirectly called in rename error path [CIFS] Fix two remaining coverity scan tool warnings. [CIFS] Set correct lock type on new posix unlock call [CIFS] Upate cifs change log [CIFS] Fix slow oplock break response when mounts to different [CIFS] Workaround various server bugs found in testing at connectathon [CIFS] Allow fallback for setting file size to Procom SMB server when [CIFS] Make POSIX CIFS Extensions SetFSInfo match exactly what we want [CIFS] Move noisy debug message (triggerred by some older servers) from [CIFS] Use correct pid on new cifs posix byte range lock call [CIFS] Add posix (advisory) byte range locking support to cifs client [CIFS] CIFS readdir perf optimizations part 1 [CIFS] Free small buffers earlier so we exceed the cifs [CIFS] Fix large (ie over 64K for MaxCIFSBufSize) buffer case for wrapping [CIFS] Convert remaining places in fs/cifs from [CIFS] SessionSetup cleanup part 2 [CIFS] fix compile error (typo) and warning in cifssmb.c [CIFS] Cleanup NTLMSSP session setup handling
This commit is contained in:
Коммит
547a77ae62
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
@ -56,9 +57,6 @@ int cifs_sign_smb(struct smb_hdr * cifs_pdu, struct TCP_Server_Info * server,
|
|||
int rc = 0;
|
||||
char smb_signature[20];
|
||||
|
||||
/* BB remember to initialize sequence number elsewhere and initialize mac_signing key elsewhere BB */
|
||||
/* BB remember to add code to save expected sequence number in midQ entry BB */
|
||||
|
||||
if((cifs_pdu == NULL) || (server == NULL))
|
||||
return -EINVAL;
|
||||
|
||||
|
@ -85,20 +83,33 @@ int cifs_sign_smb(struct smb_hdr * cifs_pdu, struct TCP_Server_Info * server,
|
|||
static int cifs_calc_signature2(const struct kvec * iov, int n_vec,
|
||||
const char * key, char * signature)
|
||||
{
|
||||
struct MD5Context context;
|
||||
struct MD5Context context;
|
||||
int i;
|
||||
|
||||
if((iov == NULL) || (signature == NULL))
|
||||
return -EINVAL;
|
||||
if((iov == NULL) || (signature == NULL))
|
||||
return -EINVAL;
|
||||
|
||||
MD5Init(&context);
|
||||
MD5Update(&context,key,CIFS_SESSION_KEY_SIZE+16);
|
||||
MD5Init(&context);
|
||||
MD5Update(&context,key,CIFS_SESSION_KEY_SIZE+16);
|
||||
for(i=0;i<n_vec;i++) {
|
||||
if(iov[i].iov_base == NULL) {
|
||||
cERROR(1,("null iovec entry"));
|
||||
return -EIO;
|
||||
} else if(iov[i].iov_len == 0)
|
||||
break; /* bail out if we are sent nothing to sign */
|
||||
/* The first entry includes a length field (which does not get
|
||||
signed that occupies the first 4 bytes before the header */
|
||||
if(i==0) {
|
||||
if (iov[0].iov_len <= 8 ) /* cmd field at offset 9 */
|
||||
break; /* nothing to sign or corrupt header */
|
||||
MD5Update(&context,iov[0].iov_base+4, iov[0].iov_len-4);
|
||||
} else
|
||||
MD5Update(&context,iov[i].iov_base, iov[i].iov_len);
|
||||
}
|
||||
|
||||
/* MD5Update(&context,cifs_pdu->Protocol,cifs_pdu->smb_buf_length); */ /* BB FIXME BB */
|
||||
MD5Final(signature,&context);
|
||||
|
||||
MD5Final(signature,&context);
|
||||
|
||||
return -EOPNOTSUPP;
|
||||
/* return 0; */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -259,4 +270,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 */
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
@ -1324,6 +1352,85 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
|
|||
return rc;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -2954,7 +3061,8 @@ findFirstRetry:
|
|||
pSMB->TotalParameterCount = cpu_to_le16(params);
|
||||
pSMB->ParameterCount = pSMB->TotalParameterCount;
|
||||
pSMB->ParameterOffset = cpu_to_le16(
|
||||
offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes) - 4);
|
||||
offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
|
||||
- 4);
|
||||
pSMB->DataCount = 0;
|
||||
pSMB->DataOffset = 0;
|
||||
pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
|
||||
|
@ -2977,12 +3085,12 @@ findFirstRetry:
|
|||
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
|
||||
cifs_stats_inc(&tcon->num_ffirst);
|
||||
|
||||
if (rc) {/* BB add logic to retry regular search if Unix search rejected unexpectedly by server */
|
||||
if (rc) {/* BB add logic to retry regular search if Unix search
|
||||
rejected unexpectedly by server */
|
||||
/* BB Add code to handle unsupported level rc */
|
||||
cFYI(1, ("Error in FindFirst = %d", rc));
|
||||
|
||||
if (pSMB)
|
||||
cifs_buf_release(pSMB);
|
||||
cifs_buf_release(pSMB);
|
||||
|
||||
/* BB eventually could optimize out free and realloc of buf */
|
||||
/* for this case */
|
||||
|
@ -2998,6 +3106,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 +3227,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 +3948,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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -48,13 +48,14 @@ build_path_from_dentry(struct dentry *direntry)
|
|||
struct dentry *temp;
|
||||
int namelen = 0;
|
||||
char *full_path;
|
||||
char dirsep = CIFS_DIR_SEP(CIFS_SB(direntry->d_sb));
|
||||
char dirsep;
|
||||
|
||||
if(direntry == NULL)
|
||||
return NULL; /* not much we can do if dentry is freed and
|
||||
we need to reopen the file after it was closed implicitly
|
||||
when the server crashed */
|
||||
|
||||
dirsep = CIFS_DIR_SEP(CIFS_SB(direntry->d_sb));
|
||||
cifs_bp_rename_retry:
|
||||
for (temp = direntry; !IS_ROOT(temp);) {
|
||||
namelen += (1 + temp->d_name.len);
|
||||
|
@ -255,12 +256,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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -565,11 +565,14 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
|
|||
struct cifsInodeInfo *cifsInode;
|
||||
FILE_BASIC_INFO *pinfo_buf;
|
||||
|
||||
cFYI(1, ("cifs_unlink, inode = 0x%p with ", inode));
|
||||
cFYI(1, ("cifs_unlink, inode = 0x%p", inode));
|
||||
|
||||
xid = GetXid();
|
||||
|
||||
cifs_sb = CIFS_SB(inode->i_sb);
|
||||
if(inode)
|
||||
cifs_sb = CIFS_SB(inode->i_sb);
|
||||
else
|
||||
cifs_sb = CIFS_SB(direntry->d_sb);
|
||||
pTcon = cifs_sb->tcon;
|
||||
|
||||
/* Unlink can be called from rename so we can not grab the sem here
|
||||
|
@ -609,9 +612,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))
|
||||
|
@ -693,9 +695,11 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
|
|||
when needed */
|
||||
direntry->d_inode->i_ctime = current_fs_time(inode->i_sb);
|
||||
}
|
||||
inode->i_ctime = inode->i_mtime = current_fs_time(inode->i_sb);
|
||||
cifsInode = CIFS_I(inode);
|
||||
cifsInode->time = 0; /* force revalidate of dir as well */
|
||||
if(inode) {
|
||||
inode->i_ctime = inode->i_mtime = current_fs_time(inode->i_sb);
|
||||
cifsInode = CIFS_I(inode);
|
||||
cifsInode->time = 0; /* force revalidate of dir as well */
|
||||
}
|
||||
|
||||
kfree(full_path);
|
||||
FreeXid(xid);
|
||||
|
@ -1167,7 +1171,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 +1193,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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
Загрузка…
Ссылка в новой задаче