diff options
| -rw-r--r-- | fs/cifs/CHANGES | 18 | ||||
| -rw-r--r-- | fs/cifs/Makefile | 2 | ||||
| -rw-r--r-- | fs/cifs/README | 7 | ||||
| -rw-r--r-- | fs/cifs/cifsencrypt.c | 6 | ||||
| -rw-r--r-- | fs/cifs/cifsfs.c | 5 | ||||
| -rw-r--r-- | fs/cifs/cifsfs.h | 2 | ||||
| -rw-r--r-- | fs/cifs/cifsglob.h | 11 | ||||
| -rw-r--r-- | fs/cifs/cifspdu.h | 13 | ||||
| -rw-r--r-- | fs/cifs/cifsproto.h | 15 | ||||
| -rw-r--r-- | fs/cifs/cifssmb.c | 135 | ||||
| -rw-r--r-- | fs/cifs/connect.c | 99 | ||||
| -rw-r--r-- | fs/cifs/dir.c | 7 | ||||
| -rw-r--r-- | fs/cifs/file.c | 94 | ||||
| -rw-r--r-- | fs/cifs/inode.c | 7 | ||||
| -rw-r--r-- | fs/cifs/link.c | 2 | ||||
| -rw-r--r-- | fs/cifs/misc.c | 46 | ||||
| -rw-r--r-- | fs/cifs/ntlmssp.c | 129 | ||||
| -rw-r--r-- | fs/cifs/ntlmssp.h | 2 | ||||
| -rw-r--r-- | fs/cifs/readdir.c | 7 | ||||
| -rw-r--r-- | fs/cifs/transport.c | 22 |
20 files changed, 491 insertions, 138 deletions
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index d335015473a5..3e0fcc394810 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES | |||
| @@ -1,3 +1,21 @@ | |||
| 1 | Version 1.42 | ||
| 2 | ------------ | ||
| 3 | Fix slow oplock break when mounted to different servers at the same time and | ||
| 4 | the tids match and we try to find matching fid on wrong server. | ||
| 5 | |||
| 6 | Version 1.41 | ||
| 7 | ------------ | ||
| 8 | Fix NTLMv2 security (can be enabled in /proc/fs/cifs) so customers can | ||
| 9 | configure stronger authentication. Fix sfu symlinks so they can | ||
| 10 | be followed (not just recognized). Fix wraparound of bcc on | ||
| 11 | read responses when buffer size over 64K and also fix wrap of | ||
| 12 | max smb buffer size when CIFSMaxBufSize over 64K. Fix oops in | ||
| 13 | cifs_user_read and cifs_readpages (when EAGAIN on send of smb | ||
| 14 | on socket is returned over and over). Add POSIX (advisory) byte range | ||
| 15 | locking support (requires server with newest CIFS UNIX Extensions | ||
| 16 | to the protocol implemented). Slow down negprot slightly in port 139 | ||
| 17 | RFC1001 case to give session_init time on buggy servers. | ||
| 18 | |||
| 1 | Version 1.40 | 19 | Version 1.40 |
| 2 | ------------ | 20 | ------------ |
| 3 | Use fsuid (fsgid) more consistently instead of uid (gid). Improve performance | 21 | Use fsuid (fsgid) more consistently instead of uid (gid). Improve performance |
diff --git a/fs/cifs/Makefile b/fs/cifs/Makefile index 7384947a0f93..58c77254a23b 100644 --- a/fs/cifs/Makefile +++ b/fs/cifs/Makefile | |||
| @@ -3,4 +3,4 @@ | |||
| 3 | # | 3 | # |
| 4 | obj-$(CONFIG_CIFS) += cifs.o | 4 | obj-$(CONFIG_CIFS) += cifs.o |
| 5 | 5 | ||
| 6 | 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 | 6 | cifs-objs := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o md4.o md5.o cifs_unicode.o nterr.o xattr.o cifsencrypt.o fcntl.o readdir.o ioctl.o ntlmssp.o |
diff --git a/fs/cifs/README b/fs/cifs/README index b0070d1b149d..b2b4d0803761 100644 --- a/fs/cifs/README +++ b/fs/cifs/README | |||
| @@ -422,6 +422,13 @@ A partial list of the supported mount options follows: | |||
| 422 | nomapchars Do not translate any of these seven characters (default). | 422 | nomapchars Do not translate any of these seven characters (default). |
| 423 | nocase Request case insensitive path name matching (case | 423 | nocase Request case insensitive path name matching (case |
| 424 | sensitive is the default if the server suports it). | 424 | sensitive is the default if the server suports it). |
| 425 | posixpaths If CIFS Unix extensions are supported, attempt to | ||
| 426 | negotiate posix path name support which allows certain | ||
| 427 | characters forbidden in typical CIFS filenames, without | ||
| 428 | requiring remapping. (default) | ||
| 429 | noposixpaths If CIFS Unix extensions are supported, do not request | ||
| 430 | posix path name support (this may cause servers to | ||
| 431 | reject creatingfile with certain reserved characters). | ||
| 425 | nobrl Do not send byte range lock requests to the server. | 432 | nobrl Do not send byte range lock requests to the server. |
| 426 | This is necessary for certain applications that break | 433 | This is necessary for certain applications that break |
| 427 | with cifs style mandatory byte range locks (and most | 434 | with cifs style mandatory byte range locks (and most |
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c index a2c24858d40f..c2cbe0ed98b3 100644 --- a/fs/cifs/cifsencrypt.c +++ b/fs/cifs/cifsencrypt.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * fs/cifs/cifsencrypt.c | 2 | * fs/cifs/cifsencrypt.c |
| 3 | * | 3 | * |
| 4 | * Copyright (C) International Business Machines Corp., 2005 | 4 | * Copyright (C) International Business Machines Corp., 2005,2006 |
| 5 | * Author(s): Steve French (sfrench@us.ibm.com) | 5 | * Author(s): Steve French (sfrench@us.ibm.com) |
| 6 | * | 6 | * |
| 7 | * This library is free software; you can redistribute it and/or modify | 7 | * This library is free software; you can redistribute it and/or modify |
| @@ -36,7 +36,8 @@ | |||
| 36 | extern void mdfour(unsigned char *out, unsigned char *in, int n); | 36 | extern void mdfour(unsigned char *out, unsigned char *in, int n); |
| 37 | extern void E_md4hash(const unsigned char *passwd, unsigned char *p16); | 37 | extern void E_md4hash(const unsigned char *passwd, unsigned char *p16); |
| 38 | 38 | ||
| 39 | static int cifs_calculate_signature(const struct smb_hdr * cifs_pdu, const char * key, char * signature) | 39 | static int cifs_calculate_signature(const struct smb_hdr * cifs_pdu, |
| 40 | const char * key, char * signature) | ||
| 40 | { | 41 | { |
| 41 | struct MD5Context context; | 42 | struct MD5Context context; |
| 42 | 43 | ||
| @@ -259,4 +260,5 @@ void CalcNTLMv2_response(const struct cifsSesInfo * ses,char * v2_session_respon | |||
| 259 | /* hmac_md5_update(v2_session_response+16)client thing,8,&context); */ /* BB fix */ | 260 | /* hmac_md5_update(v2_session_response+16)client thing,8,&context); */ /* BB fix */ |
| 260 | 261 | ||
| 261 | hmac_md5_final(v2_session_response,&context); | 262 | hmac_md5_final(v2_session_response,&context); |
| 263 | cifs_dump_mem("v2_sess_rsp: ", v2_session_response, 32); /* BB removeme BB */ | ||
| 262 | } | 264 | } |
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 79eeccd0437f..8219c02145a7 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
| @@ -93,13 +93,10 @@ cifs_read_super(struct super_block *sb, void *data, | |||
| 93 | int rc = 0; | 93 | int rc = 0; |
| 94 | 94 | ||
| 95 | sb->s_flags |= MS_NODIRATIME; /* and probably even noatime */ | 95 | sb->s_flags |= MS_NODIRATIME; /* and probably even noatime */ |
| 96 | sb->s_fs_info = kmalloc(sizeof(struct cifs_sb_info),GFP_KERNEL); | 96 | sb->s_fs_info = kzalloc(sizeof(struct cifs_sb_info),GFP_KERNEL); |
| 97 | cifs_sb = CIFS_SB(sb); | 97 | cifs_sb = CIFS_SB(sb); |
| 98 | if(cifs_sb == NULL) | 98 | if(cifs_sb == NULL) |
| 99 | return -ENOMEM; | 99 | return -ENOMEM; |
| 100 | else | ||
| 101 | memset(cifs_sb,0,sizeof(struct cifs_sb_info)); | ||
| 102 | |||
| 103 | 100 | ||
| 104 | rc = cifs_mount(sb, cifs_sb, data, devname); | 101 | rc = cifs_mount(sb, cifs_sb, data, devname); |
| 105 | 102 | ||
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index 821a8eb22559..b4dcdc2052a0 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h | |||
| @@ -99,5 +99,5 @@ extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t); | |||
| 99 | extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); | 99 | extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); |
| 100 | extern int cifs_ioctl (struct inode * inode, struct file * filep, | 100 | extern int cifs_ioctl (struct inode * inode, struct file * filep, |
| 101 | unsigned int command, unsigned long arg); | 101 | unsigned int command, unsigned long arg); |
| 102 | #define CIFS_VERSION "1.40" | 102 | #define CIFS_VERSION "1.42" |
| 103 | #endif /* _CIFSFS_H */ | 103 | #endif /* _CIFSFS_H */ |
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 7bed27601ce5..006eb33bff5f 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * fs/cifs/cifsglob.h | 2 | * fs/cifs/cifsglob.h |
| 3 | * | 3 | * |
| 4 | * Copyright (C) International Business Machines Corp., 2002,2005 | 4 | * Copyright (C) International Business Machines Corp., 2002,2006 |
| 5 | * Author(s): Steve French (sfrench@us.ibm.com) | 5 | * Author(s): Steve French (sfrench@us.ibm.com) |
| 6 | * | 6 | * |
| 7 | * This library is free software; you can redistribute it and/or modify | 7 | * This library is free software; you can redistribute it and/or modify |
| @@ -430,6 +430,15 @@ struct dir_notify_req { | |||
| 430 | #define CIFS_LARGE_BUFFER 2 | 430 | #define CIFS_LARGE_BUFFER 2 |
| 431 | #define CIFS_IOVEC 4 /* array of response buffers */ | 431 | #define CIFS_IOVEC 4 /* array of response buffers */ |
| 432 | 432 | ||
| 433 | /* Type of session setup needed */ | ||
| 434 | #define CIFS_PLAINTEXT 0 | ||
| 435 | #define CIFS_LANMAN 1 | ||
| 436 | #define CIFS_NTLM 2 | ||
| 437 | #define CIFS_NTLMSSP_NEG 3 | ||
| 438 | #define CIFS_NTLMSSP_AUTH 4 | ||
| 439 | #define CIFS_SPNEGO_INIT 5 | ||
| 440 | #define CIFS_SPNEGO_TARG 6 | ||
| 441 | |||
| 433 | /* | 442 | /* |
| 434 | ***************************************************************** | 443 | ***************************************************************** |
| 435 | * All constants go here | 444 | * All constants go here |
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h index cc2471094ca5..b2233ac05bd2 100644 --- a/fs/cifs/cifspdu.h +++ b/fs/cifs/cifspdu.h | |||
| @@ -859,7 +859,10 @@ typedef struct smb_com_lock_req { | |||
| 859 | LOCKING_ANDX_RANGE Locks[1]; | 859 | LOCKING_ANDX_RANGE Locks[1]; |
| 860 | } __attribute__((packed)) LOCK_REQ; | 860 | } __attribute__((packed)) LOCK_REQ; |
| 861 | 861 | ||
| 862 | 862 | /* lock type */ | |
| 863 | #define CIFS_RDLCK 0 | ||
| 864 | #define CIFS_WRLCK 1 | ||
| 865 | #define CIFS_UNLCK 2 | ||
| 863 | typedef struct cifs_posix_lock { | 866 | typedef struct cifs_posix_lock { |
| 864 | __le16 lock_type; /* 0 = Read, 1 = Write, 2 = Unlock */ | 867 | __le16 lock_type; /* 0 = Read, 1 = Write, 2 = Unlock */ |
| 865 | __le16 lock_flags; /* 1 = Wait (only valid for setlock) */ | 868 | __le16 lock_flags; /* 1 = Wait (only valid for setlock) */ |
| @@ -1786,7 +1789,13 @@ typedef struct { | |||
| 1786 | #define CIFS_UNIX_POSIX_ACL_CAP 0x00000002 /* support getfacl/setfacl */ | 1789 | #define CIFS_UNIX_POSIX_ACL_CAP 0x00000002 /* support getfacl/setfacl */ |
| 1787 | #define CIFS_UNIX_XATTR_CAP 0x00000004 /* support new namespace */ | 1790 | #define CIFS_UNIX_XATTR_CAP 0x00000004 /* support new namespace */ |
| 1788 | #define CIFS_UNIX_EXTATTR_CAP 0x00000008 /* support chattr/chflag */ | 1791 | #define CIFS_UNIX_EXTATTR_CAP 0x00000008 /* support chattr/chflag */ |
| 1789 | #define CIFS_UNIX_POSIX_PATHNAMES_CAP 0x00000010 /* Use POSIX pathnames on the wire. */ | 1792 | #define CIFS_UNIX_POSIX_PATHNAMES_CAP 0x00000010 /* Allow POSIX path chars */ |
| 1793 | #ifdef CONFIG_CIFS_POSIX | ||
| 1794 | #define CIFS_UNIX_CAP_MASK 0x0000001b | ||
| 1795 | #else | ||
| 1796 | #define CIFS_UNIX_CAP_MASK 0x00000013 | ||
| 1797 | #endif /* CONFIG_CIFS_POSIX */ | ||
| 1798 | |||
| 1790 | 1799 | ||
| 1791 | #define CIFS_POSIX_EXTENSIONS 0x00000010 /* support for new QFSInfo */ | 1800 | #define CIFS_POSIX_EXTENSIONS 0x00000010 /* support for new QFSInfo */ |
| 1792 | 1801 | ||
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 7b25463d3c14..2879ba343ca7 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * fs/cifs/cifsproto.h | 2 | * fs/cifs/cifsproto.h |
| 3 | * | 3 | * |
| 4 | * Copyright (c) International Business Machines Corp., 2002,2005 | 4 | * Copyright (c) International Business Machines Corp., 2002,2006 |
| 5 | * Author(s): Steve French (sfrench@us.ibm.com) | 5 | * Author(s): Steve French (sfrench@us.ibm.com) |
| 6 | * | 6 | * |
| 7 | * This library is free software; you can redistribute it and/or modify | 7 | * 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); | |||
| 64 | extern void header_assemble(struct smb_hdr *, char /* command */ , | 64 | extern void header_assemble(struct smb_hdr *, char /* command */ , |
| 65 | const struct cifsTconInfo *, int /* length of | 65 | const struct cifsTconInfo *, int /* length of |
| 66 | fixed section (word count) in two byte units */); | 66 | fixed section (word count) in two byte units */); |
| 67 | #ifdef CONFIG_CIFS_EXPERIMENTAL | ||
| 68 | extern int small_smb_init_no_tc(const int smb_cmd, const int wct, | ||
| 69 | struct cifsSesInfo *ses, | ||
| 70 | void ** request_buf); | ||
| 71 | extern int CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, | ||
| 72 | const int stage, int * pNTLMv2_flg, | ||
| 73 | const struct nls_table *nls_cp); | ||
| 74 | #endif | ||
| 67 | extern __u16 GetNextMid(struct TCP_Server_Info *server); | 75 | extern __u16 GetNextMid(struct TCP_Server_Info *server); |
| 68 | extern struct oplock_q_entry * AllocOplockQEntry(struct inode *, u16, | 76 | extern struct oplock_q_entry * AllocOplockQEntry(struct inode *, u16, |
| 69 | struct cifsTconInfo *); | 77 | struct cifsTconInfo *); |
| @@ -257,7 +265,10 @@ extern int CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, | |||
| 257 | const __u64 offset, const __u32 numUnlock, | 265 | const __u64 offset, const __u32 numUnlock, |
| 258 | const __u32 numLock, const __u8 lockType, | 266 | const __u32 numLock, const __u8 lockType, |
| 259 | const int waitFlag); | 267 | const int waitFlag); |
| 260 | 268 | extern int CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon, | |
| 269 | const __u16 smb_file_id, const int get_flag, | ||
| 270 | const __u64 len, const __u64 offset, | ||
| 271 | const __u16 lock_type, const int waitFlag); | ||
| 261 | extern int CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon); | 272 | extern int CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon); |
| 262 | extern int CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses); | 273 | extern int CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses); |
| 263 | 274 | ||
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index b41e8b379652..a5941872d3f7 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * fs/cifs/cifssmb.c | 2 | * fs/cifs/cifssmb.c |
| 3 | * | 3 | * |
| 4 | * Copyright (C) International Business Machines Corp., 2002,2005 | 4 | * Copyright (C) International Business Machines Corp., 2002,2006 |
| 5 | * Author(s): Steve French (sfrench@us.ibm.com) | 5 | * Author(s): Steve French (sfrench@us.ibm.com) |
| 6 | * | 6 | * |
| 7 | * Contains the routines for constructing the SMB PDUs themselves | 7 | * Contains the routines for constructing the SMB PDUs themselves |
| @@ -186,7 +186,35 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon, | |||
| 186 | cifs_stats_inc(&tcon->num_smbs_sent); | 186 | cifs_stats_inc(&tcon->num_smbs_sent); |
| 187 | 187 | ||
| 188 | return rc; | 188 | return rc; |
| 189 | } | 189 | } |
| 190 | |||
| 191 | #ifdef CONFIG_CIFS_EXPERIMENTAL | ||
| 192 | int | ||
| 193 | small_smb_init_no_tc(const int smb_command, const int wct, | ||
| 194 | struct cifsSesInfo *ses, void **request_buf) | ||
| 195 | { | ||
| 196 | int rc; | ||
| 197 | struct smb_hdr * buffer; | ||
| 198 | |||
| 199 | rc = small_smb_init(smb_command, wct, NULL, request_buf); | ||
| 200 | if(rc) | ||
| 201 | return rc; | ||
| 202 | |||
| 203 | buffer = (struct smb_hdr *)*request_buf; | ||
| 204 | buffer->Mid = GetNextMid(ses->server); | ||
| 205 | if (ses->capabilities & CAP_UNICODE) | ||
| 206 | buffer->Flags2 |= SMBFLG2_UNICODE; | ||
| 207 | if (ses->capabilities & CAP_STATUS32) | ||
| 208 | buffer->Flags2 |= SMBFLG2_ERR_STATUS; | ||
| 209 | |||
| 210 | /* uid, tid can stay at zero as set in header assemble */ | ||
| 211 | |||
| 212 | /* BB add support for turning on the signing when | ||
| 213 | this function is used after 1st of session setup requests */ | ||
| 214 | |||
| 215 | return rc; | ||
| 216 | } | ||
| 217 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ | ||
| 190 | 218 | ||
| 191 | /* If the return code is zero, this function must fill in request_buf pointer */ | 219 | /* If the return code is zero, this function must fill in request_buf pointer */ |
| 192 | static int | 220 | static int |
| @@ -1042,7 +1070,7 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, | |||
| 1042 | } | 1070 | } |
| 1043 | } | 1071 | } |
| 1044 | 1072 | ||
| 1045 | cifs_small_buf_release(pSMB); | 1073 | /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */ |
| 1046 | if(*buf) { | 1074 | if(*buf) { |
| 1047 | if(resp_buf_type == CIFS_SMALL_BUFFER) | 1075 | if(resp_buf_type == CIFS_SMALL_BUFFER) |
| 1048 | cifs_small_buf_release(iov[0].iov_base); | 1076 | cifs_small_buf_release(iov[0].iov_base); |
| @@ -1246,7 +1274,7 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon, | |||
| 1246 | *nbytes += le16_to_cpu(pSMBr->Count); | 1274 | *nbytes += le16_to_cpu(pSMBr->Count); |
| 1247 | } | 1275 | } |
| 1248 | 1276 | ||
| 1249 | cifs_small_buf_release(pSMB); | 1277 | /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */ |
| 1250 | if(resp_buf_type == CIFS_SMALL_BUFFER) | 1278 | if(resp_buf_type == CIFS_SMALL_BUFFER) |
| 1251 | cifs_small_buf_release(iov[0].iov_base); | 1279 | cifs_small_buf_release(iov[0].iov_base); |
| 1252 | else if(resp_buf_type == CIFS_LARGE_BUFFER) | 1280 | else if(resp_buf_type == CIFS_LARGE_BUFFER) |
| @@ -1325,6 +1353,85 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, | |||
| 1325 | } | 1353 | } |
| 1326 | 1354 | ||
| 1327 | int | 1355 | int |
| 1356 | CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon, | ||
| 1357 | const __u16 smb_file_id, const int get_flag, const __u64 len, | ||
| 1358 | const __u64 lkoffset, const __u16 lock_type, const int waitFlag) | ||
| 1359 | { | ||
| 1360 | struct smb_com_transaction2_sfi_req *pSMB = NULL; | ||
| 1361 | struct smb_com_transaction2_sfi_rsp *pSMBr = NULL; | ||
| 1362 | char *data_offset; | ||
| 1363 | struct cifs_posix_lock *parm_data; | ||
| 1364 | int rc = 0; | ||
| 1365 | int bytes_returned = 0; | ||
| 1366 | __u16 params, param_offset, offset, byte_count, count; | ||
| 1367 | |||
| 1368 | cFYI(1, ("Posix Lock")); | ||
| 1369 | rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB); | ||
| 1370 | |||
| 1371 | if (rc) | ||
| 1372 | return rc; | ||
| 1373 | |||
| 1374 | pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB; | ||
| 1375 | |||
| 1376 | params = 6; | ||
| 1377 | pSMB->MaxSetupCount = 0; | ||
| 1378 | pSMB->Reserved = 0; | ||
| 1379 | pSMB->Flags = 0; | ||
| 1380 | pSMB->Timeout = 0; | ||
| 1381 | pSMB->Reserved2 = 0; | ||
| 1382 | param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4; | ||
| 1383 | offset = param_offset + params; | ||
| 1384 | |||
| 1385 | data_offset = (char *) (&pSMB->hdr.Protocol) + offset; | ||
| 1386 | |||
| 1387 | count = sizeof(struct cifs_posix_lock); | ||
| 1388 | pSMB->MaxParameterCount = cpu_to_le16(2); | ||
| 1389 | pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */ | ||
| 1390 | pSMB->SetupCount = 1; | ||
| 1391 | pSMB->Reserved3 = 0; | ||
| 1392 | if(get_flag) | ||
| 1393 | pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION); | ||
| 1394 | else | ||
| 1395 | pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION); | ||
| 1396 | byte_count = 3 /* pad */ + params + count; | ||
| 1397 | pSMB->DataCount = cpu_to_le16(count); | ||
| 1398 | pSMB->ParameterCount = cpu_to_le16(params); | ||
| 1399 | pSMB->TotalDataCount = pSMB->DataCount; | ||
| 1400 | pSMB->TotalParameterCount = pSMB->ParameterCount; | ||
| 1401 | pSMB->ParameterOffset = cpu_to_le16(param_offset); | ||
| 1402 | parm_data = (struct cifs_posix_lock *) | ||
| 1403 | (((char *) &pSMB->hdr.Protocol) + offset); | ||
| 1404 | |||
| 1405 | parm_data->lock_type = cpu_to_le16(lock_type); | ||
| 1406 | if(waitFlag) | ||
| 1407 | parm_data->lock_flags = 1; | ||
| 1408 | parm_data->pid = cpu_to_le32(current->tgid); | ||
| 1409 | parm_data->start = lkoffset; | ||
| 1410 | parm_data->length = len; /* normalize negative numbers */ | ||
| 1411 | |||
| 1412 | pSMB->DataOffset = cpu_to_le16(offset); | ||
| 1413 | pSMB->Fid = smb_file_id; | ||
| 1414 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK); | ||
| 1415 | pSMB->Reserved4 = 0; | ||
| 1416 | pSMB->hdr.smb_buf_length += byte_count; | ||
| 1417 | pSMB->ByteCount = cpu_to_le16(byte_count); | ||
| 1418 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | ||
| 1419 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | ||
| 1420 | if (rc) { | ||
| 1421 | cFYI(1, ("Send error in Posix Lock = %d", rc)); | ||
| 1422 | } | ||
| 1423 | |||
| 1424 | if (pSMB) | ||
| 1425 | cifs_small_buf_release(pSMB); | ||
| 1426 | |||
| 1427 | /* Note: On -EAGAIN error only caller can retry on handle based calls | ||
| 1428 | since file handle passed in no longer valid */ | ||
| 1429 | |||
| 1430 | return rc; | ||
| 1431 | } | ||
| 1432 | |||
| 1433 | |||
| 1434 | int | ||
| 1328 | CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id) | 1435 | CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id) |
| 1329 | { | 1436 | { |
| 1330 | int rc = 0; | 1437 | int rc = 0; |
| @@ -2578,7 +2685,7 @@ qsec_out: | |||
| 2578 | cifs_small_buf_release(iov[0].iov_base); | 2685 | cifs_small_buf_release(iov[0].iov_base); |
| 2579 | else if(buf_type == CIFS_LARGE_BUFFER) | 2686 | else if(buf_type == CIFS_LARGE_BUFFER) |
| 2580 | cifs_buf_release(iov[0].iov_base); | 2687 | cifs_buf_release(iov[0].iov_base); |
| 2581 | cifs_small_buf_release(pSMB); | 2688 | /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */ |
| 2582 | return rc; | 2689 | return rc; |
| 2583 | } | 2690 | } |
| 2584 | 2691 | ||
| @@ -2954,7 +3061,8 @@ findFirstRetry: | |||
| 2954 | pSMB->TotalParameterCount = cpu_to_le16(params); | 3061 | pSMB->TotalParameterCount = cpu_to_le16(params); |
| 2955 | pSMB->ParameterCount = pSMB->TotalParameterCount; | 3062 | pSMB->ParameterCount = pSMB->TotalParameterCount; |
| 2956 | pSMB->ParameterOffset = cpu_to_le16( | 3063 | pSMB->ParameterOffset = cpu_to_le16( |
| 2957 | offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes) - 4); | 3064 | offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes) |
| 3065 | - 4); | ||
| 2958 | pSMB->DataCount = 0; | 3066 | pSMB->DataCount = 0; |
| 2959 | pSMB->DataOffset = 0; | 3067 | pSMB->DataOffset = 0; |
| 2960 | pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */ | 3068 | pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */ |
| @@ -2977,12 +3085,12 @@ findFirstRetry: | |||
| 2977 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 3085 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
| 2978 | cifs_stats_inc(&tcon->num_ffirst); | 3086 | cifs_stats_inc(&tcon->num_ffirst); |
| 2979 | 3087 | ||
| 2980 | if (rc) {/* BB add logic to retry regular search if Unix search rejected unexpectedly by server */ | 3088 | if (rc) {/* BB add logic to retry regular search if Unix search |
| 3089 | rejected unexpectedly by server */ | ||
| 2981 | /* BB Add code to handle unsupported level rc */ | 3090 | /* BB Add code to handle unsupported level rc */ |
| 2982 | cFYI(1, ("Error in FindFirst = %d", rc)); | 3091 | cFYI(1, ("Error in FindFirst = %d", rc)); |
| 2983 | 3092 | ||
| 2984 | if (pSMB) | 3093 | cifs_buf_release(pSMB); |
| 2985 | cifs_buf_release(pSMB); | ||
| 2986 | 3094 | ||
| 2987 | /* BB eventually could optimize out free and realloc of buf */ | 3095 | /* BB eventually could optimize out free and realloc of buf */ |
| 2988 | /* for this case */ | 3096 | /* for this case */ |
| @@ -2998,6 +3106,7 @@ findFirstRetry: | |||
| 2998 | psrch_inf->unicode = FALSE; | 3106 | psrch_inf->unicode = FALSE; |
| 2999 | 3107 | ||
| 3000 | psrch_inf->ntwrk_buf_start = (char *)pSMBr; | 3108 | psrch_inf->ntwrk_buf_start = (char *)pSMBr; |
| 3109 | psrch_inf->smallBuf = 0; | ||
| 3001 | psrch_inf->srch_entries_start = | 3110 | psrch_inf->srch_entries_start = |
| 3002 | (char *) &pSMBr->hdr.Protocol + | 3111 | (char *) &pSMBr->hdr.Protocol + |
| 3003 | le16_to_cpu(pSMBr->t2.DataOffset); | 3112 | le16_to_cpu(pSMBr->t2.DataOffset); |
| @@ -3118,9 +3227,14 @@ int CIFSFindNext(const int xid, struct cifsTconInfo *tcon, | |||
| 3118 | parms = (T2_FNEXT_RSP_PARMS *)response_data; | 3227 | parms = (T2_FNEXT_RSP_PARMS *)response_data; |
| 3119 | response_data = (char *)&pSMBr->hdr.Protocol + | 3228 | response_data = (char *)&pSMBr->hdr.Protocol + |
| 3120 | le16_to_cpu(pSMBr->t2.DataOffset); | 3229 | le16_to_cpu(pSMBr->t2.DataOffset); |
| 3121 | cifs_buf_release(psrch_inf->ntwrk_buf_start); | 3230 | if(psrch_inf->smallBuf) |
| 3231 | cifs_small_buf_release( | ||
| 3232 | psrch_inf->ntwrk_buf_start); | ||
| 3233 | else | ||
| 3234 | cifs_buf_release(psrch_inf->ntwrk_buf_start); | ||
| 3122 | psrch_inf->srch_entries_start = response_data; | 3235 | psrch_inf->srch_entries_start = response_data; |
| 3123 | psrch_inf->ntwrk_buf_start = (char *)pSMB; | 3236 | psrch_inf->ntwrk_buf_start = (char *)pSMB; |
| 3237 | psrch_inf->smallBuf = 0; | ||
| 3124 | if(parms->EndofSearch) | 3238 | if(parms->EndofSearch) |
| 3125 | psrch_inf->endOfSearch = TRUE; | 3239 | psrch_inf->endOfSearch = TRUE; |
| 3126 | else | 3240 | else |
| @@ -3834,6 +3948,7 @@ CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap) | |||
| 3834 | 3948 | ||
| 3835 | cFYI(1, ("In SETFSUnixInfo")); | 3949 | cFYI(1, ("In SETFSUnixInfo")); |
| 3836 | SETFSUnixRetry: | 3950 | SETFSUnixRetry: |
| 3951 | /* BB switch to small buf init to save memory */ | ||
| 3837 | rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, | 3952 | rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, |
| 3838 | (void **) &pSMBr); | 3953 | (void **) &pSMBr); |
| 3839 | if (rc) | 3954 | if (rc) |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 2a0c1f4ca0ae..0b86d5ca9014 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * fs/cifs/connect.c | 2 | * fs/cifs/connect.c |
| 3 | * | 3 | * |
| 4 | * Copyright (C) International Business Machines Corp., 2002,2005 | 4 | * Copyright (C) International Business Machines Corp., 2002,2006 |
| 5 | * Author(s): Steve French (sfrench@us.ibm.com) | 5 | * Author(s): Steve French (sfrench@us.ibm.com) |
| 6 | * | 6 | * |
| 7 | * This library is free software; you can redistribute it and/or modify | 7 | * This library is free software; you can redistribute it and/or modify |
| @@ -564,7 +564,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) | |||
| 564 | 564 | ||
| 565 | 565 | ||
| 566 | dump_smb(smb_buffer, length); | 566 | dump_smb(smb_buffer, length); |
| 567 | if (checkSMB (smb_buffer, smb_buffer->Mid, total_read+4)) { | 567 | if (checkSMB(smb_buffer, smb_buffer->Mid, total_read+4)) { |
| 568 | cifs_dump_mem("Bad SMB: ", smb_buffer, 48); | 568 | cifs_dump_mem("Bad SMB: ", smb_buffer, 48); |
| 569 | continue; | 569 | continue; |
| 570 | } | 570 | } |
| @@ -1476,6 +1476,14 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket, | |||
| 1476 | rc = smb_send(*csocket, smb_buf, 0x44, | 1476 | rc = smb_send(*csocket, smb_buf, 0x44, |
| 1477 | (struct sockaddr *)psin_server); | 1477 | (struct sockaddr *)psin_server); |
| 1478 | kfree(ses_init_buf); | 1478 | kfree(ses_init_buf); |
| 1479 | msleep(1); /* RFC1001 layer in at least one server | ||
| 1480 | requires very short break before negprot | ||
| 1481 | presumably because not expecting negprot | ||
| 1482 | to follow so fast. This is a simple | ||
| 1483 | solution that works without | ||
| 1484 | complicating the code and causes no | ||
| 1485 | significant slowing down on mount | ||
| 1486 | for everyone else */ | ||
| 1479 | } | 1487 | } |
| 1480 | /* else the negprot may still work without this | 1488 | /* else the negprot may still work without this |
| 1481 | even though malloc failed */ | 1489 | even though malloc failed */ |
| @@ -1920,27 +1928,34 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
| 1920 | cifs_sb->tcon = tcon; | 1928 | cifs_sb->tcon = tcon; |
| 1921 | tcon->ses = pSesInfo; | 1929 | tcon->ses = pSesInfo; |
| 1922 | 1930 | ||
| 1923 | /* do not care if following two calls succeed - informational only */ | 1931 | /* do not care if following two calls succeed - informational */ |
| 1924 | CIFSSMBQFSDeviceInfo(xid, tcon); | 1932 | CIFSSMBQFSDeviceInfo(xid, tcon); |
| 1925 | CIFSSMBQFSAttributeInfo(xid, tcon); | 1933 | CIFSSMBQFSAttributeInfo(xid, tcon); |
| 1934 | |||
| 1926 | if (tcon->ses->capabilities & CAP_UNIX) { | 1935 | if (tcon->ses->capabilities & CAP_UNIX) { |
| 1927 | if(!CIFSSMBQFSUnixInfo(xid, tcon)) { | 1936 | if(!CIFSSMBQFSUnixInfo(xid, tcon)) { |
| 1928 | if(!volume_info.no_psx_acl) { | 1937 | __u64 cap = |
| 1929 | if(CIFS_UNIX_POSIX_ACL_CAP & | 1938 | le64_to_cpu(tcon->fsUnixInfo.Capability); |
| 1930 | le64_to_cpu(tcon->fsUnixInfo.Capability)) | 1939 | cap &= CIFS_UNIX_CAP_MASK; |
| 1931 | cFYI(1,("server negotiated posix acl support")); | 1940 | if(volume_info.no_psx_acl) |
| 1932 | sb->s_flags |= MS_POSIXACL; | 1941 | cap &= ~CIFS_UNIX_POSIX_ACL_CAP; |
| 1942 | else if(CIFS_UNIX_POSIX_ACL_CAP & cap) { | ||
| 1943 | cFYI(1,("negotiated posix acl support")); | ||
| 1944 | sb->s_flags |= MS_POSIXACL; | ||
| 1933 | } | 1945 | } |
| 1934 | 1946 | ||
| 1935 | /* Try and negotiate POSIX pathnames if we can. */ | 1947 | if(volume_info.posix_paths == 0) |
| 1936 | if (volume_info.posix_paths && (CIFS_UNIX_POSIX_PATHNAMES_CAP & | 1948 | cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP; |
| 1937 | le64_to_cpu(tcon->fsUnixInfo.Capability))) { | 1949 | else if(cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) { |
| 1938 | if (!CIFSSMBSetFSUnixInfo(xid, tcon, CIFS_UNIX_POSIX_PATHNAMES_CAP)) { | 1950 | cFYI(1,("negotiate posix pathnames")); |
| 1939 | cFYI(1,("negotiated posix pathnames support")); | 1951 | cifs_sb->mnt_cifs_flags |= |
| 1940 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS; | 1952 | CIFS_MOUNT_POSIX_PATHS; |
| 1941 | } else { | 1953 | } |
| 1942 | cFYI(1,("posix pathnames support requested but not supported")); | 1954 | |
| 1943 | } | 1955 | cFYI(1,("Negotiate caps 0x%x",(int)cap)); |
| 1956 | |||
| 1957 | if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) { | ||
| 1958 | cFYI(1,("setting capabilities failed")); | ||
| 1944 | } | 1959 | } |
| 1945 | } | 1960 | } |
| 1946 | } | 1961 | } |
| @@ -2278,6 +2293,8 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
| 2278 | smb_buffer->Mid = GetNextMid(ses->server); | 2293 | smb_buffer->Mid = GetNextMid(ses->server); |
| 2279 | pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; | 2294 | pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; |
| 2280 | pSMB->req.AndXCommand = 0xFF; | 2295 | pSMB->req.AndXCommand = 0xFF; |
| 2296 | if(ses->server->maxBuf > 64*1024) | ||
| 2297 | ses->server->maxBuf = (64*1023); | ||
| 2281 | pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf); | 2298 | pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf); |
| 2282 | pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq); | 2299 | pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq); |
| 2283 | 2300 | ||
| @@ -2525,7 +2542,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, | |||
| 2525 | __u32 negotiate_flags, capabilities; | 2542 | __u32 negotiate_flags, capabilities; |
| 2526 | __u16 count; | 2543 | __u16 count; |
| 2527 | 2544 | ||
| 2528 | cFYI(1, ("In NTLMSSP sesssetup (negotiate) ")); | 2545 | cFYI(1, ("In NTLMSSP sesssetup (negotiate)")); |
| 2529 | if(ses == NULL) | 2546 | if(ses == NULL) |
| 2530 | return -EINVAL; | 2547 | return -EINVAL; |
| 2531 | domain = ses->domainName; | 2548 | domain = ses->domainName; |
| @@ -2575,7 +2592,8 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, | |||
| 2575 | SecurityBlob->MessageType = NtLmNegotiate; | 2592 | SecurityBlob->MessageType = NtLmNegotiate; |
| 2576 | negotiate_flags = | 2593 | negotiate_flags = |
| 2577 | NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM | | 2594 | NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM | |
| 2578 | NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM | 0x80000000 | | 2595 | NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM | |
| 2596 | NTLMSSP_NEGOTIATE_56 | | ||
| 2579 | /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128; | 2597 | /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128; |
| 2580 | if(sign_CIFS_PDUs) | 2598 | if(sign_CIFS_PDUs) |
| 2581 | negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN; | 2599 | negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN; |
| @@ -2588,26 +2606,11 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, | |||
| 2588 | SecurityBlob->WorkstationName.Length = 0; | 2606 | SecurityBlob->WorkstationName.Length = 0; |
| 2589 | SecurityBlob->WorkstationName.MaximumLength = 0; | 2607 | SecurityBlob->WorkstationName.MaximumLength = 0; |
| 2590 | 2608 | ||
| 2591 | if (domain == NULL) { | 2609 | /* Domain not sent on first Sesssetup in NTLMSSP, instead it is sent |
| 2592 | SecurityBlob->DomainName.Buffer = 0; | 2610 | along with username on auth request (ie the response to challenge) */ |
| 2593 | SecurityBlob->DomainName.Length = 0; | 2611 | SecurityBlob->DomainName.Buffer = 0; |
| 2594 | SecurityBlob->DomainName.MaximumLength = 0; | 2612 | SecurityBlob->DomainName.Length = 0; |
| 2595 | } else { | 2613 | SecurityBlob->DomainName.MaximumLength = 0; |
| 2596 | __u16 len; | ||
| 2597 | negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED; | ||
| 2598 | strncpy(bcc_ptr, domain, 63); | ||
| 2599 | len = strnlen(domain, 64); | ||
| 2600 | SecurityBlob->DomainName.MaximumLength = | ||
| 2601 | cpu_to_le16(len); | ||
| 2602 | SecurityBlob->DomainName.Buffer = | ||
| 2603 | cpu_to_le32((long) &SecurityBlob-> | ||
| 2604 | DomainString - | ||
| 2605 | (long) &SecurityBlob->Signature); | ||
| 2606 | bcc_ptr += len; | ||
| 2607 | SecurityBlobLength += len; | ||
| 2608 | SecurityBlob->DomainName.Length = | ||
| 2609 | cpu_to_le16(len); | ||
| 2610 | } | ||
| 2611 | if (ses->capabilities & CAP_UNICODE) { | 2614 | if (ses->capabilities & CAP_UNICODE) { |
| 2612 | if ((long) bcc_ptr % 2) { | 2615 | if ((long) bcc_ptr % 2) { |
| 2613 | *bcc_ptr = 0; | 2616 | *bcc_ptr = 0; |
| @@ -2677,7 +2680,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, | |||
| 2677 | SecurityBlob2->MessageType)); | 2680 | SecurityBlob2->MessageType)); |
| 2678 | } else if (ses) { | 2681 | } else if (ses) { |
| 2679 | ses->Suid = smb_buffer_response->Uid; /* UID left in le format */ | 2682 | ses->Suid = smb_buffer_response->Uid; /* UID left in le format */ |
| 2680 | cFYI(1, ("UID = %d ", ses->Suid)); | 2683 | cFYI(1, ("UID = %d", ses->Suid)); |
| 2681 | if ((pSMBr->resp.hdr.WordCount == 3) | 2684 | if ((pSMBr->resp.hdr.WordCount == 3) |
| 2682 | || ((pSMBr->resp.hdr.WordCount == 4) | 2685 | || ((pSMBr->resp.hdr.WordCount == 4) |
| 2683 | && (blob_len < | 2686 | && (blob_len < |
| @@ -2685,17 +2688,17 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, | |||
| 2685 | 2688 | ||
| 2686 | if (pSMBr->resp.hdr.WordCount == 4) { | 2689 | if (pSMBr->resp.hdr.WordCount == 4) { |
| 2687 | bcc_ptr += blob_len; | 2690 | bcc_ptr += blob_len; |
| 2688 | cFYI(1, | 2691 | cFYI(1, ("Security Blob Length %d", |
| 2689 | ("Security Blob Length %d ", | ||
| 2690 | blob_len)); | 2692 | blob_len)); |
| 2691 | } | 2693 | } |
| 2692 | 2694 | ||
| 2693 | cFYI(1, ("NTLMSSP Challenge rcvd ")); | 2695 | cFYI(1, ("NTLMSSP Challenge rcvd")); |
| 2694 | 2696 | ||
| 2695 | memcpy(ses->server->cryptKey, | 2697 | memcpy(ses->server->cryptKey, |
| 2696 | SecurityBlob2->Challenge, | 2698 | SecurityBlob2->Challenge, |
| 2697 | CIFS_CRYPTO_KEY_SIZE); | 2699 | CIFS_CRYPTO_KEY_SIZE); |
| 2698 | if(SecurityBlob2->NegotiateFlags & cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2)) | 2700 | if(SecurityBlob2->NegotiateFlags & |
| 2701 | cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2)) | ||
| 2699 | *pNTLMv2_flag = TRUE; | 2702 | *pNTLMv2_flag = TRUE; |
| 2700 | 2703 | ||
| 2701 | if((SecurityBlob2->NegotiateFlags & | 2704 | if((SecurityBlob2->NegotiateFlags & |
| @@ -2818,7 +2821,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, | |||
| 2818 | bcc_ptr++; | 2821 | bcc_ptr++; |
| 2819 | } else | 2822 | } else |
| 2820 | cFYI(1, | 2823 | cFYI(1, |
| 2821 | ("Variable field of length %d extends beyond end of smb ", | 2824 | ("Variable field of length %d extends beyond end of smb", |
| 2822 | len)); | 2825 | len)); |
| 2823 | } | 2826 | } |
| 2824 | } else { | 2827 | } else { |
| @@ -2830,7 +2833,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, | |||
| 2830 | } | 2833 | } |
| 2831 | } else { | 2834 | } else { |
| 2832 | cERROR(1, | 2835 | cERROR(1, |
| 2833 | (" Invalid Word count %d: ", | 2836 | (" Invalid Word count %d:", |
| 2834 | smb_buffer_response->WordCount)); | 2837 | smb_buffer_response->WordCount)); |
| 2835 | rc = -EIO; | 2838 | rc = -EIO; |
| 2836 | } | 2839 | } |
| @@ -3447,7 +3450,7 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, | |||
| 3447 | if (extended_security | 3450 | if (extended_security |
| 3448 | && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY) | 3451 | && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY) |
| 3449 | && (pSesInfo->server->secType == NTLMSSP)) { | 3452 | && (pSesInfo->server->secType == NTLMSSP)) { |
| 3450 | cFYI(1, ("New style sesssetup ")); | 3453 | cFYI(1, ("New style sesssetup")); |
| 3451 | rc = CIFSSpnegoSessSetup(xid, pSesInfo, | 3454 | rc = CIFSSpnegoSessSetup(xid, pSesInfo, |
| 3452 | NULL /* security blob */, | 3455 | NULL /* security blob */, |
| 3453 | 0 /* blob length */, | 3456 | 0 /* blob length */, |
| @@ -3455,7 +3458,7 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, | |||
| 3455 | } else if (extended_security | 3458 | } else if (extended_security |
| 3456 | && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY) | 3459 | && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY) |
| 3457 | && (pSesInfo->server->secType == RawNTLMSSP)) { | 3460 | && (pSesInfo->server->secType == RawNTLMSSP)) { |
| 3458 | cFYI(1, ("NTLMSSP sesssetup ")); | 3461 | cFYI(1, ("NTLMSSP sesssetup")); |
| 3459 | rc = CIFSNTLMSSPNegotiateSessSetup(xid, | 3462 | rc = CIFSNTLMSSPNegotiateSessSetup(xid, |
| 3460 | pSesInfo, | 3463 | pSesInfo, |
| 3461 | &ntlmv2_flag, | 3464 | &ntlmv2_flag, |
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index fed55e3c53df..ddd11fa15528 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c | |||
| @@ -48,13 +48,14 @@ build_path_from_dentry(struct dentry *direntry) | |||
| 48 | struct dentry *temp; | 48 | struct dentry *temp; |
| 49 | int namelen = 0; | 49 | int namelen = 0; |
| 50 | char *full_path; | 50 | char *full_path; |
| 51 | char dirsep = CIFS_DIR_SEP(CIFS_SB(direntry->d_sb)); | 51 | char dirsep; |
| 52 | 52 | ||
| 53 | if(direntry == NULL) | 53 | if(direntry == NULL) |
| 54 | return NULL; /* not much we can do if dentry is freed and | 54 | return NULL; /* not much we can do if dentry is freed and |
| 55 | we need to reopen the file after it was closed implicitly | 55 | we need to reopen the file after it was closed implicitly |
| 56 | when the server crashed */ | 56 | when the server crashed */ |
| 57 | 57 | ||
| 58 | dirsep = CIFS_DIR_SEP(CIFS_SB(direntry->d_sb)); | ||
| 58 | cifs_bp_rename_retry: | 59 | cifs_bp_rename_retry: |
| 59 | for (temp = direntry; !IS_ROOT(temp);) { | 60 | for (temp = direntry; !IS_ROOT(temp);) { |
| 60 | namelen += (1 + temp->d_name.len); | 61 | namelen += (1 + temp->d_name.len); |
| @@ -255,12 +256,10 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, | |||
| 255 | CIFSSMBClose(xid, pTcon, fileHandle); | 256 | CIFSSMBClose(xid, pTcon, fileHandle); |
| 256 | } else if(newinode) { | 257 | } else if(newinode) { |
| 257 | pCifsFile = | 258 | pCifsFile = |
| 258 | kmalloc(sizeof (struct cifsFileInfo), GFP_KERNEL); | 259 | kzalloc(sizeof (struct cifsFileInfo), GFP_KERNEL); |
| 259 | 260 | ||
| 260 | if(pCifsFile == NULL) | 261 | if(pCifsFile == NULL) |
| 261 | goto cifs_create_out; | 262 | goto cifs_create_out; |
| 262 | memset((char *)pCifsFile, 0, | ||
| 263 | sizeof (struct cifsFileInfo)); | ||
| 264 | pCifsFile->netfid = fileHandle; | 263 | pCifsFile->netfid = fileHandle; |
| 265 | pCifsFile->pid = current->tgid; | 264 | pCifsFile->pid = current->tgid; |
| 266 | pCifsFile->pInode = newinode; | 265 | pCifsFile->pInode = newinode; |
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 675bd2568297..2c093de26225 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
| @@ -555,7 +555,10 @@ int cifs_closedir(struct inode *inode, struct file *file) | |||
| 555 | if (ptmp) { | 555 | if (ptmp) { |
| 556 | cFYI(1, ("closedir free smb buf in srch struct")); | 556 | cFYI(1, ("closedir free smb buf in srch struct")); |
| 557 | pCFileStruct->srch_inf.ntwrk_buf_start = NULL; | 557 | pCFileStruct->srch_inf.ntwrk_buf_start = NULL; |
| 558 | cifs_buf_release(ptmp); | 558 | if(pCFileStruct->srch_inf.smallBuf) |
| 559 | cifs_small_buf_release(ptmp); | ||
| 560 | else | ||
| 561 | cifs_buf_release(ptmp); | ||
| 559 | } | 562 | } |
| 560 | ptmp = pCFileStruct->search_resume_name; | 563 | ptmp = pCFileStruct->search_resume_name; |
| 561 | if (ptmp) { | 564 | if (ptmp) { |
| @@ -574,13 +577,14 @@ int cifs_closedir(struct inode *inode, struct file *file) | |||
| 574 | int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) | 577 | int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) |
| 575 | { | 578 | { |
| 576 | int rc, xid; | 579 | int rc, xid; |
| 577 | __u32 lockType = LOCKING_ANDX_LARGE_FILES; | ||
| 578 | __u32 numLock = 0; | 580 | __u32 numLock = 0; |
| 579 | __u32 numUnlock = 0; | 581 | __u32 numUnlock = 0; |
| 580 | __u64 length; | 582 | __u64 length; |
| 581 | int wait_flag = FALSE; | 583 | int wait_flag = FALSE; |
| 582 | struct cifs_sb_info *cifs_sb; | 584 | struct cifs_sb_info *cifs_sb; |
| 583 | struct cifsTconInfo *pTcon; | 585 | struct cifsTconInfo *pTcon; |
| 586 | __u16 netfid; | ||
| 587 | __u8 lockType = LOCKING_ANDX_LARGE_FILES; | ||
| 584 | 588 | ||
| 585 | length = 1 + pfLock->fl_end - pfLock->fl_start; | 589 | length = 1 + pfLock->fl_end - pfLock->fl_start; |
| 586 | rc = -EACCES; | 590 | rc = -EACCES; |
| @@ -592,11 +596,11 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) | |||
| 592 | pfLock->fl_end)); | 596 | pfLock->fl_end)); |
| 593 | 597 | ||
| 594 | if (pfLock->fl_flags & FL_POSIX) | 598 | if (pfLock->fl_flags & FL_POSIX) |
| 595 | cFYI(1, ("Posix ")); | 599 | cFYI(1, ("Posix")); |
| 596 | if (pfLock->fl_flags & FL_FLOCK) | 600 | if (pfLock->fl_flags & FL_FLOCK) |
| 597 | cFYI(1, ("Flock ")); | 601 | cFYI(1, ("Flock")); |
| 598 | if (pfLock->fl_flags & FL_SLEEP) { | 602 | if (pfLock->fl_flags & FL_SLEEP) { |
| 599 | cFYI(1, ("Blocking lock ")); | 603 | cFYI(1, ("Blocking lock")); |
| 600 | wait_flag = TRUE; | 604 | wait_flag = TRUE; |
| 601 | } | 605 | } |
| 602 | if (pfLock->fl_flags & FL_ACCESS) | 606 | if (pfLock->fl_flags & FL_ACCESS) |
| @@ -612,21 +616,23 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) | |||
| 612 | cFYI(1, ("F_WRLCK ")); | 616 | cFYI(1, ("F_WRLCK ")); |
| 613 | numLock = 1; | 617 | numLock = 1; |
| 614 | } else if (pfLock->fl_type == F_UNLCK) { | 618 | } else if (pfLock->fl_type == F_UNLCK) { |
| 615 | cFYI(1, ("F_UNLCK ")); | 619 | cFYI(1, ("F_UNLCK")); |
| 616 | numUnlock = 1; | 620 | numUnlock = 1; |
| 621 | /* Check if unlock includes more than | ||
| 622 | one lock range */ | ||
| 617 | } else if (pfLock->fl_type == F_RDLCK) { | 623 | } else if (pfLock->fl_type == F_RDLCK) { |
| 618 | cFYI(1, ("F_RDLCK ")); | 624 | cFYI(1, ("F_RDLCK")); |
| 619 | lockType |= LOCKING_ANDX_SHARED_LOCK; | 625 | lockType |= LOCKING_ANDX_SHARED_LOCK; |
| 620 | numLock = 1; | 626 | numLock = 1; |
| 621 | } else if (pfLock->fl_type == F_EXLCK) { | 627 | } else if (pfLock->fl_type == F_EXLCK) { |
| 622 | cFYI(1, ("F_EXLCK ")); | 628 | cFYI(1, ("F_EXLCK")); |
| 623 | numLock = 1; | 629 | numLock = 1; |
| 624 | } else if (pfLock->fl_type == F_SHLCK) { | 630 | } else if (pfLock->fl_type == F_SHLCK) { |
| 625 | cFYI(1, ("F_SHLCK ")); | 631 | cFYI(1, ("F_SHLCK")); |
| 626 | lockType |= LOCKING_ANDX_SHARED_LOCK; | 632 | lockType |= LOCKING_ANDX_SHARED_LOCK; |
| 627 | numLock = 1; | 633 | numLock = 1; |
| 628 | } else | 634 | } else |
| 629 | cFYI(1, ("Unknown type of lock ")); | 635 | cFYI(1, ("Unknown type of lock")); |
| 630 | 636 | ||
| 631 | cifs_sb = CIFS_SB(file->f_dentry->d_sb); | 637 | cifs_sb = CIFS_SB(file->f_dentry->d_sb); |
| 632 | pTcon = cifs_sb->tcon; | 638 | pTcon = cifs_sb->tcon; |
| @@ -635,27 +641,41 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) | |||
| 635 | FreeXid(xid); | 641 | FreeXid(xid); |
| 636 | return -EBADF; | 642 | return -EBADF; |
| 637 | } | 643 | } |
| 644 | netfid = ((struct cifsFileInfo *)file->private_data)->netfid; | ||
| 645 | |||
| 638 | 646 | ||
| 647 | /* BB add code here to normalize offset and length to | ||
| 648 | account for negative length which we can not accept over the | ||
| 649 | wire */ | ||
| 639 | if (IS_GETLK(cmd)) { | 650 | if (IS_GETLK(cmd)) { |
| 640 | rc = CIFSSMBLock(xid, pTcon, | 651 | if(experimEnabled && |
| 641 | ((struct cifsFileInfo *)file-> | 652 | (cifs_sb->tcon->ses->capabilities & CAP_UNIX) && |
| 642 | private_data)->netfid, | 653 | (CIFS_UNIX_FCNTL_CAP & |
| 643 | length, | 654 | le64_to_cpu(cifs_sb->tcon->fsUnixInfo.Capability))) { |
| 644 | pfLock->fl_start, 0, 1, lockType, | 655 | int posix_lock_type; |
| 645 | 0 /* wait flag */ ); | 656 | if(lockType & LOCKING_ANDX_SHARED_LOCK) |
| 657 | posix_lock_type = CIFS_RDLCK; | ||
| 658 | else | ||
| 659 | posix_lock_type = CIFS_WRLCK; | ||
| 660 | rc = CIFSSMBPosixLock(xid, pTcon, netfid, 1 /* get */, | ||
| 661 | length, pfLock->fl_start, | ||
| 662 | posix_lock_type, wait_flag); | ||
| 663 | FreeXid(xid); | ||
| 664 | return rc; | ||
| 665 | } | ||
| 666 | |||
| 667 | /* BB we could chain these into one lock request BB */ | ||
| 668 | rc = CIFSSMBLock(xid, pTcon, netfid, length, pfLock->fl_start, | ||
| 669 | 0, 1, lockType, 0 /* wait flag */ ); | ||
| 646 | if (rc == 0) { | 670 | if (rc == 0) { |
| 647 | rc = CIFSSMBLock(xid, pTcon, | 671 | rc = CIFSSMBLock(xid, pTcon, netfid, length, |
| 648 | ((struct cifsFileInfo *) file-> | ||
| 649 | private_data)->netfid, | ||
| 650 | length, | ||
| 651 | pfLock->fl_start, 1 /* numUnlock */ , | 672 | pfLock->fl_start, 1 /* numUnlock */ , |
| 652 | 0 /* numLock */ , lockType, | 673 | 0 /* numLock */ , lockType, |
| 653 | 0 /* wait flag */ ); | 674 | 0 /* wait flag */ ); |
| 654 | pfLock->fl_type = F_UNLCK; | 675 | pfLock->fl_type = F_UNLCK; |
| 655 | if (rc != 0) | 676 | if (rc != 0) |
| 656 | cERROR(1, ("Error unlocking previously locked " | 677 | cERROR(1, ("Error unlocking previously locked " |
| 657 | "range %d during test of lock ", | 678 | "range %d during test of lock", rc)); |
| 658 | rc)); | ||
| 659 | rc = 0; | 679 | rc = 0; |
| 660 | 680 | ||
| 661 | } else { | 681 | } else { |
| @@ -667,12 +687,30 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) | |||
| 667 | FreeXid(xid); | 687 | FreeXid(xid); |
| 668 | return rc; | 688 | return rc; |
| 669 | } | 689 | } |
| 670 | 690 | if (experimEnabled && | |
| 671 | rc = CIFSSMBLock(xid, pTcon, | 691 | (cifs_sb->tcon->ses->capabilities & CAP_UNIX) && |
| 672 | ((struct cifsFileInfo *) file->private_data)-> | 692 | (CIFS_UNIX_FCNTL_CAP & |
| 673 | netfid, length, | 693 | le64_to_cpu(cifs_sb->tcon->fsUnixInfo.Capability))) { |
| 674 | pfLock->fl_start, numUnlock, numLock, lockType, | 694 | int posix_lock_type; |
| 675 | wait_flag); | 695 | if(lockType & LOCKING_ANDX_SHARED_LOCK) |
| 696 | posix_lock_type = CIFS_RDLCK; | ||
| 697 | else | ||
| 698 | posix_lock_type = CIFS_WRLCK; | ||
| 699 | |||
| 700 | if(numUnlock == 1) | ||
| 701 | posix_lock_type = CIFS_UNLCK; | ||
| 702 | else if(numLock == 0) { | ||
| 703 | /* if no lock or unlock then nothing | ||
| 704 | to do since we do not know what it is */ | ||
| 705 | FreeXid(xid); | ||
| 706 | return -EOPNOTSUPP; | ||
| 707 | } | ||
| 708 | rc = CIFSSMBPosixLock(xid, pTcon, netfid, 0 /* set */, | ||
| 709 | length, pfLock->fl_start, | ||
| 710 | posix_lock_type, wait_flag); | ||
| 711 | } else | ||
| 712 | rc = CIFSSMBLock(xid, pTcon, netfid, length, pfLock->fl_start, | ||
| 713 | numUnlock, numLock, lockType, wait_flag); | ||
| 676 | if (pfLock->fl_flags & FL_POSIX) | 714 | if (pfLock->fl_flags & FL_POSIX) |
| 677 | posix_lock_file_wait(file, pfLock); | 715 | posix_lock_file_wait(file, pfLock); |
| 678 | FreeXid(xid); | 716 | FreeXid(xid); |
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 59359911f481..b21038b99fc2 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
| @@ -609,9 +609,8 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry) | |||
| 609 | } | 609 | } |
| 610 | } else if (rc == -EACCES) { | 610 | } else if (rc == -EACCES) { |
| 611 | /* try only if r/o attribute set in local lookup data? */ | 611 | /* try only if r/o attribute set in local lookup data? */ |
| 612 | pinfo_buf = kmalloc(sizeof(FILE_BASIC_INFO), GFP_KERNEL); | 612 | pinfo_buf = kzalloc(sizeof(FILE_BASIC_INFO), GFP_KERNEL); |
| 613 | if (pinfo_buf) { | 613 | if (pinfo_buf) { |
| 614 | memset(pinfo_buf, 0, sizeof(FILE_BASIC_INFO)); | ||
| 615 | /* ATTRS set to normal clears r/o bit */ | 614 | /* ATTRS set to normal clears r/o bit */ |
| 616 | pinfo_buf->Attributes = cpu_to_le32(ATTR_NORMAL); | 615 | pinfo_buf->Attributes = cpu_to_le32(ATTR_NORMAL); |
| 617 | if (!(pTcon->ses->flags & CIFS_SES_NT4)) | 616 | if (!(pTcon->ses->flags & CIFS_SES_NT4)) |
| @@ -1167,7 +1166,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) | |||
| 1167 | nfid, npid, FALSE); | 1166 | nfid, npid, FALSE); |
| 1168 | atomic_dec(&open_file->wrtPending); | 1167 | atomic_dec(&open_file->wrtPending); |
| 1169 | cFYI(1,("SetFSize for attrs rc = %d", rc)); | 1168 | cFYI(1,("SetFSize for attrs rc = %d", rc)); |
| 1170 | if(rc == -EINVAL) { | 1169 | if((rc == -EINVAL) || (rc == -EOPNOTSUPP)) { |
| 1171 | int bytes_written; | 1170 | int bytes_written; |
| 1172 | rc = CIFSSMBWrite(xid, pTcon, | 1171 | rc = CIFSSMBWrite(xid, pTcon, |
| 1173 | nfid, 0, attrs->ia_size, | 1172 | nfid, 0, attrs->ia_size, |
| @@ -1189,7 +1188,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) | |||
| 1189 | cifs_sb->mnt_cifs_flags & | 1188 | cifs_sb->mnt_cifs_flags & |
| 1190 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 1189 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
| 1191 | cFYI(1, ("SetEOF by path (setattrs) rc = %d", rc)); | 1190 | cFYI(1, ("SetEOF by path (setattrs) rc = %d", rc)); |
| 1192 | if(rc == -EINVAL) { | 1191 | if((rc == -EINVAL) || (rc == -EOPNOTSUPP)) { |
| 1193 | __u16 netfid; | 1192 | __u16 netfid; |
| 1194 | int oplock = FALSE; | 1193 | int oplock = FALSE; |
| 1195 | 1194 | ||
diff --git a/fs/cifs/link.c b/fs/cifs/link.c index 0f99aae33162..ce86ec69fe01 100644 --- a/fs/cifs/link.c +++ b/fs/cifs/link.c | |||
| @@ -67,7 +67,7 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode, | |||
| 67 | cifs_sb_target->local_nls, | 67 | cifs_sb_target->local_nls, |
| 68 | cifs_sb_target->mnt_cifs_flags & | 68 | cifs_sb_target->mnt_cifs_flags & |
| 69 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 69 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
| 70 | if(rc == -EIO) | 70 | if((rc == -EIO) || (rc == -EINVAL)) |
| 71 | rc = -EOPNOTSUPP; | 71 | rc = -EOPNOTSUPP; |
| 72 | } | 72 | } |
| 73 | 73 | ||
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index 432ba15e2c2d..fafd056426e4 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c | |||
| @@ -72,10 +72,9 @@ sesInfoAlloc(void) | |||
| 72 | struct cifsSesInfo *ret_buf; | 72 | struct cifsSesInfo *ret_buf; |
| 73 | 73 | ||
| 74 | ret_buf = | 74 | ret_buf = |
| 75 | (struct cifsSesInfo *) kmalloc(sizeof (struct cifsSesInfo), | 75 | (struct cifsSesInfo *) kzalloc(sizeof (struct cifsSesInfo), |
| 76 | GFP_KERNEL); | 76 | GFP_KERNEL); |
| 77 | if (ret_buf) { | 77 | if (ret_buf) { |
| 78 | memset(ret_buf, 0, sizeof (struct cifsSesInfo)); | ||
| 79 | write_lock(&GlobalSMBSeslock); | 78 | write_lock(&GlobalSMBSeslock); |
| 80 | atomic_inc(&sesInfoAllocCount); | 79 | atomic_inc(&sesInfoAllocCount); |
| 81 | ret_buf->status = CifsNew; | 80 | ret_buf->status = CifsNew; |
| @@ -110,10 +109,9 @@ tconInfoAlloc(void) | |||
| 110 | { | 109 | { |
| 111 | struct cifsTconInfo *ret_buf; | 110 | struct cifsTconInfo *ret_buf; |
| 112 | ret_buf = | 111 | ret_buf = |
| 113 | (struct cifsTconInfo *) kmalloc(sizeof (struct cifsTconInfo), | 112 | (struct cifsTconInfo *) kzalloc(sizeof (struct cifsTconInfo), |
| 114 | GFP_KERNEL); | 113 | GFP_KERNEL); |
| 115 | if (ret_buf) { | 114 | if (ret_buf) { |
| 116 | memset(ret_buf, 0, sizeof (struct cifsTconInfo)); | ||
| 117 | write_lock(&GlobalSMBSeslock); | 115 | write_lock(&GlobalSMBSeslock); |
| 118 | atomic_inc(&tconInfoAllocCount); | 116 | atomic_inc(&tconInfoAllocCount); |
| 119 | list_add(&ret_buf->cifsConnectionList, | 117 | list_add(&ret_buf->cifsConnectionList, |
| @@ -423,9 +421,7 @@ checkSMB(struct smb_hdr *smb, __u16 mid, int length) | |||
| 423 | { | 421 | { |
| 424 | __u32 len = smb->smb_buf_length; | 422 | __u32 len = smb->smb_buf_length; |
| 425 | __u32 clc_len; /* calculated length */ | 423 | __u32 clc_len; /* calculated length */ |
| 426 | cFYI(0, | 424 | cFYI(0, ("checkSMB Length: 0x%x, smb_buf_length: 0x%x", length, len)); |
| 427 | ("Entering checkSMB with Length: %x, smb_buf_length: %x", | ||
| 428 | length, len)); | ||
| 429 | if (((unsigned int)length < 2 + sizeof (struct smb_hdr)) || | 425 | if (((unsigned int)length < 2 + sizeof (struct smb_hdr)) || |
| 430 | (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4)) { | 426 | (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4)) { |
| 431 | if ((unsigned int)length < 2 + sizeof (struct smb_hdr)) { | 427 | if ((unsigned int)length < 2 + sizeof (struct smb_hdr)) { |
| @@ -433,29 +429,36 @@ checkSMB(struct smb_hdr *smb, __u16 mid, int length) | |||
| 433 | sizeof (struct smb_hdr) - 1) | 429 | sizeof (struct smb_hdr) - 1) |
| 434 | && (smb->Status.CifsError != 0)) { | 430 | && (smb->Status.CifsError != 0)) { |
| 435 | smb->WordCount = 0; | 431 | smb->WordCount = 0; |
| 436 | return 0; /* some error cases do not return wct and bcc */ | 432 | /* some error cases do not return wct and bcc */ |
| 433 | return 0; | ||
| 437 | } else { | 434 | } else { |
| 438 | cERROR(1, ("Length less than smb header size")); | 435 | cERROR(1, ("Length less than smb header size")); |
| 439 | } | 436 | } |
| 440 | |||
| 441 | } | 437 | } |
| 442 | if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) | 438 | if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) |
| 443 | cERROR(1, | 439 | cERROR(1, ("smb length greater than MaxBufSize, mid=%d", |
| 444 | ("smb_buf_length greater than MaxBufSize")); | 440 | smb->Mid)); |
| 445 | cERROR(1, | ||
| 446 | ("bad smb detected. Illegal length. mid=%d", | ||
| 447 | smb->Mid)); | ||
| 448 | return 1; | 441 | return 1; |
| 449 | } | 442 | } |
| 450 | 443 | ||
| 451 | if (checkSMBhdr(smb, mid)) | 444 | if (checkSMBhdr(smb, mid)) |
| 452 | return 1; | 445 | return 1; |
| 453 | clc_len = smbCalcSize_LE(smb); | 446 | clc_len = smbCalcSize_LE(smb); |
| 454 | if ((4 + len != clc_len) | 447 | |
| 455 | || (4 + len != (unsigned int)length)) { | 448 | if(4 + len != (unsigned int)length) { |
| 456 | cERROR(1, ("Calculated size 0x%x vs actual length 0x%x", | 449 | cERROR(1, ("Length read does not match RFC1001 length %d",len)); |
| 457 | clc_len, 4 + len)); | 450 | return 1; |
| 458 | cERROR(1, ("bad smb size detected for Mid=%d", smb->Mid)); | 451 | } |
| 452 | |||
| 453 | if (4 + len != clc_len) { | ||
| 454 | /* check if bcc wrapped around for large read responses */ | ||
| 455 | if((len > 64 * 1024) && (len > clc_len)) { | ||
| 456 | /* check if lengths match mod 64K */ | ||
| 457 | if(((4 + len) & 0xFFFF) == (clc_len & 0xFFFF)) | ||
| 458 | return 0; /* bcc wrapped */ | ||
| 459 | } | ||
| 460 | cFYI(1, ("Calculated size %d vs length %d mismatch for mid %d", | ||
| 461 | clc_len, 4 + len, smb->Mid)); | ||
| 459 | /* Windows XP can return a few bytes too much, presumably | 462 | /* Windows XP can return a few bytes too much, presumably |
| 460 | an illegal pad, at the end of byte range lock responses | 463 | an illegal pad, at the end of byte range lock responses |
| 461 | so we allow for that three byte pad, as long as actual | 464 | 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) | |||
| 469 | wct and bcc to minimum size and drop the t2 parms and data */ | 472 | wct and bcc to minimum size and drop the t2 parms and data */ |
| 470 | if((4+len > clc_len) && (len <= clc_len + 512)) | 473 | if((4+len > clc_len) && (len <= clc_len + 512)) |
| 471 | return 0; | 474 | return 0; |
| 472 | else | 475 | else { |
| 476 | cERROR(1, ("RFC1001 size %d bigger than SMB for Mid=%d", | ||
| 477 | len, smb->Mid)); | ||
| 473 | return 1; | 478 | return 1; |
| 479 | } | ||
| 474 | } | 480 | } |
| 475 | return 0; | 481 | return 0; |
| 476 | } | 482 | } |
diff --git a/fs/cifs/ntlmssp.c b/fs/cifs/ntlmssp.c new file mode 100644 index 000000000000..78866f925747 --- /dev/null +++ b/fs/cifs/ntlmssp.c | |||
| @@ -0,0 +1,129 @@ | |||
| 1 | /* | ||
| 2 | * fs/cifs/ntlmssp.h | ||
| 3 | * | ||
| 4 | * Copyright (c) International Business Machines Corp., 2006 | ||
| 5 | * Author(s): Steve French (sfrench@us.ibm.com) | ||
| 6 | * | ||
| 7 | * This library is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU Lesser General Public License as published | ||
| 9 | * by the Free Software Foundation; either version 2.1 of the License, or | ||
| 10 | * (at your option) any later version. | ||
| 11 | * | ||
| 12 | * This library is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See | ||
| 15 | * the GNU Lesser General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU Lesser General Public License | ||
| 18 | * along with this library; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 20 | */ | ||
| 21 | |||
| 22 | #include "cifspdu.h" | ||
| 23 | #include "cifsglob.h" | ||
| 24 | #include "cifsproto.h" | ||
| 25 | #include "cifs_unicode.h" | ||
| 26 | #include "cifs_debug.h" | ||
| 27 | #include "ntlmssp.h" | ||
| 28 | #include "nterr.h" | ||
| 29 | |||
| 30 | #ifdef CONFIG_CIFS_EXPERIMENTAL | ||
| 31 | static __u32 cifs_ssetup_hdr(struct cifsSesInfo *ses, SESSION_SETUP_ANDX *pSMB) | ||
| 32 | { | ||
| 33 | __u32 capabilities = 0; | ||
| 34 | |||
| 35 | /* init fields common to all four types of SessSetup */ | ||
| 36 | /* note that header is initialized to zero in header_assemble */ | ||
| 37 | pSMB->req.AndXCommand = 0xFF; | ||
| 38 | pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf); | ||
| 39 | pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq); | ||
| 40 | |||
| 41 | /* Now no need to set SMBFLG_CASELESS or obsolete CANONICAL PATH */ | ||
| 42 | |||
| 43 | /* BB verify whether signing required on neg or just on auth frame | ||
| 44 | (and NTLM case) */ | ||
| 45 | |||
| 46 | capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS | | ||
| 47 | CAP_LARGE_WRITE_X | CAP_LARGE_READ_X; | ||
| 48 | |||
| 49 | if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) | ||
| 50 | pSMB->req.hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE; | ||
| 51 | |||
| 52 | if (ses->capabilities & CAP_UNICODE) { | ||
| 53 | pSMB->req.hdr.Flags2 |= SMBFLG2_UNICODE; | ||
| 54 | capabilities |= CAP_UNICODE; | ||
| 55 | } | ||
| 56 | if (ses->capabilities & CAP_STATUS32) { | ||
| 57 | pSMB->req.hdr.Flags2 |= SMBFLG2_ERR_STATUS; | ||
| 58 | capabilities |= CAP_STATUS32; | ||
| 59 | } | ||
| 60 | if (ses->capabilities & CAP_DFS) { | ||
| 61 | pSMB->req.hdr.Flags2 |= SMBFLG2_DFS; | ||
| 62 | capabilities |= CAP_DFS; | ||
| 63 | } | ||
| 64 | |||
| 65 | /* BB check whether to init vcnum BB */ | ||
| 66 | return capabilities; | ||
| 67 | } | ||
| 68 | int | ||
| 69 | CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, const int type, | ||
| 70 | int * pNTLMv2_flg, const struct nls_table *nls_cp) | ||
| 71 | { | ||
| 72 | int rc = 0; | ||
| 73 | int wct; | ||
| 74 | struct smb_hdr *smb_buffer; | ||
| 75 | char *bcc_ptr; | ||
| 76 | SESSION_SETUP_ANDX *pSMB; | ||
| 77 | __u32 capabilities; | ||
| 78 | |||
| 79 | if(ses == NULL) | ||
| 80 | return -EINVAL; | ||
| 81 | |||
| 82 | cFYI(1,("SStp type: %d",type)); | ||
| 83 | if(type < CIFS_NTLM) { | ||
| 84 | #ifndef CONFIG_CIFS_WEAK_PW_HASH | ||
| 85 | /* LANMAN and plaintext are less secure and off by default. | ||
| 86 | So we make this explicitly be turned on in kconfig (in the | ||
| 87 | build) and turned on at runtime (changed from the default) | ||
| 88 | in proc/fs/cifs or via mount parm. Unfortunately this is | ||
| 89 | needed for old Win (e.g. Win95), some obscure NAS and OS/2 */ | ||
| 90 | return -EOPNOTSUPP; | ||
| 91 | #endif | ||
| 92 | wct = 10; /* lanman 2 style sessionsetup */ | ||
| 93 | } else if(type < CIFS_NTLMSSP_NEG) | ||
| 94 | wct = 13; /* old style NTLM sessionsetup */ | ||
| 95 | else /* same size for negotiate or auth, NTLMSSP or extended security */ | ||
| 96 | wct = 12; | ||
| 97 | |||
| 98 | rc = small_smb_init_no_tc(SMB_COM_SESSION_SETUP_ANDX, wct, ses, | ||
| 99 | (void **)&smb_buffer); | ||
| 100 | if(rc) | ||
| 101 | return rc; | ||
| 102 | |||
| 103 | pSMB = (SESSION_SETUP_ANDX *)smb_buffer; | ||
| 104 | |||
| 105 | capabilities = cifs_ssetup_hdr(ses, pSMB); | ||
| 106 | bcc_ptr = pByteArea(smb_buffer); | ||
| 107 | if(type > CIFS_NTLM) { | ||
| 108 | pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; | ||
| 109 | capabilities |= CAP_EXTENDED_SECURITY; | ||
| 110 | pSMB->req.Capabilities = cpu_to_le32(capabilities); | ||
| 111 | /* BB set password lengths */ | ||
| 112 | } else if(type < CIFS_NTLM) /* lanman */ { | ||
| 113 | /* no capabilities flags in old lanman negotiation */ | ||
| 114 | /* pSMB->old_req.PasswordLength = */ /* BB fixme BB */ | ||
| 115 | } else /* type CIFS_NTLM */ { | ||
| 116 | pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities); | ||
| 117 | pSMB->req_no_secext.CaseInsensitivePasswordLength = | ||
| 118 | cpu_to_le16(CIFS_SESSION_KEY_SIZE); | ||
| 119 | pSMB->req_no_secext.CaseSensitivePasswordLength = | ||
| 120 | cpu_to_le16(CIFS_SESSION_KEY_SIZE); | ||
| 121 | } | ||
| 122 | |||
| 123 | |||
| 124 | /* rc = SendReceive2(xid, ses, iov, num_iovecs, &resp_buf_type, 0); */ | ||
| 125 | /* SMB request buf freed in SendReceive2 */ | ||
| 126 | |||
| 127 | return rc; | ||
| 128 | } | ||
| 129 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ | ||
diff --git a/fs/cifs/ntlmssp.h b/fs/cifs/ntlmssp.h index 803389b64a2c..d39b712a11c5 100644 --- a/fs/cifs/ntlmssp.h +++ b/fs/cifs/ntlmssp.h | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * fs/cifs/ntlmssp.h | 2 | * fs/cifs/ntlmssp.h |
| 3 | * | 3 | * |
| 4 | * Copyright (c) International Business Machines Corp., 2002 | 4 | * Copyright (c) International Business Machines Corp., 2002,2006 |
| 5 | * Author(s): Steve French (sfrench@us.ibm.com) | 5 | * Author(s): Steve French (sfrench@us.ibm.com) |
| 6 | * | 6 | * |
| 7 | * This library is free software; you can redistribute it and/or modify | 7 | * This library is free software; you can redistribute it and/or modify |
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index 288cc048d37f..405d4b7ec3ac 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c | |||
| @@ -604,7 +604,12 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon, | |||
| 604 | cifsFile->search_resume_name = NULL; | 604 | cifsFile->search_resume_name = NULL; |
| 605 | if(cifsFile->srch_inf.ntwrk_buf_start) { | 605 | if(cifsFile->srch_inf.ntwrk_buf_start) { |
| 606 | cFYI(1,("freeing SMB ff cache buf on search rewind")); | 606 | cFYI(1,("freeing SMB ff cache buf on search rewind")); |
| 607 | cifs_buf_release(cifsFile->srch_inf.ntwrk_buf_start); | 607 | if(cifsFile->srch_inf.smallBuf) |
| 608 | cifs_small_buf_release(cifsFile->srch_inf. | ||
| 609 | ntwrk_buf_start); | ||
| 610 | else | ||
| 611 | cifs_buf_release(cifsFile->srch_inf. | ||
| 612 | ntwrk_buf_start); | ||
| 608 | } | 613 | } |
| 609 | rc = initiate_cifs_search(xid,file); | 614 | rc = initiate_cifs_search(xid,file); |
| 610 | if(rc) { | 615 | if(rc) { |
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index b12cb8a7da7c..3da80409466c 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c | |||
| @@ -309,17 +309,16 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, | |||
| 309 | 309 | ||
| 310 | *pRespBufType = CIFS_NO_BUFFER; /* no response buf yet */ | 310 | *pRespBufType = CIFS_NO_BUFFER; /* no response buf yet */ |
| 311 | 311 | ||
| 312 | if (ses == NULL) { | 312 | if ((ses == NULL) || (ses->server == NULL)) { |
| 313 | cERROR(1,("Null smb session")); | 313 | cifs_small_buf_release(in_buf); |
| 314 | return -EIO; | 314 | cERROR(1,("Null session")); |
| 315 | } | ||
| 316 | if(ses->server == NULL) { | ||
| 317 | cERROR(1,("Null tcp session")); | ||
| 318 | return -EIO; | 315 | return -EIO; |
| 319 | } | 316 | } |
| 320 | 317 | ||
| 321 | if(ses->server->tcpStatus == CifsExiting) | 318 | if(ses->server->tcpStatus == CifsExiting) { |
| 319 | cifs_small_buf_release(in_buf); | ||
| 322 | return -ENOENT; | 320 | return -ENOENT; |
| 321 | } | ||
| 323 | 322 | ||
| 324 | /* Ensure that we do not send more than 50 overlapping requests | 323 | /* Ensure that we do not send more than 50 overlapping requests |
| 325 | to the same server. We may make this configurable later or | 324 | to the same server. We may make this configurable later or |
| @@ -346,6 +345,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, | |||
| 346 | } else { | 345 | } else { |
| 347 | if(ses->server->tcpStatus == CifsExiting) { | 346 | if(ses->server->tcpStatus == CifsExiting) { |
| 348 | spin_unlock(&GlobalMid_Lock); | 347 | spin_unlock(&GlobalMid_Lock); |
| 348 | cifs_small_buf_release(in_buf); | ||
| 349 | return -ENOENT; | 349 | return -ENOENT; |
| 350 | } | 350 | } |
| 351 | 351 | ||
| @@ -385,6 +385,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, | |||
| 385 | midQ = AllocMidQEntry(in_buf, ses); | 385 | midQ = AllocMidQEntry(in_buf, ses); |
| 386 | if (midQ == NULL) { | 386 | if (midQ == NULL) { |
| 387 | up(&ses->server->tcpSem); | 387 | up(&ses->server->tcpSem); |
| 388 | cifs_small_buf_release(in_buf); | ||
| 388 | /* If not lock req, update # of requests on wire to server */ | 389 | /* If not lock req, update # of requests on wire to server */ |
| 389 | if(long_op < 3) { | 390 | if(long_op < 3) { |
| 390 | atomic_dec(&ses->server->inFlight); | 391 | atomic_dec(&ses->server->inFlight); |
| @@ -408,14 +409,18 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, | |||
| 408 | if(rc < 0) { | 409 | if(rc < 0) { |
| 409 | DeleteMidQEntry(midQ); | 410 | DeleteMidQEntry(midQ); |
| 410 | up(&ses->server->tcpSem); | 411 | up(&ses->server->tcpSem); |
| 412 | cifs_small_buf_release(in_buf); | ||
| 411 | /* If not lock req, update # of requests on wire to server */ | 413 | /* If not lock req, update # of requests on wire to server */ |
| 412 | if(long_op < 3) { | 414 | if(long_op < 3) { |
| 413 | atomic_dec(&ses->server->inFlight); | 415 | atomic_dec(&ses->server->inFlight); |
| 414 | wake_up(&ses->server->request_q); | 416 | wake_up(&ses->server->request_q); |
| 415 | } | 417 | } |
| 416 | return rc; | 418 | return rc; |
| 417 | } else | 419 | } else { |
| 418 | up(&ses->server->tcpSem); | 420 | up(&ses->server->tcpSem); |
| 421 | cifs_small_buf_release(in_buf); | ||
| 422 | } | ||
| 423 | |||
| 419 | if (long_op == -1) | 424 | if (long_op == -1) |
| 420 | goto cifs_no_response_exit2; | 425 | goto cifs_no_response_exit2; |
| 421 | else if (long_op == 2) /* writes past end of file can take loong time */ | 426 | else if (long_op == 2) /* writes past end of file can take loong time */ |
| @@ -543,6 +548,7 @@ cifs_no_response_exit2: | |||
| 543 | 548 | ||
| 544 | out_unlock2: | 549 | out_unlock2: |
| 545 | up(&ses->server->tcpSem); | 550 | up(&ses->server->tcpSem); |
| 551 | cifs_small_buf_release(in_buf); | ||
| 546 | /* If not lock req, update # of requests on wire to server */ | 552 | /* If not lock req, update # of requests on wire to server */ |
| 547 | if(long_op < 3) { | 553 | if(long_op < 3) { |
| 548 | atomic_dec(&ses->server->inFlight); | 554 | atomic_dec(&ses->server->inFlight); |
