mirror of https://gitee.com/openkylin/linux.git
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:
commit
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
|
Version 1.40
|
||||||
------------
|
------------
|
||||||
Use fsuid (fsgid) more consistently instead of uid (gid). Improve performance
|
Use fsuid (fsgid) more consistently instead of uid (gid). Improve performance
|
||||||
|
|
|
@ -3,4 +3,4 @@
|
||||||
#
|
#
|
||||||
obj-$(CONFIG_CIFS) += cifs.o
|
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).
|
nomapchars Do not translate any of these seven characters (default).
|
||||||
nocase Request case insensitive path name matching (case
|
nocase Request case insensitive path name matching (case
|
||||||
sensitive is the default if the server suports it).
|
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.
|
nobrl Do not send byte range lock requests to the server.
|
||||||
This is necessary for certain applications that break
|
This is necessary for certain applications that break
|
||||||
with cifs style mandatory byte range locks (and most
|
with cifs style mandatory byte range locks (and most
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* fs/cifs/cifsencrypt.c
|
* 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)
|
* Author(s): Steve French (sfrench@us.ibm.com)
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or modify
|
* 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 mdfour(unsigned char *out, unsigned char *in, int n);
|
||||||
extern void E_md4hash(const unsigned char *passwd, unsigned char *p16);
|
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;
|
struct MD5Context context;
|
||||||
|
|
||||||
|
@ -56,9 +57,6 @@ int cifs_sign_smb(struct smb_hdr * cifs_pdu, struct TCP_Server_Info * server,
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
char smb_signature[20];
|
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))
|
if((cifs_pdu == NULL) || (server == NULL))
|
||||||
return -EINVAL;
|
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,
|
static int cifs_calc_signature2(const struct kvec * iov, int n_vec,
|
||||||
const char * key, char * signature)
|
const char * key, char * signature)
|
||||||
{
|
{
|
||||||
struct MD5Context context;
|
struct MD5Context context;
|
||||||
|
int i;
|
||||||
|
|
||||||
if((iov == NULL) || (signature == NULL))
|
if((iov == NULL) || (signature == NULL))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
MD5Init(&context);
|
MD5Init(&context);
|
||||||
MD5Update(&context,key,CIFS_SESSION_KEY_SIZE+16);
|
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 0;
|
||||||
|
|
||||||
return -EOPNOTSUPP;
|
|
||||||
/* 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_update(v2_session_response+16)client thing,8,&context); */ /* BB fix */
|
||||||
|
|
||||||
hmac_md5_final(v2_session_response,&context);
|
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;
|
int rc = 0;
|
||||||
|
|
||||||
sb->s_flags |= MS_NODIRATIME; /* and probably even noatime */
|
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);
|
cifs_sb = CIFS_SB(sb);
|
||||||
if(cifs_sb == NULL)
|
if(cifs_sb == NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
else
|
|
||||||
memset(cifs_sb,0,sizeof(struct cifs_sb_info));
|
|
||||||
|
|
||||||
|
|
||||||
rc = cifs_mount(sb, cifs_sb, data, devname);
|
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 ssize_t cifs_listxattr(struct dentry *, char *, size_t);
|
||||||
extern int cifs_ioctl (struct inode * inode, struct file * filep,
|
extern int cifs_ioctl (struct inode * inode, struct file * filep,
|
||||||
unsigned int command, unsigned long arg);
|
unsigned int command, unsigned long arg);
|
||||||
#define CIFS_VERSION "1.40"
|
#define CIFS_VERSION "1.42"
|
||||||
#endif /* _CIFSFS_H */
|
#endif /* _CIFSFS_H */
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* fs/cifs/cifsglob.h
|
* 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)
|
* Author(s): Steve French (sfrench@us.ibm.com)
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or modify
|
* 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_LARGE_BUFFER 2
|
||||||
#define CIFS_IOVEC 4 /* array of response buffers */
|
#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
|
* All constants go here
|
||||||
|
|
|
@ -859,7 +859,10 @@ typedef struct smb_com_lock_req {
|
||||||
LOCKING_ANDX_RANGE Locks[1];
|
LOCKING_ANDX_RANGE Locks[1];
|
||||||
} __attribute__((packed)) LOCK_REQ;
|
} __attribute__((packed)) LOCK_REQ;
|
||||||
|
|
||||||
|
/* lock type */
|
||||||
|
#define CIFS_RDLCK 0
|
||||||
|
#define CIFS_WRLCK 1
|
||||||
|
#define CIFS_UNLCK 2
|
||||||
typedef struct cifs_posix_lock {
|
typedef struct cifs_posix_lock {
|
||||||
__le16 lock_type; /* 0 = Read, 1 = Write, 2 = Unlock */
|
__le16 lock_type; /* 0 = Read, 1 = Write, 2 = Unlock */
|
||||||
__le16 lock_flags; /* 1 = Wait (only valid for setlock) */
|
__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_POSIX_ACL_CAP 0x00000002 /* support getfacl/setfacl */
|
||||||
#define CIFS_UNIX_XATTR_CAP 0x00000004 /* support new namespace */
|
#define CIFS_UNIX_XATTR_CAP 0x00000004 /* support new namespace */
|
||||||
#define CIFS_UNIX_EXTATTR_CAP 0x00000008 /* support chattr/chflag */
|
#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 */
|
#define CIFS_POSIX_EXTENSIONS 0x00000010 /* support for new QFSInfo */
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* fs/cifs/cifsproto.h
|
* 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)
|
* Author(s): Steve French (sfrench@us.ibm.com)
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or modify
|
* 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 */ ,
|
extern void header_assemble(struct smb_hdr *, char /* command */ ,
|
||||||
const struct cifsTconInfo *, int /* length of
|
const struct cifsTconInfo *, int /* length of
|
||||||
fixed section (word count) in two byte units */);
|
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 __u16 GetNextMid(struct TCP_Server_Info *server);
|
||||||
extern struct oplock_q_entry * AllocOplockQEntry(struct inode *, u16,
|
extern struct oplock_q_entry * AllocOplockQEntry(struct inode *, u16,
|
||||||
struct cifsTconInfo *);
|
struct cifsTconInfo *);
|
||||||
|
@ -257,7 +265,10 @@ extern int CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
|
||||||
const __u64 offset, const __u32 numUnlock,
|
const __u64 offset, const __u32 numUnlock,
|
||||||
const __u32 numLock, const __u8 lockType,
|
const __u32 numLock, const __u8 lockType,
|
||||||
const int waitFlag);
|
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 CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon);
|
||||||
extern int CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses);
|
extern int CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses);
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* fs/cifs/cifssmb.c
|
* 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)
|
* Author(s): Steve French (sfrench@us.ibm.com)
|
||||||
*
|
*
|
||||||
* Contains the routines for constructing the SMB PDUs themselves
|
* 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);
|
cifs_stats_inc(&tcon->num_smbs_sent);
|
||||||
|
|
||||||
return rc;
|
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 */
|
/* If the return code is zero, this function must fill in request_buf pointer */
|
||||||
static int
|
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(*buf) {
|
||||||
if(resp_buf_type == CIFS_SMALL_BUFFER)
|
if(resp_buf_type == CIFS_SMALL_BUFFER)
|
||||||
cifs_small_buf_release(iov[0].iov_base);
|
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);
|
*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)
|
if(resp_buf_type == CIFS_SMALL_BUFFER)
|
||||||
cifs_small_buf_release(iov[0].iov_base);
|
cifs_small_buf_release(iov[0].iov_base);
|
||||||
else if(resp_buf_type == CIFS_LARGE_BUFFER)
|
else if(resp_buf_type == CIFS_LARGE_BUFFER)
|
||||||
|
@ -1324,6 +1352,85 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
|
||||||
return rc;
|
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
|
int
|
||||||
CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
|
CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
|
||||||
{
|
{
|
||||||
|
@ -2578,7 +2685,7 @@ CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
|
||||||
cifs_small_buf_release(iov[0].iov_base);
|
cifs_small_buf_release(iov[0].iov_base);
|
||||||
else if(buf_type == CIFS_LARGE_BUFFER)
|
else if(buf_type == CIFS_LARGE_BUFFER)
|
||||||
cifs_buf_release(iov[0].iov_base);
|
cifs_buf_release(iov[0].iov_base);
|
||||||
cifs_small_buf_release(pSMB);
|
/* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2954,7 +3061,8 @@ CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
|
||||||
pSMB->TotalParameterCount = cpu_to_le16(params);
|
pSMB->TotalParameterCount = cpu_to_le16(params);
|
||||||
pSMB->ParameterCount = pSMB->TotalParameterCount;
|
pSMB->ParameterCount = pSMB->TotalParameterCount;
|
||||||
pSMB->ParameterOffset = cpu_to_le16(
|
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->DataCount = 0;
|
||||||
pSMB->DataOffset = 0;
|
pSMB->DataOffset = 0;
|
||||||
pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
|
pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
|
||||||
|
@ -2977,12 +3085,12 @@ CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
|
||||||
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
|
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
|
||||||
cifs_stats_inc(&tcon->num_ffirst);
|
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 */
|
/* BB Add code to handle unsupported level rc */
|
||||||
cFYI(1, ("Error in FindFirst = %d", 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 */
|
/* BB eventually could optimize out free and realloc of buf */
|
||||||
/* for this case */
|
/* for this case */
|
||||||
|
@ -2998,6 +3106,7 @@ CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
|
||||||
psrch_inf->unicode = FALSE;
|
psrch_inf->unicode = FALSE;
|
||||||
|
|
||||||
psrch_inf->ntwrk_buf_start = (char *)pSMBr;
|
psrch_inf->ntwrk_buf_start = (char *)pSMBr;
|
||||||
|
psrch_inf->smallBuf = 0;
|
||||||
psrch_inf->srch_entries_start =
|
psrch_inf->srch_entries_start =
|
||||||
(char *) &pSMBr->hdr.Protocol +
|
(char *) &pSMBr->hdr.Protocol +
|
||||||
le16_to_cpu(pSMBr->t2.DataOffset);
|
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;
|
parms = (T2_FNEXT_RSP_PARMS *)response_data;
|
||||||
response_data = (char *)&pSMBr->hdr.Protocol +
|
response_data = (char *)&pSMBr->hdr.Protocol +
|
||||||
le16_to_cpu(pSMBr->t2.DataOffset);
|
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->srch_entries_start = response_data;
|
||||||
psrch_inf->ntwrk_buf_start = (char *)pSMB;
|
psrch_inf->ntwrk_buf_start = (char *)pSMB;
|
||||||
|
psrch_inf->smallBuf = 0;
|
||||||
if(parms->EndofSearch)
|
if(parms->EndofSearch)
|
||||||
psrch_inf->endOfSearch = TRUE;
|
psrch_inf->endOfSearch = TRUE;
|
||||||
else
|
else
|
||||||
|
@ -3834,6 +3948,7 @@ CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
|
||||||
|
|
||||||
cFYI(1, ("In SETFSUnixInfo"));
|
cFYI(1, ("In SETFSUnixInfo"));
|
||||||
SETFSUnixRetry:
|
SETFSUnixRetry:
|
||||||
|
/* BB switch to small buf init to save memory */
|
||||||
rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
|
rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
|
||||||
(void **) &pSMBr);
|
(void **) &pSMBr);
|
||||||
if (rc)
|
if (rc)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* fs/cifs/connect.c
|
* 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)
|
* Author(s): Steve French (sfrench@us.ibm.com)
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or modify
|
* 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);
|
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);
|
cifs_dump_mem("Bad SMB: ", smb_buffer, 48);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -1476,6 +1476,14 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
|
||||||
rc = smb_send(*csocket, smb_buf, 0x44,
|
rc = smb_send(*csocket, smb_buf, 0x44,
|
||||||
(struct sockaddr *)psin_server);
|
(struct sockaddr *)psin_server);
|
||||||
kfree(ses_init_buf);
|
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
|
/* else the negprot may still work without this
|
||||||
even though malloc failed */
|
even though malloc failed */
|
||||||
|
@ -1920,27 +1928,34 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
|
||||||
cifs_sb->tcon = tcon;
|
cifs_sb->tcon = tcon;
|
||||||
tcon->ses = pSesInfo;
|
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);
|
CIFSSMBQFSDeviceInfo(xid, tcon);
|
||||||
CIFSSMBQFSAttributeInfo(xid, tcon);
|
CIFSSMBQFSAttributeInfo(xid, tcon);
|
||||||
|
|
||||||
if (tcon->ses->capabilities & CAP_UNIX) {
|
if (tcon->ses->capabilities & CAP_UNIX) {
|
||||||
if(!CIFSSMBQFSUnixInfo(xid, tcon)) {
|
if(!CIFSSMBQFSUnixInfo(xid, tcon)) {
|
||||||
if(!volume_info.no_psx_acl) {
|
__u64 cap =
|
||||||
if(CIFS_UNIX_POSIX_ACL_CAP &
|
le64_to_cpu(tcon->fsUnixInfo.Capability);
|
||||||
le64_to_cpu(tcon->fsUnixInfo.Capability))
|
cap &= CIFS_UNIX_CAP_MASK;
|
||||||
cFYI(1,("server negotiated posix acl support"));
|
if(volume_info.no_psx_acl)
|
||||||
sb->s_flags |= MS_POSIXACL;
|
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 == 0)
|
||||||
if (volume_info.posix_paths && (CIFS_UNIX_POSIX_PATHNAMES_CAP &
|
cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
|
||||||
le64_to_cpu(tcon->fsUnixInfo.Capability))) {
|
else if(cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
|
||||||
if (!CIFSSMBSetFSUnixInfo(xid, tcon, CIFS_UNIX_POSIX_PATHNAMES_CAP)) {
|
cFYI(1,("negotiate posix pathnames"));
|
||||||
cFYI(1,("negotiated posix pathnames support"));
|
cifs_sb->mnt_cifs_flags |=
|
||||||
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS;
|
CIFS_MOUNT_POSIX_PATHS;
|
||||||
} else {
|
}
|
||||||
cFYI(1,("posix pathnames support requested but not supported"));
|
|
||||||
}
|
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);
|
smb_buffer->Mid = GetNextMid(ses->server);
|
||||||
pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
|
pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
|
||||||
pSMB->req.AndXCommand = 0xFF;
|
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.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
|
||||||
pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
|
pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
|
||||||
|
|
||||||
|
@ -2525,7 +2542,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
|
||||||
__u32 negotiate_flags, capabilities;
|
__u32 negotiate_flags, capabilities;
|
||||||
__u16 count;
|
__u16 count;
|
||||||
|
|
||||||
cFYI(1, ("In NTLMSSP sesssetup (negotiate) "));
|
cFYI(1, ("In NTLMSSP sesssetup (negotiate)"));
|
||||||
if(ses == NULL)
|
if(ses == NULL)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
domain = ses->domainName;
|
domain = ses->domainName;
|
||||||
|
@ -2575,7 +2592,8 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
|
||||||
SecurityBlob->MessageType = NtLmNegotiate;
|
SecurityBlob->MessageType = NtLmNegotiate;
|
||||||
negotiate_flags =
|
negotiate_flags =
|
||||||
NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM |
|
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;
|
/* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128;
|
||||||
if(sign_CIFS_PDUs)
|
if(sign_CIFS_PDUs)
|
||||||
negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN;
|
negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN;
|
||||||
|
@ -2588,26 +2606,11 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
|
||||||
SecurityBlob->WorkstationName.Length = 0;
|
SecurityBlob->WorkstationName.Length = 0;
|
||||||
SecurityBlob->WorkstationName.MaximumLength = 0;
|
SecurityBlob->WorkstationName.MaximumLength = 0;
|
||||||
|
|
||||||
if (domain == NULL) {
|
/* Domain not sent on first Sesssetup in NTLMSSP, instead it is sent
|
||||||
SecurityBlob->DomainName.Buffer = 0;
|
along with username on auth request (ie the response to challenge) */
|
||||||
SecurityBlob->DomainName.Length = 0;
|
SecurityBlob->DomainName.Buffer = 0;
|
||||||
SecurityBlob->DomainName.MaximumLength = 0;
|
SecurityBlob->DomainName.Length = 0;
|
||||||
} else {
|
SecurityBlob->DomainName.MaximumLength = 0;
|
||||||
__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);
|
|
||||||
}
|
|
||||||
if (ses->capabilities & CAP_UNICODE) {
|
if (ses->capabilities & CAP_UNICODE) {
|
||||||
if ((long) bcc_ptr % 2) {
|
if ((long) bcc_ptr % 2) {
|
||||||
*bcc_ptr = 0;
|
*bcc_ptr = 0;
|
||||||
|
@ -2677,7 +2680,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
|
||||||
SecurityBlob2->MessageType));
|
SecurityBlob2->MessageType));
|
||||||
} else if (ses) {
|
} else if (ses) {
|
||||||
ses->Suid = smb_buffer_response->Uid; /* UID left in le format */
|
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)
|
if ((pSMBr->resp.hdr.WordCount == 3)
|
||||||
|| ((pSMBr->resp.hdr.WordCount == 4)
|
|| ((pSMBr->resp.hdr.WordCount == 4)
|
||||||
&& (blob_len <
|
&& (blob_len <
|
||||||
|
@ -2685,17 +2688,17 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
|
||||||
|
|
||||||
if (pSMBr->resp.hdr.WordCount == 4) {
|
if (pSMBr->resp.hdr.WordCount == 4) {
|
||||||
bcc_ptr += blob_len;
|
bcc_ptr += blob_len;
|
||||||
cFYI(1,
|
cFYI(1, ("Security Blob Length %d",
|
||||||
("Security Blob Length %d ",
|
|
||||||
blob_len));
|
blob_len));
|
||||||
}
|
}
|
||||||
|
|
||||||
cFYI(1, ("NTLMSSP Challenge rcvd "));
|
cFYI(1, ("NTLMSSP Challenge rcvd"));
|
||||||
|
|
||||||
memcpy(ses->server->cryptKey,
|
memcpy(ses->server->cryptKey,
|
||||||
SecurityBlob2->Challenge,
|
SecurityBlob2->Challenge,
|
||||||
CIFS_CRYPTO_KEY_SIZE);
|
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;
|
*pNTLMv2_flag = TRUE;
|
||||||
|
|
||||||
if((SecurityBlob2->NegotiateFlags &
|
if((SecurityBlob2->NegotiateFlags &
|
||||||
|
@ -2818,7 +2821,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
|
||||||
bcc_ptr++;
|
bcc_ptr++;
|
||||||
} else
|
} else
|
||||||
cFYI(1,
|
cFYI(1,
|
||||||
("Variable field of length %d extends beyond end of smb ",
|
("Variable field of length %d extends beyond end of smb",
|
||||||
len));
|
len));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -2830,7 +2833,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
cERROR(1,
|
cERROR(1,
|
||||||
(" Invalid Word count %d: ",
|
(" Invalid Word count %d:",
|
||||||
smb_buffer_response->WordCount));
|
smb_buffer_response->WordCount));
|
||||||
rc = -EIO;
|
rc = -EIO;
|
||||||
}
|
}
|
||||||
|
@ -3447,7 +3450,7 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
|
||||||
if (extended_security
|
if (extended_security
|
||||||
&& (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
|
&& (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
|
||||||
&& (pSesInfo->server->secType == NTLMSSP)) {
|
&& (pSesInfo->server->secType == NTLMSSP)) {
|
||||||
cFYI(1, ("New style sesssetup "));
|
cFYI(1, ("New style sesssetup"));
|
||||||
rc = CIFSSpnegoSessSetup(xid, pSesInfo,
|
rc = CIFSSpnegoSessSetup(xid, pSesInfo,
|
||||||
NULL /* security blob */,
|
NULL /* security blob */,
|
||||||
0 /* blob length */,
|
0 /* blob length */,
|
||||||
|
@ -3455,7 +3458,7 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
|
||||||
} else if (extended_security
|
} else if (extended_security
|
||||||
&& (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
|
&& (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
|
||||||
&& (pSesInfo->server->secType == RawNTLMSSP)) {
|
&& (pSesInfo->server->secType == RawNTLMSSP)) {
|
||||||
cFYI(1, ("NTLMSSP sesssetup "));
|
cFYI(1, ("NTLMSSP sesssetup"));
|
||||||
rc = CIFSNTLMSSPNegotiateSessSetup(xid,
|
rc = CIFSNTLMSSPNegotiateSessSetup(xid,
|
||||||
pSesInfo,
|
pSesInfo,
|
||||||
&ntlmv2_flag,
|
&ntlmv2_flag,
|
||||||
|
|
|
@ -48,13 +48,14 @@ build_path_from_dentry(struct dentry *direntry)
|
||||||
struct dentry *temp;
|
struct dentry *temp;
|
||||||
int namelen = 0;
|
int namelen = 0;
|
||||||
char *full_path;
|
char *full_path;
|
||||||
char dirsep = CIFS_DIR_SEP(CIFS_SB(direntry->d_sb));
|
char dirsep;
|
||||||
|
|
||||||
if(direntry == NULL)
|
if(direntry == NULL)
|
||||||
return NULL; /* not much we can do if dentry is freed and
|
return NULL; /* not much we can do if dentry is freed and
|
||||||
we need to reopen the file after it was closed implicitly
|
we need to reopen the file after it was closed implicitly
|
||||||
when the server crashed */
|
when the server crashed */
|
||||||
|
|
||||||
|
dirsep = CIFS_DIR_SEP(CIFS_SB(direntry->d_sb));
|
||||||
cifs_bp_rename_retry:
|
cifs_bp_rename_retry:
|
||||||
for (temp = direntry; !IS_ROOT(temp);) {
|
for (temp = direntry; !IS_ROOT(temp);) {
|
||||||
namelen += (1 + temp->d_name.len);
|
namelen += (1 + temp->d_name.len);
|
||||||
|
@ -255,12 +256,10 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
|
||||||
CIFSSMBClose(xid, pTcon, fileHandle);
|
CIFSSMBClose(xid, pTcon, fileHandle);
|
||||||
} else if(newinode) {
|
} else if(newinode) {
|
||||||
pCifsFile =
|
pCifsFile =
|
||||||
kmalloc(sizeof (struct cifsFileInfo), GFP_KERNEL);
|
kzalloc(sizeof (struct cifsFileInfo), GFP_KERNEL);
|
||||||
|
|
||||||
if(pCifsFile == NULL)
|
if(pCifsFile == NULL)
|
||||||
goto cifs_create_out;
|
goto cifs_create_out;
|
||||||
memset((char *)pCifsFile, 0,
|
|
||||||
sizeof (struct cifsFileInfo));
|
|
||||||
pCifsFile->netfid = fileHandle;
|
pCifsFile->netfid = fileHandle;
|
||||||
pCifsFile->pid = current->tgid;
|
pCifsFile->pid = current->tgid;
|
||||||
pCifsFile->pInode = newinode;
|
pCifsFile->pInode = newinode;
|
||||||
|
|
|
@ -555,7 +555,10 @@ int cifs_closedir(struct inode *inode, struct file *file)
|
||||||
if (ptmp) {
|
if (ptmp) {
|
||||||
cFYI(1, ("closedir free smb buf in srch struct"));
|
cFYI(1, ("closedir free smb buf in srch struct"));
|
||||||
pCFileStruct->srch_inf.ntwrk_buf_start = NULL;
|
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;
|
ptmp = pCFileStruct->search_resume_name;
|
||||||
if (ptmp) {
|
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 cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
|
||||||
{
|
{
|
||||||
int rc, xid;
|
int rc, xid;
|
||||||
__u32 lockType = LOCKING_ANDX_LARGE_FILES;
|
|
||||||
__u32 numLock = 0;
|
__u32 numLock = 0;
|
||||||
__u32 numUnlock = 0;
|
__u32 numUnlock = 0;
|
||||||
__u64 length;
|
__u64 length;
|
||||||
int wait_flag = FALSE;
|
int wait_flag = FALSE;
|
||||||
struct cifs_sb_info *cifs_sb;
|
struct cifs_sb_info *cifs_sb;
|
||||||
struct cifsTconInfo *pTcon;
|
struct cifsTconInfo *pTcon;
|
||||||
|
__u16 netfid;
|
||||||
|
__u8 lockType = LOCKING_ANDX_LARGE_FILES;
|
||||||
|
|
||||||
length = 1 + pfLock->fl_end - pfLock->fl_start;
|
length = 1 + pfLock->fl_end - pfLock->fl_start;
|
||||||
rc = -EACCES;
|
rc = -EACCES;
|
||||||
|
@ -592,11 +596,11 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
|
||||||
pfLock->fl_end));
|
pfLock->fl_end));
|
||||||
|
|
||||||
if (pfLock->fl_flags & FL_POSIX)
|
if (pfLock->fl_flags & FL_POSIX)
|
||||||
cFYI(1, ("Posix "));
|
cFYI(1, ("Posix"));
|
||||||
if (pfLock->fl_flags & FL_FLOCK)
|
if (pfLock->fl_flags & FL_FLOCK)
|
||||||
cFYI(1, ("Flock "));
|
cFYI(1, ("Flock"));
|
||||||
if (pfLock->fl_flags & FL_SLEEP) {
|
if (pfLock->fl_flags & FL_SLEEP) {
|
||||||
cFYI(1, ("Blocking lock "));
|
cFYI(1, ("Blocking lock"));
|
||||||
wait_flag = TRUE;
|
wait_flag = TRUE;
|
||||||
}
|
}
|
||||||
if (pfLock->fl_flags & FL_ACCESS)
|
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 "));
|
cFYI(1, ("F_WRLCK "));
|
||||||
numLock = 1;
|
numLock = 1;
|
||||||
} else if (pfLock->fl_type == F_UNLCK) {
|
} else if (pfLock->fl_type == F_UNLCK) {
|
||||||
cFYI(1, ("F_UNLCK "));
|
cFYI(1, ("F_UNLCK"));
|
||||||
numUnlock = 1;
|
numUnlock = 1;
|
||||||
|
/* Check if unlock includes more than
|
||||||
|
one lock range */
|
||||||
} else if (pfLock->fl_type == F_RDLCK) {
|
} else if (pfLock->fl_type == F_RDLCK) {
|
||||||
cFYI(1, ("F_RDLCK "));
|
cFYI(1, ("F_RDLCK"));
|
||||||
lockType |= LOCKING_ANDX_SHARED_LOCK;
|
lockType |= LOCKING_ANDX_SHARED_LOCK;
|
||||||
numLock = 1;
|
numLock = 1;
|
||||||
} else if (pfLock->fl_type == F_EXLCK) {
|
} else if (pfLock->fl_type == F_EXLCK) {
|
||||||
cFYI(1, ("F_EXLCK "));
|
cFYI(1, ("F_EXLCK"));
|
||||||
numLock = 1;
|
numLock = 1;
|
||||||
} else if (pfLock->fl_type == F_SHLCK) {
|
} else if (pfLock->fl_type == F_SHLCK) {
|
||||||
cFYI(1, ("F_SHLCK "));
|
cFYI(1, ("F_SHLCK"));
|
||||||
lockType |= LOCKING_ANDX_SHARED_LOCK;
|
lockType |= LOCKING_ANDX_SHARED_LOCK;
|
||||||
numLock = 1;
|
numLock = 1;
|
||||||
} else
|
} else
|
||||||
cFYI(1, ("Unknown type of lock "));
|
cFYI(1, ("Unknown type of lock"));
|
||||||
|
|
||||||
cifs_sb = CIFS_SB(file->f_dentry->d_sb);
|
cifs_sb = CIFS_SB(file->f_dentry->d_sb);
|
||||||
pTcon = cifs_sb->tcon;
|
pTcon = cifs_sb->tcon;
|
||||||
|
@ -635,27 +641,41 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
|
||||||
FreeXid(xid);
|
FreeXid(xid);
|
||||||
return -EBADF;
|
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)) {
|
if (IS_GETLK(cmd)) {
|
||||||
rc = CIFSSMBLock(xid, pTcon,
|
if(experimEnabled &&
|
||||||
((struct cifsFileInfo *)file->
|
(cifs_sb->tcon->ses->capabilities & CAP_UNIX) &&
|
||||||
private_data)->netfid,
|
(CIFS_UNIX_FCNTL_CAP &
|
||||||
length,
|
le64_to_cpu(cifs_sb->tcon->fsUnixInfo.Capability))) {
|
||||||
pfLock->fl_start, 0, 1, lockType,
|
int posix_lock_type;
|
||||||
0 /* wait flag */ );
|
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) {
|
if (rc == 0) {
|
||||||
rc = CIFSSMBLock(xid, pTcon,
|
rc = CIFSSMBLock(xid, pTcon, netfid, length,
|
||||||
((struct cifsFileInfo *) file->
|
|
||||||
private_data)->netfid,
|
|
||||||
length,
|
|
||||||
pfLock->fl_start, 1 /* numUnlock */ ,
|
pfLock->fl_start, 1 /* numUnlock */ ,
|
||||||
0 /* numLock */ , lockType,
|
0 /* numLock */ , lockType,
|
||||||
0 /* wait flag */ );
|
0 /* wait flag */ );
|
||||||
pfLock->fl_type = F_UNLCK;
|
pfLock->fl_type = F_UNLCK;
|
||||||
if (rc != 0)
|
if (rc != 0)
|
||||||
cERROR(1, ("Error unlocking previously locked "
|
cERROR(1, ("Error unlocking previously locked "
|
||||||
"range %d during test of lock ",
|
"range %d during test of lock", rc));
|
||||||
rc));
|
|
||||||
rc = 0;
|
rc = 0;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -667,12 +687,30 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
|
||||||
FreeXid(xid);
|
FreeXid(xid);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
if (experimEnabled &&
|
||||||
rc = CIFSSMBLock(xid, pTcon,
|
(cifs_sb->tcon->ses->capabilities & CAP_UNIX) &&
|
||||||
((struct cifsFileInfo *) file->private_data)->
|
(CIFS_UNIX_FCNTL_CAP &
|
||||||
netfid, length,
|
le64_to_cpu(cifs_sb->tcon->fsUnixInfo.Capability))) {
|
||||||
pfLock->fl_start, numUnlock, numLock, lockType,
|
int posix_lock_type;
|
||||||
wait_flag);
|
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)
|
if (pfLock->fl_flags & FL_POSIX)
|
||||||
posix_lock_file_wait(file, pfLock);
|
posix_lock_file_wait(file, pfLock);
|
||||||
FreeXid(xid);
|
FreeXid(xid);
|
||||||
|
|
|
@ -565,11 +565,14 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
|
||||||
struct cifsInodeInfo *cifsInode;
|
struct cifsInodeInfo *cifsInode;
|
||||||
FILE_BASIC_INFO *pinfo_buf;
|
FILE_BASIC_INFO *pinfo_buf;
|
||||||
|
|
||||||
cFYI(1, ("cifs_unlink, inode = 0x%p with ", inode));
|
cFYI(1, ("cifs_unlink, inode = 0x%p", inode));
|
||||||
|
|
||||||
xid = GetXid();
|
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;
|
pTcon = cifs_sb->tcon;
|
||||||
|
|
||||||
/* Unlink can be called from rename so we can not grab the sem here
|
/* 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) {
|
} else if (rc == -EACCES) {
|
||||||
/* try only if r/o attribute set in local lookup data? */
|
/* 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) {
|
if (pinfo_buf) {
|
||||||
memset(pinfo_buf, 0, sizeof(FILE_BASIC_INFO));
|
|
||||||
/* ATTRS set to normal clears r/o bit */
|
/* ATTRS set to normal clears r/o bit */
|
||||||
pinfo_buf->Attributes = cpu_to_le32(ATTR_NORMAL);
|
pinfo_buf->Attributes = cpu_to_le32(ATTR_NORMAL);
|
||||||
if (!(pTcon->ses->flags & CIFS_SES_NT4))
|
if (!(pTcon->ses->flags & CIFS_SES_NT4))
|
||||||
|
@ -693,9 +695,11 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
|
||||||
when needed */
|
when needed */
|
||||||
direntry->d_inode->i_ctime = current_fs_time(inode->i_sb);
|
direntry->d_inode->i_ctime = current_fs_time(inode->i_sb);
|
||||||
}
|
}
|
||||||
inode->i_ctime = inode->i_mtime = current_fs_time(inode->i_sb);
|
if(inode) {
|
||||||
cifsInode = CIFS_I(inode);
|
inode->i_ctime = inode->i_mtime = current_fs_time(inode->i_sb);
|
||||||
cifsInode->time = 0; /* force revalidate of dir as well */
|
cifsInode = CIFS_I(inode);
|
||||||
|
cifsInode->time = 0; /* force revalidate of dir as well */
|
||||||
|
}
|
||||||
|
|
||||||
kfree(full_path);
|
kfree(full_path);
|
||||||
FreeXid(xid);
|
FreeXid(xid);
|
||||||
|
@ -1167,7 +1171,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
|
||||||
nfid, npid, FALSE);
|
nfid, npid, FALSE);
|
||||||
atomic_dec(&open_file->wrtPending);
|
atomic_dec(&open_file->wrtPending);
|
||||||
cFYI(1,("SetFSize for attrs rc = %d", rc));
|
cFYI(1,("SetFSize for attrs rc = %d", rc));
|
||||||
if(rc == -EINVAL) {
|
if((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
|
||||||
int bytes_written;
|
int bytes_written;
|
||||||
rc = CIFSSMBWrite(xid, pTcon,
|
rc = CIFSSMBWrite(xid, pTcon,
|
||||||
nfid, 0, attrs->ia_size,
|
nfid, 0, attrs->ia_size,
|
||||||
|
@ -1189,7 +1193,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
|
||||||
cifs_sb->mnt_cifs_flags &
|
cifs_sb->mnt_cifs_flags &
|
||||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
cFYI(1, ("SetEOF by path (setattrs) rc = %d", rc));
|
cFYI(1, ("SetEOF by path (setattrs) rc = %d", rc));
|
||||||
if(rc == -EINVAL) {
|
if((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
|
||||||
__u16 netfid;
|
__u16 netfid;
|
||||||
int oplock = FALSE;
|
int oplock = FALSE;
|
||||||
|
|
||||||
|
|
|
@ -67,7 +67,7 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,
|
||||||
cifs_sb_target->local_nls,
|
cifs_sb_target->local_nls,
|
||||||
cifs_sb_target->mnt_cifs_flags &
|
cifs_sb_target->mnt_cifs_flags &
|
||||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
if(rc == -EIO)
|
if((rc == -EIO) || (rc == -EINVAL))
|
||||||
rc = -EOPNOTSUPP;
|
rc = -EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -72,10 +72,9 @@ sesInfoAlloc(void)
|
||||||
struct cifsSesInfo *ret_buf;
|
struct cifsSesInfo *ret_buf;
|
||||||
|
|
||||||
ret_buf =
|
ret_buf =
|
||||||
(struct cifsSesInfo *) kmalloc(sizeof (struct cifsSesInfo),
|
(struct cifsSesInfo *) kzalloc(sizeof (struct cifsSesInfo),
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
if (ret_buf) {
|
if (ret_buf) {
|
||||||
memset(ret_buf, 0, sizeof (struct cifsSesInfo));
|
|
||||||
write_lock(&GlobalSMBSeslock);
|
write_lock(&GlobalSMBSeslock);
|
||||||
atomic_inc(&sesInfoAllocCount);
|
atomic_inc(&sesInfoAllocCount);
|
||||||
ret_buf->status = CifsNew;
|
ret_buf->status = CifsNew;
|
||||||
|
@ -110,10 +109,9 @@ tconInfoAlloc(void)
|
||||||
{
|
{
|
||||||
struct cifsTconInfo *ret_buf;
|
struct cifsTconInfo *ret_buf;
|
||||||
ret_buf =
|
ret_buf =
|
||||||
(struct cifsTconInfo *) kmalloc(sizeof (struct cifsTconInfo),
|
(struct cifsTconInfo *) kzalloc(sizeof (struct cifsTconInfo),
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
if (ret_buf) {
|
if (ret_buf) {
|
||||||
memset(ret_buf, 0, sizeof (struct cifsTconInfo));
|
|
||||||
write_lock(&GlobalSMBSeslock);
|
write_lock(&GlobalSMBSeslock);
|
||||||
atomic_inc(&tconInfoAllocCount);
|
atomic_inc(&tconInfoAllocCount);
|
||||||
list_add(&ret_buf->cifsConnectionList,
|
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 len = smb->smb_buf_length;
|
||||||
__u32 clc_len; /* calculated length */
|
__u32 clc_len; /* calculated length */
|
||||||
cFYI(0,
|
cFYI(0, ("checkSMB Length: 0x%x, smb_buf_length: 0x%x", length, len));
|
||||||
("Entering checkSMB with Length: %x, smb_buf_length: %x",
|
|
||||||
length, len));
|
|
||||||
if (((unsigned int)length < 2 + sizeof (struct smb_hdr)) ||
|
if (((unsigned int)length < 2 + sizeof (struct smb_hdr)) ||
|
||||||
(len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4)) {
|
(len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4)) {
|
||||||
if ((unsigned int)length < 2 + sizeof (struct smb_hdr)) {
|
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)
|
sizeof (struct smb_hdr) - 1)
|
||||||
&& (smb->Status.CifsError != 0)) {
|
&& (smb->Status.CifsError != 0)) {
|
||||||
smb->WordCount = 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 {
|
} else {
|
||||||
cERROR(1, ("Length less than smb header size"));
|
cERROR(1, ("Length less than smb header size"));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4)
|
if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4)
|
||||||
cERROR(1,
|
cERROR(1, ("smb length greater than MaxBufSize, mid=%d",
|
||||||
("smb_buf_length greater than MaxBufSize"));
|
smb->Mid));
|
||||||
cERROR(1,
|
|
||||||
("bad smb detected. Illegal length. mid=%d",
|
|
||||||
smb->Mid));
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (checkSMBhdr(smb, mid))
|
if (checkSMBhdr(smb, mid))
|
||||||
return 1;
|
return 1;
|
||||||
clc_len = smbCalcSize_LE(smb);
|
clc_len = smbCalcSize_LE(smb);
|
||||||
if ((4 + len != clc_len)
|
|
||||||
|| (4 + len != (unsigned int)length)) {
|
if(4 + len != (unsigned int)length) {
|
||||||
cERROR(1, ("Calculated size 0x%x vs actual length 0x%x",
|
cERROR(1, ("Length read does not match RFC1001 length %d",len));
|
||||||
clc_len, 4 + len));
|
return 1;
|
||||||
cERROR(1, ("bad smb size detected for Mid=%d", smb->Mid));
|
}
|
||||||
|
|
||||||
|
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
|
/* Windows XP can return a few bytes too much, presumably
|
||||||
an illegal pad, at the end of byte range lock responses
|
an illegal pad, at the end of byte range lock responses
|
||||||
so we allow for that three byte pad, as long as actual
|
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 */
|
wct and bcc to minimum size and drop the t2 parms and data */
|
||||||
if((4+len > clc_len) && (len <= clc_len + 512))
|
if((4+len > clc_len) && (len <= clc_len + 512))
|
||||||
return 0;
|
return 0;
|
||||||
else
|
else {
|
||||||
|
cERROR(1, ("RFC1001 size %d bigger than SMB for Mid=%d",
|
||||||
|
len, smb->Mid));
|
||||||
return 1;
|
return 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
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
|
* 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)
|
* Author(s): Steve French (sfrench@us.ibm.com)
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or modify
|
* 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;
|
cifsFile->search_resume_name = NULL;
|
||||||
if(cifsFile->srch_inf.ntwrk_buf_start) {
|
if(cifsFile->srch_inf.ntwrk_buf_start) {
|
||||||
cFYI(1,("freeing SMB ff cache buf on search rewind"));
|
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);
|
rc = initiate_cifs_search(xid,file);
|
||||||
if(rc) {
|
if(rc) {
|
||||||
|
|
|
@ -309,17 +309,16 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
|
||||||
|
|
||||||
*pRespBufType = CIFS_NO_BUFFER; /* no response buf yet */
|
*pRespBufType = CIFS_NO_BUFFER; /* no response buf yet */
|
||||||
|
|
||||||
if (ses == NULL) {
|
if ((ses == NULL) || (ses->server == NULL)) {
|
||||||
cERROR(1,("Null smb session"));
|
cifs_small_buf_release(in_buf);
|
||||||
return -EIO;
|
cERROR(1,("Null session"));
|
||||||
}
|
|
||||||
if(ses->server == NULL) {
|
|
||||||
cERROR(1,("Null tcp session"));
|
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ses->server->tcpStatus == CifsExiting)
|
if(ses->server->tcpStatus == CifsExiting) {
|
||||||
|
cifs_small_buf_release(in_buf);
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
/* Ensure that we do not send more than 50 overlapping requests
|
/* Ensure that we do not send more than 50 overlapping requests
|
||||||
to the same server. We may make this configurable later or
|
to the same server. We may make this configurable later or
|
||||||
|
@ -346,6 +345,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
|
||||||
} else {
|
} else {
|
||||||
if(ses->server->tcpStatus == CifsExiting) {
|
if(ses->server->tcpStatus == CifsExiting) {
|
||||||
spin_unlock(&GlobalMid_Lock);
|
spin_unlock(&GlobalMid_Lock);
|
||||||
|
cifs_small_buf_release(in_buf);
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -385,6 +385,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
|
||||||
midQ = AllocMidQEntry(in_buf, ses);
|
midQ = AllocMidQEntry(in_buf, ses);
|
||||||
if (midQ == NULL) {
|
if (midQ == NULL) {
|
||||||
up(&ses->server->tcpSem);
|
up(&ses->server->tcpSem);
|
||||||
|
cifs_small_buf_release(in_buf);
|
||||||
/* If not lock req, update # of requests on wire to server */
|
/* If not lock req, update # of requests on wire to server */
|
||||||
if(long_op < 3) {
|
if(long_op < 3) {
|
||||||
atomic_dec(&ses->server->inFlight);
|
atomic_dec(&ses->server->inFlight);
|
||||||
|
@ -408,14 +409,18 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
|
||||||
if(rc < 0) {
|
if(rc < 0) {
|
||||||
DeleteMidQEntry(midQ);
|
DeleteMidQEntry(midQ);
|
||||||
up(&ses->server->tcpSem);
|
up(&ses->server->tcpSem);
|
||||||
|
cifs_small_buf_release(in_buf);
|
||||||
/* If not lock req, update # of requests on wire to server */
|
/* If not lock req, update # of requests on wire to server */
|
||||||
if(long_op < 3) {
|
if(long_op < 3) {
|
||||||
atomic_dec(&ses->server->inFlight);
|
atomic_dec(&ses->server->inFlight);
|
||||||
wake_up(&ses->server->request_q);
|
wake_up(&ses->server->request_q);
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
} else
|
} else {
|
||||||
up(&ses->server->tcpSem);
|
up(&ses->server->tcpSem);
|
||||||
|
cifs_small_buf_release(in_buf);
|
||||||
|
}
|
||||||
|
|
||||||
if (long_op == -1)
|
if (long_op == -1)
|
||||||
goto cifs_no_response_exit2;
|
goto cifs_no_response_exit2;
|
||||||
else if (long_op == 2) /* writes past end of file can take loong time */
|
else if (long_op == 2) /* writes past end of file can take loong time */
|
||||||
|
@ -543,6 +548,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
|
||||||
|
|
||||||
out_unlock2:
|
out_unlock2:
|
||||||
up(&ses->server->tcpSem);
|
up(&ses->server->tcpSem);
|
||||||
|
cifs_small_buf_release(in_buf);
|
||||||
/* If not lock req, update # of requests on wire to server */
|
/* If not lock req, update # of requests on wire to server */
|
||||||
if(long_op < 3) {
|
if(long_op < 3) {
|
||||||
atomic_dec(&ses->server->inFlight);
|
atomic_dec(&ses->server->inFlight);
|
||||||
|
|
Loading…
Reference in New Issue