aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-19 15:00:58 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-19 15:00:58 -0400
commit2843483d2eb02ad104edbe8b2429fb6a39d25063 (patch)
tree7a63d1fa408ab50277666b2d73d2553ea4cfc7a7 /fs/cifs
parent26790656d7dc34206f78eeca0f4be5caede788ce (diff)
parenta761ac579b89bc1f00212a42401398108deba65c (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6: (51 commits) [CIFS] log better errors on failed mounts [CIFS] Return better error when server requires signing but client forbids [CIFS] fix typo [CIFS] acl support part 4 [CIFS] Fix minor problems noticed by scan [CIFS] fix bad handling of EAGAIN error on kernel_recvmsg in cifs_demultiplex_thread [CIFS] build break [CIFS] endian fixes [CIFS] endian fixes in new acl code [CIFS] Fix some endianness problems in new acl code [CIFS] missing #endif from a previous patch [CIFS] formatting fixes [CIFS] Break up unicode_sessetup string functions [CIFS] parse server_GUID in SPNEGO negProt response [CIFS] [CIFS] Fix endian conversion problem in posix mkdir [CIFS] fix build break when lanman not enabled [CIFS] remove two sparse warnings [CIFS] remove compile warnings when debug disabled [CIFS] CIFS ACL support part 3 ...
Diffstat (limited to 'fs/cifs')
-rw-r--r--fs/cifs/CHANGES21
-rw-r--r--fs/cifs/Makefile2
-rw-r--r--fs/cifs/asn1.c10
-rw-r--r--fs/cifs/cifs_debug.c28
-rw-r--r--fs/cifs/cifsacl.c333
-rw-r--r--fs/cifs/cifsacl.h64
-rw-r--r--fs/cifs/cifsencrypt.c5
-rw-r--r--fs/cifs/cifsfs.c38
-rw-r--r--fs/cifs/cifsfs.h11
-rw-r--r--fs/cifs/cifsglob.h31
-rw-r--r--fs/cifs/cifspdu.h20
-rw-r--r--fs/cifs/cifsproto.h8
-rw-r--r--fs/cifs/cifssmb.c158
-rw-r--r--fs/cifs/connect.c262
-rw-r--r--fs/cifs/dir.c9
-rw-r--r--fs/cifs/export.c1
-rw-r--r--fs/cifs/file.c86
-rw-r--r--fs/cifs/inode.c52
-rw-r--r--fs/cifs/link.c2
-rw-r--r--fs/cifs/misc.c1
-rw-r--r--fs/cifs/netmisc.c33
-rw-r--r--fs/cifs/readdir.c8
-rw-r--r--fs/cifs/sess.c103
-rw-r--r--fs/cifs/smberr.h5
-rw-r--r--fs/cifs/transport.c34
-rw-r--r--fs/cifs/xattr.c19
26 files changed, 961 insertions, 383 deletions
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index bed6215c0794..3d419163c3d3 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -1,3 +1,19 @@
1Version 1.51
2------------
3Fix memory leak in statfs when mounted to very old servers (e.g.
4Windows 9x). Add new feature "POSIX open" which allows servers
5which support the current POSIX Extensions to provide better semantics
6(e.g. delete for open files opened with posix open). Take into
7account umask on posix mkdir not just older style mkdir. Add
8ability to mount to IPC$ share (which allows CIFS named pipes to be
9opened, read and written as if they were files). When 1st tree
10connect fails (e.g. due to signing negotiation failure) fix
11leak that causes cifsd not to stop and rmmod to fail to cleanup
12cifs_request_buffers pool. Fix problem with POSIX Open/Mkdir on
13bigendian architectures. Fix possible memory corruption when
14EAGAIN returned on kern_recvmsg. Return better error if server
15requires packet signing but client has disabled it.
16
1Version 1.50 17Version 1.50
2------------ 18------------
3Fix NTLMv2 signing. NFS server mounted over cifs works (if cifs mount is 19Fix NTLMv2 signing. NFS server mounted over cifs works (if cifs mount is
@@ -6,7 +22,10 @@ done with "serverino" mount option). Add support for POSIX Unlink
6Samba supports newer POSIX CIFS Protocol Extensions). Add "nounix" 22Samba supports newer POSIX CIFS Protocol Extensions). Add "nounix"
7mount option to allow disabling the CIFS Unix Extensions for just 23mount option to allow disabling the CIFS Unix Extensions for just
8that mount. Fix hang on spinlock in find_writable_file (race when 24that mount. Fix hang on spinlock in find_writable_file (race when
9reopening file after session crash). 25reopening file after session crash). Byte range unlock request to
26windows server could unlock more bytes (on server copy of file)
27than intended if start of unlock request is well before start of
28a previous byte range lock that we issued.
10 29
11Version 1.49 30Version 1.49
12------------ 31------------
diff --git a/fs/cifs/Makefile b/fs/cifs/Makefile
index 6ecd9d6ba3f3..ff6ba8d823f0 100644
--- a/fs/cifs/Makefile
+++ b/fs/cifs/Makefile
@@ -3,4 +3,4 @@
3# 3#
4obj-$(CONFIG_CIFS) += cifs.o 4obj-$(CONFIG_CIFS) += cifs.o
5 5
6cifs-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 sess.o export.o 6cifs-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 sess.o export.o cifsacl.o
diff --git a/fs/cifs/asn1.c b/fs/cifs/asn1.c
index f50a88d58f78..2a01f3ef96a0 100644
--- a/fs/cifs/asn1.c
+++ b/fs/cifs/asn1.c
@@ -385,10 +385,9 @@ asn1_oid_decode(struct asn1_ctx *ctx,
385 unsigned long *optr; 385 unsigned long *optr;
386 386
387 size = eoc - ctx->pointer + 1; 387 size = eoc - ctx->pointer + 1;
388 *oid = kmalloc(size * sizeof (unsigned long), GFP_ATOMIC); 388 *oid = kmalloc(size * sizeof(unsigned long), GFP_ATOMIC);
389 if (*oid == NULL) { 389 if (*oid == NULL)
390 return 0; 390 return 0;
391 }
392 391
393 optr = *oid; 392 optr = *oid;
394 393
@@ -581,9 +580,8 @@ decode_negTokenInit(unsigned char *security_blob, int length,
581 return 0; 580 return 0;
582 } else if ((cls != ASN1_UNI) || (con != ASN1_CON) 581 } else if ((cls != ASN1_UNI) || (con != ASN1_CON)
583 || (tag != ASN1_SEQ)) { 582 || (tag != ASN1_SEQ)) {
584 cFYI(1, 583 cFYI(1, ("cls = %d con = %d tag = %d end = %p (%d)",
585 ("Exit 6 cls = %d con = %d tag = %d end = %p (%d)", 584 cls, con, tag, end, *end));
586 cls, con, tag, end, *end));
587 } 585 }
588 586
589 if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { 587 if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c
index 1bf8cf522ad6..73c4c419663c 100644
--- a/fs/cifs/cifs_debug.c
+++ b/fs/cifs/cifs_debug.c
@@ -209,13 +209,16 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
209 i++; 209 i++;
210 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList); 210 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
211 dev_type = le32_to_cpu(tcon->fsDevInfo.DeviceType); 211 dev_type = le32_to_cpu(tcon->fsDevInfo.DeviceType);
212 length = 212 length = sprintf(buf, "\n%d) %s Uses: %d ", i,
213 sprintf(buf, 213 tcon->treeName, atomic_read(&tcon->useCount));
214 "\n%d) %s Uses: %d Type: %s DevInfo: 0x%x " 214 buf += length;
215 "Attributes: 0x%x\nPathComponentMax: %d Status: %d", 215 if (tcon->nativeFileSystem) {
216 i, tcon->treeName, 216 length = sprintf(buf, "Type: %s ",
217 atomic_read(&tcon->useCount), 217 tcon->nativeFileSystem);
218 tcon->nativeFileSystem, 218 buf += length;
219 }
220 length = sprintf(buf, "DevInfo: 0x%x Attributes: 0x%x"
221 "\nPathComponentMax: %d Status: %d",
219 le32_to_cpu(tcon->fsDevInfo.DeviceCharacteristics), 222 le32_to_cpu(tcon->fsDevInfo.DeviceCharacteristics),
220 le32_to_cpu(tcon->fsAttrInfo.Attributes), 223 le32_to_cpu(tcon->fsAttrInfo.Attributes),
221 le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength), 224 le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength),
@@ -876,11 +879,16 @@ security_flags_write(struct file *file, const char __user *buffer,
876 if (count < 3) { 879 if (count < 3) {
877 /* single char or single char followed by null */ 880 /* single char or single char followed by null */
878 c = flags_string[0]; 881 c = flags_string[0];
879 if (c == '0' || c == 'n' || c == 'N') 882 if (c == '0' || c == 'n' || c == 'N') {
880 extended_security = CIFSSEC_DEF; /* default */ 883 extended_security = CIFSSEC_DEF; /* default */
881 else if (c == '1' || c == 'y' || c == 'Y') 884 return count;
885 } else if (c == '1' || c == 'y' || c == 'Y') {
882 extended_security = CIFSSEC_MAX; 886 extended_security = CIFSSEC_MAX;
883 return count; 887 return count;
888 } else if (!isdigit(c)) {
889 cERROR(1, ("invalid flag %c", c));
890 return -EINVAL;
891 }
884 } 892 }
885 /* else we have a number */ 893 /* else we have a number */
886 894
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c
new file mode 100644
index 000000000000..e8e56353f5a1
--- /dev/null
+++ b/fs/cifs/cifsacl.c
@@ -0,0 +1,333 @@
1/*
2 * fs/cifs/cifsacl.c
3 *
4 * Copyright (C) International Business Machines Corp., 2007
5 * Author(s): Steve French (sfrench@us.ibm.com)
6 *
7 * Contains the routines for mapping CIFS/NTFS ACLs
8 *
9 * This library is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as published
11 * by the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17 * the GNU Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23
24#include <linux/fs.h>
25#include "cifspdu.h"
26#include "cifsglob.h"
27#include "cifsacl.h"
28#include "cifsproto.h"
29#include "cifs_debug.h"
30
31
32#ifdef CONFIG_CIFS_EXPERIMENTAL
33
34static struct cifs_wksid wksidarr[NUM_WK_SIDS] = {
35 {{1, 0, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0} }, "null user"},
36 {{1, 1, {0, 0, 0, 0, 0, 1}, {0, 0, 0, 0, 0} }, "nobody"},
37 {{1, 1, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(11), 0, 0, 0, 0} }, "net-users"},
38 {{1, 1, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(18), 0, 0, 0, 0} }, "sys"},
39 {{1, 2, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(32), cpu_to_le32(544), 0, 0, 0} }, "root"},
40 {{1, 2, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(32), cpu_to_le32(545), 0, 0, 0} }, "users"},
41 {{1, 2, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(32), cpu_to_le32(546), 0, 0, 0} }, "guest"}
42};
43
44
45/* security id for everyone */
46static const struct cifs_sid sid_everyone =
47 {1, 1, {0, 0, 0, 0, 0, 0}, {} };
48/* group users */
49static const struct cifs_sid sid_user =
50 {1, 2 , {0, 0, 0, 0, 0, 5}, {} };
51
52
53int match_sid(struct cifs_sid *ctsid)
54{
55 int i, j;
56 int num_subauth, num_sat, num_saw;
57 struct cifs_sid *cwsid;
58
59 if (!ctsid)
60 return (-1);
61
62 for (i = 0; i < NUM_WK_SIDS; ++i) {
63 cwsid = &(wksidarr[i].cifssid);
64
65 /* compare the revision */
66 if (ctsid->revision != cwsid->revision)
67 continue;
68
69 /* compare all of the six auth values */
70 for (j = 0; j < 6; ++j) {
71 if (ctsid->authority[j] != cwsid->authority[j])
72 break;
73 }
74 if (j < 6)
75 continue; /* all of the auth values did not match */
76
77 /* compare all of the subauth values if any */
78 num_sat = ctsid->num_subauth;
79 num_saw = cwsid->num_subauth;
80 num_subauth = num_sat < num_saw ? num_sat : num_saw;
81 if (num_subauth) {
82 for (j = 0; j < num_subauth; ++j) {
83 if (ctsid->sub_auth[j] != cwsid->sub_auth[j])
84 break;
85 }
86 if (j < num_subauth)
87 continue; /* all sub_auth values do not match */
88 }
89
90 cFYI(1, ("matching sid: %s\n", wksidarr[i].sidname));
91 return (0); /* sids compare/match */
92 }
93
94 cFYI(1, ("No matching sid"));
95 return (-1);
96}
97
98/* if the two SIDs (roughly equivalent to a UUID for a user or group) are
99 the same returns 1, if they do not match returns 0 */
100int compare_sids(struct cifs_sid *ctsid, struct cifs_sid *cwsid)
101{
102 int i;
103 int num_subauth, num_sat, num_saw;
104
105 if ((!ctsid) || (!cwsid))
106 return (0);
107
108 /* compare the revision */
109 if (ctsid->revision != cwsid->revision)
110 return (0);
111
112 /* compare all of the six auth values */
113 for (i = 0; i < 6; ++i) {
114 if (ctsid->authority[i] != cwsid->authority[i])
115 return (0);
116 }
117
118 /* compare all of the subauth values if any */
119 num_sat = ctsid->num_subauth;
120 num_saw = cwsid->num_subauth;
121 num_subauth = num_sat < num_saw ? num_sat : num_saw;
122 if (num_subauth) {
123 for (i = 0; i < num_subauth; ++i) {
124 if (ctsid->sub_auth[i] != cwsid->sub_auth[i])
125 return (0);
126 }
127 }
128
129 return (1); /* sids compare/match */
130}
131
132
133static void parse_ace(struct cifs_ace *pace, char *end_of_acl)
134{
135 int num_subauth;
136
137 /* validate that we do not go past end of acl */
138
139 /* XXX this if statement can be removed
140 if (end_of_acl < (char *)pace + sizeof(struct cifs_ace)) {
141 cERROR(1, ("ACL too small to parse ACE"));
142 return;
143 } */
144
145 num_subauth = pace->num_subauth;
146 if (num_subauth) {
147#ifdef CONFIG_CIFS_DEBUG2
148 int i;
149 cFYI(1, ("ACE revision %d num_subauth %d",
150 pace->revision, pace->num_subauth));
151 for (i = 0; i < num_subauth; ++i) {
152 cFYI(1, ("ACE sub_auth[%d]: 0x%x", i,
153 le32_to_cpu(pace->sub_auth[i])));
154 }
155
156 /* BB add length check to make sure that we do not have huge
157 num auths and therefore go off the end */
158
159 cFYI(1, ("RID %d", le32_to_cpu(pace->sub_auth[num_subauth-1])));
160#endif
161 }
162
163 return;
164}
165
166static void parse_ntace(struct cifs_ntace *pntace, char *end_of_acl)
167{
168 /* validate that we do not go past end of acl */
169 if (end_of_acl < (char *)pntace + sizeof(struct cifs_ntace)) {
170 cERROR(1, ("ACL too small to parse NT ACE"));
171 return;
172 }
173
174#ifdef CONFIG_CIFS_DEBUG2
175 cFYI(1, ("NTACE type %d flags 0x%x size %d, access Req 0x%x",
176 pntace->type, pntace->flags, pntace->size,
177 pntace->access_req));
178#endif
179 return;
180}
181
182
183
184static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
185 struct cifs_sid *pownersid, struct cifs_sid *pgrpsid)
186{
187 int i;
188 int num_aces = 0;
189 int acl_size;
190 char *acl_base;
191 struct cifs_ntace **ppntace;
192 struct cifs_ace **ppace;
193
194 /* BB need to add parm so we can store the SID BB */
195
196 /* validate that we do not go past end of acl */
197 if (end_of_acl < (char *)pdacl + le16_to_cpu(pdacl->size)) {
198 cERROR(1, ("ACL too small to parse DACL"));
199 return;
200 }
201
202#ifdef CONFIG_CIFS_DEBUG2
203 cFYI(1, ("DACL revision %d size %d num aces %d",
204 le16_to_cpu(pdacl->revision), le16_to_cpu(pdacl->size),
205 le32_to_cpu(pdacl->num_aces)));
206#endif
207
208 acl_base = (char *)pdacl;
209 acl_size = sizeof(struct cifs_acl);
210
211 num_aces = le32_to_cpu(pdacl->num_aces);
212 if (num_aces > 0) {
213 ppntace = kmalloc(num_aces * sizeof(struct cifs_ntace *),
214 GFP_KERNEL);
215 ppace = kmalloc(num_aces * sizeof(struct cifs_ace *),
216 GFP_KERNEL);
217
218/* cifscred->cecount = pdacl->num_aces;
219 cifscred->ntaces = kmalloc(num_aces *
220 sizeof(struct cifs_ntace *), GFP_KERNEL);
221 cifscred->aces = kmalloc(num_aces *
222 sizeof(struct cifs_ace *), GFP_KERNEL);*/
223
224 for (i = 0; i < num_aces; ++i) {
225 ppntace[i] = (struct cifs_ntace *)
226 (acl_base + acl_size);
227 ppace[i] = (struct cifs_ace *) ((char *)ppntace[i] +
228 sizeof(struct cifs_ntace));
229
230 parse_ntace(ppntace[i], end_of_acl);
231 if (end_of_acl < ((char *)ppace[i] +
232 (le16_to_cpu(ppntace[i]->size) -
233 sizeof(struct cifs_ntace)))) {
234 cERROR(1, ("ACL too small to parse ACE"));
235 break;
236 } else
237 parse_ace(ppace[i], end_of_acl);
238
239/* memcpy((void *)(&(cifscred->ntaces[i])),
240 (void *)ppntace[i],
241 sizeof(struct cifs_ntace));
242 memcpy((void *)(&(cifscred->aces[i])),
243 (void *)ppace[i],
244 sizeof(struct cifs_ace)); */
245
246 acl_base = (char *)ppntace[i];
247 acl_size = le16_to_cpu(ppntace[i]->size);
248 }
249
250 kfree(ppace);
251 kfree(ppntace);
252 }
253
254 return;
255}
256
257
258static int parse_sid(struct cifs_sid *psid, char *end_of_acl)
259{
260
261 /* BB need to add parm so we can store the SID BB */
262
263 /* validate that we do not go past end of acl */
264 if (end_of_acl < (char *)psid + sizeof(struct cifs_sid)) {
265 cERROR(1, ("ACL too small to parse SID"));
266 return -EINVAL;
267 }
268
269 if (psid->num_subauth) {
270#ifdef CONFIG_CIFS_DEBUG2
271 int i;
272 cFYI(1, ("SID revision %d num_auth %d First subauth 0x%x",
273 psid->revision, psid->num_subauth, psid->sub_auth[0]));
274
275 for (i = 0; i < psid->num_subauth; i++) {
276 cFYI(1, ("SID sub_auth[%d]: 0x%x ", i,
277 le32_to_cpu(psid->sub_auth[i])));
278 }
279
280 /* BB add length check to make sure that we do not have huge
281 num auths and therefore go off the end */
282 cFYI(1, ("RID 0x%x",
283 le32_to_cpu(psid->sub_auth[psid->num_subauth-1])));
284#endif
285 }
286
287 return 0;
288}
289
290
291/* Convert CIFS ACL to POSIX form */
292int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len)
293{
294 int rc;
295 struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
296 struct cifs_acl *dacl_ptr; /* no need for SACL ptr */
297 char *end_of_acl = ((char *)pntsd) + acl_len;
298
299 owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
300 le32_to_cpu(pntsd->osidoffset));
301 group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
302 le32_to_cpu(pntsd->gsidoffset));
303 dacl_ptr = (struct cifs_acl *)((char *)pntsd +
304 le32_to_cpu(pntsd->dacloffset));
305#ifdef CONFIG_CIFS_DEBUG2
306 cFYI(1, ("revision %d type 0x%x ooffset 0x%x goffset 0x%x "
307 "sacloffset 0x%x dacloffset 0x%x",
308 pntsd->revision, pntsd->type, le32_to_cpu(pntsd->osidoffset),
309 le32_to_cpu(pntsd->gsidoffset),
310 le32_to_cpu(pntsd->sacloffset),
311 le32_to_cpu(pntsd->dacloffset)));
312#endif
313 rc = parse_sid(owner_sid_ptr, end_of_acl);
314 if (rc)
315 return rc;
316
317 rc = parse_sid(group_sid_ptr, end_of_acl);
318 if (rc)
319 return rc;
320
321 parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr, group_sid_ptr);
322
323/* cifscred->uid = owner_sid_ptr->rid;
324 cifscred->gid = group_sid_ptr->rid;
325 memcpy((void *)(&(cifscred->osid)), (void *)owner_sid_ptr,
326 sizeof (struct cifs_sid));
327 memcpy((void *)(&(cifscred->gsid)), (void *)group_sid_ptr,
328 sizeof (struct cifs_sid)); */
329
330
331 return (0);
332}
333#endif /* CONFIG_CIFS_EXPERIMENTAL */
diff --git a/fs/cifs/cifsacl.h b/fs/cifs/cifsacl.h
index 5eff35d6e564..420f87813647 100644
--- a/fs/cifs/cifsacl.h
+++ b/fs/cifs/cifsacl.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * fs/cifs/cifsacl.h 2 * fs/cifs/cifsacl.h
3 * 3 *
4 * Copyright (c) International Business Machines Corp., 2005 4 * Copyright (c) International Business Machines Corp., 2007
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
@@ -22,17 +22,65 @@
22#ifndef _CIFSACL_H 22#ifndef _CIFSACL_H
23#define _CIFSACL_H 23#define _CIFSACL_H
24 24
25
26#define NUM_AUTHS 6 /* number of authority fields */
27#define NUM_SUBAUTHS 5 /* number of sub authority fields */
28#define NUM_WK_SIDS 7 /* number of well known sids */
29#define SIDNAMELENGTH 20 /* long enough for the ones we care about */
30
31#define READ_BIT 0x4
32#define WRITE_BIT 0x2
33#define EXEC_BIT 0x1
34
35#define UBITSHIFT 6
36#define GBITSHIFT 3
37
38struct cifs_ntsd {
39 __le16 revision; /* revision level */
40 __le16 type;
41 __le32 osidoffset;
42 __le32 gsidoffset;
43 __le32 sacloffset;
44 __le32 dacloffset;
45} __attribute__((packed));
46
25struct cifs_sid { 47struct cifs_sid {
26 __u8 revision; /* revision level */ 48 __u8 revision; /* revision level */
27 __u8 num_subauths; 49 __u8 num_subauth;
50 __u8 authority[6];
51 __le32 sub_auth[5]; /* sub_auth[num_subauth] */ /* BB FIXME endianness BB */
52} __attribute__((packed));
53
54struct cifs_acl {
55 __le16 revision; /* revision level */
56 __le16 size;
57 __le32 num_aces;
58} __attribute__((packed));
59
60struct cifs_ntace { /* first part of ACE which contains perms */
61 __u8 type;
62 __u8 flags;
63 __le16 size;
64 __le32 access_req;
65} __attribute__((packed));
66
67struct cifs_ace { /* last part of ACE which includes user info */
68 __u8 revision; /* revision level */
69 __u8 num_subauth;
28 __u8 authority[6]; 70 __u8 authority[6];
29 __u32 sub_auth[4]; 71 __le32 sub_auth[5];
30 /* next sub_auth if any ... */
31} __attribute__((packed)); 72} __attribute__((packed));
32 73
33/* everyone */ 74struct cifs_wksid {
34/* extern const struct cifs_sid sid_everyone;*/ 75 struct cifs_sid cifssid;
35/* group users */ 76 char sidname[SIDNAMELENGTH];
36/* extern const struct cifs_sid sid_user;*/ 77} __attribute__((packed));
78
79#ifdef CONFIG_CIFS_EXPERIMENTAL
80
81extern int match_sid(struct cifs_sid *);
82extern int compare_sids(struct cifs_sid *, struct cifs_sid *);
83
84#endif /* CONFIG_CIFS_EXPERIMENTAL */
37 85
38#endif /* _CIFSACL_H */ 86#endif /* _CIFSACL_H */
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index 36272293027d..632070b4275d 100644
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -345,7 +345,7 @@ static int calc_ntlmv2_hash(struct cifsSesInfo *ses,
345 user = kmalloc(2 + (len * 2), GFP_KERNEL); 345 user = kmalloc(2 + (len * 2), GFP_KERNEL);
346 if (user == NULL) 346 if (user == NULL)
347 goto calc_exit_2; 347 goto calc_exit_2;
348 len = cifs_strtoUCS(user, ses->userName, len, nls_cp); 348 len = cifs_strtoUCS((__le16 *)user, ses->userName, len, nls_cp);
349 UniStrupr(user); 349 UniStrupr(user);
350 hmac_md5_update((char *)user, 2*len, pctxt); 350 hmac_md5_update((char *)user, 2*len, pctxt);
351 351
@@ -356,7 +356,8 @@ static int calc_ntlmv2_hash(struct cifsSesInfo *ses,
356 domain = kmalloc(2 + (len * 2), GFP_KERNEL); 356 domain = kmalloc(2 + (len * 2), GFP_KERNEL);
357 if (domain == NULL) 357 if (domain == NULL)
358 goto calc_exit_1; 358 goto calc_exit_1;
359 len = cifs_strtoUCS(domain, ses->domainName, len, nls_cp); 359 len = cifs_strtoUCS((__le16 *)domain, ses->domainName, len,
360 nls_cp);
360 /* the following line was removed since it didn't work well 361 /* the following line was removed since it didn't work well
361 with lower cased domain name that passed as an option. 362 with lower cased domain name that passed as an option.
362 Maybe converting the domain name earlier makes sense */ 363 Maybe converting the domain name earlier makes sense */
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index ba8f7868cb23..a6fbea57c4b1 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -49,10 +49,6 @@
49static struct quotactl_ops cifs_quotactl_ops; 49static struct quotactl_ops cifs_quotactl_ops;
50#endif /* QUOTA */ 50#endif /* QUOTA */
51 51
52#ifdef CONFIG_CIFS_EXPERIMENTAL
53extern struct export_operations cifs_export_ops;
54#endif /* EXPERIMENTAL */
55
56int cifsFYI = 0; 52int cifsFYI = 0;
57int cifsERROR = 1; 53int cifsERROR = 1;
58int traceSMB = 0; 54int traceSMB = 0;
@@ -240,9 +236,9 @@ static int cifs_permission(struct inode *inode, int mask, struct nameidata *nd)
240 236
241 cifs_sb = CIFS_SB(inode->i_sb); 237 cifs_sb = CIFS_SB(inode->i_sb);
242 238
243 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) { 239 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
244 return 0; 240 return 0;
245 } else /* file mode might have been restricted at mount time 241 else /* file mode might have been restricted at mount time
246 on the client (above and beyond ACL on servers) for 242 on the client (above and beyond ACL on servers) for
247 servers which do not support setting and viewing mode bits, 243 servers which do not support setting and viewing mode bits,
248 so allowing client to check permissions is useful */ 244 so allowing client to check permissions is useful */
@@ -312,15 +308,15 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m)
312 seq_printf(s, ",domain=%s", 308 seq_printf(s, ",domain=%s",
313 cifs_sb->tcon->ses->domainName); 309 cifs_sb->tcon->ses->domainName);
314 } 310 }
311 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) ||
312 !(cifs_sb->tcon->unix_ext))
313 seq_printf(s, ",uid=%d", cifs_sb->mnt_uid);
314 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) ||
315 !(cifs_sb->tcon->unix_ext))
316 seq_printf(s, ",gid=%d", cifs_sb->mnt_gid);
315 } 317 }
316 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) 318 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)
317 seq_printf(s, ",posixpaths"); 319 seq_printf(s, ",posixpaths");
318 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) ||
319 !(cifs_sb->tcon->unix_ext))
320 seq_printf(s, ",uid=%d", cifs_sb->mnt_uid);
321 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) ||
322 !(cifs_sb->tcon->unix_ext))
323 seq_printf(s, ",gid=%d", cifs_sb->mnt_gid);
324 seq_printf(s, ",rsize=%d", cifs_sb->rsize); 320 seq_printf(s, ",rsize=%d", cifs_sb->rsize);
325 seq_printf(s, ",wsize=%d", cifs_sb->wsize); 321 seq_printf(s, ",wsize=%d", cifs_sb->wsize);
326 } 322 }
@@ -346,7 +342,7 @@ int cifs_xquota_set(struct super_block *sb, int quota_type, qid_t qid,
346 if (pTcon) { 342 if (pTcon) {
347 cFYI(1, ("set type: 0x%x id: %d", quota_type, qid)); 343 cFYI(1, ("set type: 0x%x id: %d", quota_type, qid));
348 } else { 344 } else {
349 return -EIO; 345 rc = -EIO;
350 } 346 }
351 347
352 FreeXid(xid); 348 FreeXid(xid);
@@ -716,7 +712,7 @@ static int
716cifs_init_inodecache(void) 712cifs_init_inodecache(void)
717{ 713{
718 cifs_inode_cachep = kmem_cache_create("cifs_inode_cache", 714 cifs_inode_cachep = kmem_cache_create("cifs_inode_cache",
719 sizeof (struct cifsInodeInfo), 715 sizeof(struct cifsInodeInfo),
720 0, (SLAB_RECLAIM_ACCOUNT| 716 0, (SLAB_RECLAIM_ACCOUNT|
721 SLAB_MEM_SPREAD), 717 SLAB_MEM_SPREAD),
722 cifs_init_once); 718 cifs_init_once);
@@ -816,8 +812,8 @@ static int
816cifs_init_mids(void) 812cifs_init_mids(void)
817{ 813{
818 cifs_mid_cachep = kmem_cache_create("cifs_mpx_ids", 814 cifs_mid_cachep = kmem_cache_create("cifs_mpx_ids",
819 sizeof (struct mid_q_entry), 0, 815 sizeof(struct mid_q_entry), 0,
820 SLAB_HWCACHE_ALIGN, NULL); 816 SLAB_HWCACHE_ALIGN, NULL);
821 if (cifs_mid_cachep == NULL) 817 if (cifs_mid_cachep == NULL)
822 return -ENOMEM; 818 return -ENOMEM;
823 819
@@ -829,8 +825,8 @@ cifs_init_mids(void)
829 } 825 }
830 826
831 cifs_oplock_cachep = kmem_cache_create("cifs_oplock_structs", 827 cifs_oplock_cachep = kmem_cache_create("cifs_oplock_structs",
832 sizeof (struct oplock_q_entry), 0, 828 sizeof(struct oplock_q_entry), 0,
833 SLAB_HWCACHE_ALIGN, NULL); 829 SLAB_HWCACHE_ALIGN, NULL);
834 if (cifs_oplock_cachep == NULL) { 830 if (cifs_oplock_cachep == NULL) {
835 mempool_destroy(cifs_mid_poolp); 831 mempool_destroy(cifs_mid_poolp);
836 kmem_cache_destroy(cifs_mid_cachep); 832 kmem_cache_destroy(cifs_mid_cachep);
@@ -882,7 +878,8 @@ static int cifs_oplock_thread(void *dummyarg)
882 the call */ 878 the call */
883 /* mutex_lock(&inode->i_mutex);*/ 879 /* mutex_lock(&inode->i_mutex);*/
884 if (S_ISREG(inode->i_mode)) { 880 if (S_ISREG(inode->i_mode)) {
885 rc = filemap_fdatawrite(inode->i_mapping); 881 rc =
882 filemap_fdatawrite(inode->i_mapping);
886 if (CIFS_I(inode)->clientCanCacheRead 883 if (CIFS_I(inode)->clientCanCacheRead
887 == 0) { 884 == 0) {
888 filemap_fdatawait(inode->i_mapping); 885 filemap_fdatawait(inode->i_mapping);
@@ -907,8 +904,7 @@ static int cifs_oplock_thread(void *dummyarg)
907 0 /* len */ , 0 /* offset */, 0, 904 0 /* len */ , 0 /* offset */, 0,
908 0, LOCKING_ANDX_OPLOCK_RELEASE, 905 0, LOCKING_ANDX_OPLOCK_RELEASE,
909 0 /* wait flag */); 906 0 /* wait flag */);
910 cFYI(1, 907 cFYI(1, ("Oplock release rc = %d", rc));
911 ("Oplock release rc = %d ", rc));
912 } 908 }
913 } else 909 } else
914 spin_unlock(&GlobalMid_Lock); 910 spin_unlock(&GlobalMid_Lock);
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index a20de77a3856..0a3ee5a322b0 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * fs/cifs/cifsfs.h 2 * fs/cifs/cifsfs.h
3 * 3 *
4 * Copyright (c) International Business Machines Corp., 2002, 2005 4 * Copyright (c) International Business Machines Corp., 2002, 2007
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
@@ -99,7 +99,12 @@ extern int cifs_setxattr(struct dentry *, const char *, const void *,
99 size_t, int); 99 size_t, int);
100extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t); 100extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t);
101extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); 101extern ssize_t cifs_listxattr(struct dentry *, char *, size_t);
102extern int cifs_ioctl (struct inode *inode, struct file *filep, 102extern int cifs_ioctl(struct inode *inode, struct file *filep,
103 unsigned int command, unsigned long arg); 103 unsigned int command, unsigned long arg);
104#define CIFS_VERSION "1.50" 104
105#ifdef CONFIG_CIFS_EXPERIMENTAL
106extern struct export_operations cifs_export_ops;
107#endif /* EXPERIMENTAL */
108
109#define CIFS_VERSION "1.51"
105#endif /* _CIFSFS_H */ 110#endif /* _CIFSFS_H */
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index b98742fc3b5a..87f51f23276f 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -19,6 +19,7 @@
19#include <linux/in.h> 19#include <linux/in.h>
20#include <linux/in6.h> 20#include <linux/in6.h>
21#include "cifs_fs_sb.h" 21#include "cifs_fs_sb.h"
22#include "cifsacl.h"
22/* 23/*
23 * The sizes of various internal tables and strings 24 * The sizes of various internal tables and strings
24 */ 25 */
@@ -89,7 +90,8 @@ enum statusEnum {
89}; 90};
90 91
91enum securityEnum { 92enum securityEnum {
92 LANMAN = 0, /* Legacy LANMAN auth */ 93 PLAINTXT = 0, /* Legacy with Plaintext passwords */
94 LANMAN, /* Legacy LANMAN auth */
93 NTLM, /* Legacy NTLM012 auth with NTLM hash */ 95 NTLM, /* Legacy NTLM012 auth with NTLM hash */
94 NTLMv2, /* Legacy NTLM auth with NTLMv2 hash */ 96 NTLMv2, /* Legacy NTLM auth with NTLMv2 hash */
95 RawNTLMSSP, /* NTLMSSP without SPNEGO */ 97 RawNTLMSSP, /* NTLMSSP without SPNEGO */
@@ -115,6 +117,17 @@ struct mac_key {
115 } data; 117 } data;
116}; 118};
117 119
120struct cifs_cred {
121 int uid;
122 int gid;
123 int mode;
124 int cecount;
125 struct cifs_sid osid;
126 struct cifs_sid gsid;
127 struct cifs_ntace *ntaces;
128 struct cifs_ace *aces;
129};
130
118/* 131/*
119 ***************************************************************** 132 *****************************************************************
120 * Except the CIFS PDUs themselves all the 133 * Except the CIFS PDUs themselves all the
@@ -279,6 +292,7 @@ struct cifsTconInfo {
279 FILE_SYSTEM_DEVICE_INFO fsDevInfo; 292 FILE_SYSTEM_DEVICE_INFO fsDevInfo;
280 FILE_SYSTEM_ATTRIBUTE_INFO fsAttrInfo; /* ok if fs name truncated */ 293 FILE_SYSTEM_ATTRIBUTE_INFO fsAttrInfo; /* ok if fs name truncated */
281 FILE_SYSTEM_UNIX_INFO fsUnixInfo; 294 FILE_SYSTEM_UNIX_INFO fsUnixInfo;
295 unsigned ipc:1; /* set if connection to IPC$ eg for RPC/PIPES */
282 unsigned retry:1; 296 unsigned retry:1;
283 unsigned nocase:1; 297 unsigned nocase:1;
284 unsigned unix_ext:1; /* if off disable Linux extensions to CIFS protocol 298 unsigned unix_ext:1; /* if off disable Linux extensions to CIFS protocol
@@ -329,6 +343,7 @@ struct cifsFileInfo {
329 struct list_head llist; /* list of byte range locks we have. */ 343 struct list_head llist; /* list of byte range locks we have. */
330 unsigned closePend:1; /* file is marked to close */ 344 unsigned closePend:1; /* file is marked to close */
331 unsigned invalidHandle:1; /* file closed via session abend */ 345 unsigned invalidHandle:1; /* file closed via session abend */
346 unsigned messageMode:1; /* for pipes: message vs byte mode */
332 atomic_t wrtPending; /* handle in use - defer close */ 347 atomic_t wrtPending; /* handle in use - defer close */
333 struct semaphore fh_sem; /* prevents reopen race after dead ses*/ 348 struct semaphore fh_sem; /* prevents reopen race after dead ses*/
334 char *search_resume_name; /* BB removeme BB */ 349 char *search_resume_name; /* BB removeme BB */
@@ -464,6 +479,9 @@ struct dir_notify_req {
464#ifdef CONFIG_CIFS_WEAK_PW_HASH 479#ifdef CONFIG_CIFS_WEAK_PW_HASH
465#define CIFSSEC_MAY_LANMAN 0x00010 480#define CIFSSEC_MAY_LANMAN 0x00010
466#define CIFSSEC_MAY_PLNTXT 0x00020 481#define CIFSSEC_MAY_PLNTXT 0x00020
482#else
483#define CIFSSEC_MAY_LANMAN 0
484#define CIFSSEC_MAY_PLNTXT 0
467#endif /* weak passwords */ 485#endif /* weak passwords */
468#define CIFSSEC_MAY_SEAL 0x00040 /* not supported yet */ 486#define CIFSSEC_MAY_SEAL 0x00040 /* not supported yet */
469 487
@@ -477,14 +495,23 @@ require use of the stronger protocol */
477#ifdef CONFIG_CIFS_WEAK_PW_HASH 495#ifdef CONFIG_CIFS_WEAK_PW_HASH
478#define CIFSSEC_MUST_LANMAN 0x10010 496#define CIFSSEC_MUST_LANMAN 0x10010
479#define CIFSSEC_MUST_PLNTXT 0x20020 497#define CIFSSEC_MUST_PLNTXT 0x20020
498#ifdef CONFIG_CIFS_UPCALL
499#define CIFSSEC_MASK 0x3F03F /* allows weak security but also krb5 */
500#else
480#define CIFSSEC_MASK 0x37037 /* current flags supported if weak */ 501#define CIFSSEC_MASK 0x37037 /* current flags supported if weak */
502#endif /* UPCALL */
503#else /* do not allow weak pw hash */
504#ifdef CONFIG_CIFS_UPCALL
505#define CIFSSEC_MASK 0x0F00F /* flags supported if no weak allowed */
481#else 506#else
482#define CIFSSEC_MASK 0x07007 /* flags supported if no weak config */ 507#define CIFSSEC_MASK 0x07007 /* flags supported if no weak allowed */
508#endif /* UPCALL */
483#endif /* WEAK_PW_HASH */ 509#endif /* WEAK_PW_HASH */
484#define CIFSSEC_MUST_SEAL 0x40040 /* not supported yet */ 510#define CIFSSEC_MUST_SEAL 0x40040 /* not supported yet */
485 511
486#define CIFSSEC_DEF CIFSSEC_MAY_SIGN | CIFSSEC_MAY_NTLM | CIFSSEC_MAY_NTLMV2 512#define CIFSSEC_DEF CIFSSEC_MAY_SIGN | CIFSSEC_MAY_NTLM | CIFSSEC_MAY_NTLMV2
487#define CIFSSEC_MAX CIFSSEC_MUST_SIGN | CIFSSEC_MUST_NTLMV2 513#define CIFSSEC_MAX CIFSSEC_MUST_SIGN | CIFSSEC_MUST_NTLMV2
514#define CIFSSEC_AUTH_MASK (CIFSSEC_MAY_NTLM | CIFSSEC_MAY_NTLMV2 | CIFSSEC_MAY_LANMAN | CIFSSEC_MAY_PLNTXT | CIFSSEC_MAY_KRB5)
488/* 515/*
489 ***************************************************************** 516 *****************************************************************
490 * All constants go here 517 * All constants go here
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
index 6a2056e58ceb..c41ff74e9128 100644
--- a/fs/cifs/cifspdu.h
+++ b/fs/cifs/cifspdu.h
@@ -215,6 +215,12 @@
215 /* file_execute, file_read_attributes*/ 215 /* file_execute, file_read_attributes*/
216 /* write_dac, and delete. */ 216 /* write_dac, and delete. */
217 217
218#define FILE_READ_RIGHTS (FILE_READ_DATA | FILE_READ_EA | FILE_READ_ATTRIBUTES)
219#define FILE_WRITE_RIGHTS (FILE_WRITE_DATA | FILE_APPEND_DATA \
220 | FILE_WRITE_EA | FILE_WRITE_ATTRIBUTES)
221#define FILE_EXEC_RIGHTS (FILE_EXECUTE)
222
223
218/* 224/*
219 * Invalid readdir handle 225 * Invalid readdir handle
220 */ 226 */
@@ -360,10 +366,10 @@ struct smb_hdr {
360 __u8 WordCount; 366 __u8 WordCount;
361} __attribute__((packed)); 367} __attribute__((packed));
362/* given a pointer to an smb_hdr retrieve the value of byte count */ 368/* given a pointer to an smb_hdr retrieve the value of byte count */
363#define BCC(smb_var) ( *(__u16 *)((char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) ) ) 369#define BCC(smb_var) ( *(__u16 *)((char *)smb_var + sizeof(struct smb_hdr) + (2 * smb_var->WordCount)))
364#define BCC_LE(smb_var) ( *(__le16 *)((char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) ) ) 370#define BCC_LE(smb_var) ( *(__le16 *)((char *)smb_var + sizeof(struct smb_hdr) + (2 * smb_var->WordCount)))
365/* given a pointer to an smb_hdr retrieve the pointer to the byte area */ 371/* given a pointer to an smb_hdr retrieve the pointer to the byte area */
366#define pByteArea(smb_var) ((unsigned char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) + 2 ) 372#define pByteArea(smb_var) ((unsigned char *)smb_var + sizeof(struct smb_hdr) + (2 * smb_var->WordCount) + 2)
367 373
368/* 374/*
369 * Computer Name Length (since Netbios name was length 16 with last byte 0x20) 375 * Computer Name Length (since Netbios name was length 16 with last byte 0x20)
@@ -716,6 +722,14 @@ typedef struct smb_com_findclose_req {
716#define REQ_OPENDIRONLY 0x00000008 722#define REQ_OPENDIRONLY 0x00000008
717#define REQ_EXTENDED_INFO 0x00000010 723#define REQ_EXTENDED_INFO 0x00000010
718 724
725/* File type */
726#define DISK_TYPE 0x0000
727#define BYTE_PIPE_TYPE 0x0001
728#define MESSAGE_PIPE_TYPE 0x0002
729#define PRINTER_TYPE 0x0003
730#define COMM_DEV_TYPE 0x0004
731#define UNKNOWN_TYPE 0xFFFF
732
719typedef struct smb_com_open_req { /* also handles create */ 733typedef struct smb_com_open_req { /* also handles create */
720 struct smb_hdr hdr; /* wct = 24 */ 734 struct smb_hdr hdr; /* wct = 24 */
721 __u8 AndXCommand; 735 __u8 AndXCommand;
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 04a69dafedba..1a883663b22d 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -50,7 +50,8 @@ extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *,
50 int * /* bytes returned */ , const int long_op); 50 int * /* bytes returned */ , const int long_op);
51extern int SendReceive2(const unsigned int /* xid */ , struct cifsSesInfo *, 51extern int SendReceive2(const unsigned int /* xid */ , struct cifsSesInfo *,
52 struct kvec *, int /* nvec to send */, 52 struct kvec *, int /* nvec to send */,
53 int * /* type of buf returned */ , const int long_op); 53 int * /* type of buf returned */ , const int long_op,
54 const int logError /* whether to log status code*/ );
54extern int SendReceiveBlockingLock(const unsigned int /* xid */ , 55extern int SendReceiveBlockingLock(const unsigned int /* xid */ ,
55 struct cifsTconInfo *, 56 struct cifsTconInfo *,
56 struct smb_hdr * /* input */ , 57 struct smb_hdr * /* input */ ,
@@ -65,7 +66,7 @@ extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr);
65extern int decode_negTokenInit(unsigned char *security_blob, int length, 66extern int decode_negTokenInit(unsigned char *security_blob, int length,
66 enum securityEnum *secType); 67 enum securityEnum *secType);
67extern int cifs_inet_pton(int, char *source, void *dst); 68extern int cifs_inet_pton(int, char *source, void *dst);
68extern int map_smb_to_linux_error(struct smb_hdr *smb); 69extern int map_smb_to_linux_error(struct smb_hdr *smb, int logErr);
69extern void header_assemble(struct smb_hdr *, char /* command */ , 70extern void header_assemble(struct smb_hdr *, char /* command */ ,
70 const struct cifsTconInfo *, int /* length of 71 const struct cifsTconInfo *, int /* length of
71 fixed section (word count) in two byte units */); 72 fixed section (word count) in two byte units */);
@@ -304,12 +305,13 @@ extern int cifs_calculate_mac_key(struct mac_key *key, const char *rn,
304 const char *pass); 305 const char *pass);
305extern int CalcNTLMv2_partial_mac_key(struct cifsSesInfo *, 306extern int CalcNTLMv2_partial_mac_key(struct cifsSesInfo *,
306 const struct nls_table *); 307 const struct nls_table *);
307extern void CalcNTLMv2_response(const struct cifsSesInfo *, char * ); 308extern void CalcNTLMv2_response(const struct cifsSesInfo *, char *);
308extern void setup_ntlmv2_rsp(struct cifsSesInfo *, char *, 309extern void setup_ntlmv2_rsp(struct cifsSesInfo *, char *,
309 const struct nls_table *); 310 const struct nls_table *);
310#ifdef CONFIG_CIFS_WEAK_PW_HASH 311#ifdef CONFIG_CIFS_WEAK_PW_HASH
311extern void calc_lanman_hash(struct cifsSesInfo *ses, char *lnm_session_key); 312extern void calc_lanman_hash(struct cifsSesInfo *ses, char *lnm_session_key);
312#endif /* CIFS_WEAK_PW_HASH */ 313#endif /* CIFS_WEAK_PW_HASH */
314extern int parse_sec_desc(struct cifs_ntsd *, int);
313extern int CIFSSMBCopy(int xid, 315extern int CIFSSMBCopy(int xid,
314 struct cifsTconInfo *source_tcon, 316 struct cifsTconInfo *source_tcon,
315 const char *fromName, 317 const char *fromName,
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 8eb102f940d4..f0d9a485d095 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -34,10 +34,10 @@
34#include <asm/uaccess.h> 34#include <asm/uaccess.h>
35#include "cifspdu.h" 35#include "cifspdu.h"
36#include "cifsglob.h" 36#include "cifsglob.h"
37#include "cifsacl.h"
37#include "cifsproto.h" 38#include "cifsproto.h"
38#include "cifs_unicode.h" 39#include "cifs_unicode.h"
39#include "cifs_debug.h" 40#include "cifs_debug.h"
40#include "cifsacl.h"
41 41
42#ifdef CONFIG_CIFS_POSIX 42#ifdef CONFIG_CIFS_POSIX
43static struct { 43static struct {
@@ -94,9 +94,8 @@ static void mark_open_files_invalid(struct cifsTconInfo *pTcon)
94 write_lock(&GlobalSMBSeslock); 94 write_lock(&GlobalSMBSeslock);
95 list_for_each_safe(tmp, tmp1, &pTcon->openFileList) { 95 list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
96 open_file = list_entry(tmp, struct cifsFileInfo, tlist); 96 open_file = list_entry(tmp, struct cifsFileInfo, tlist);
97 if (open_file) { 97 if (open_file)
98 open_file->invalidHandle = TRUE; 98 open_file->invalidHandle = TRUE;
99 }
100 } 99 }
101 write_unlock(&GlobalSMBSeslock); 100 write_unlock(&GlobalSMBSeslock);
102 /* BB Add call to invalidate_inodes(sb) for all superblocks mounted 101 /* BB Add call to invalidate_inodes(sb) for all superblocks mounted
@@ -439,8 +438,13 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
439 438
440 pSMB->hdr.Mid = GetNextMid(server); 439 pSMB->hdr.Mid = GetNextMid(server);
441 pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS); 440 pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
441
442 if ((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5) 442 if ((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
443 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC; 443 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
444 else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_KRB5) {
445 cFYI(1, ("Kerberos only mechanism, enable extended security"));
446 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
447 }
444 448
445 count = 0; 449 count = 0;
446 for (i = 0; i < CIFS_NUM_PROT; i++) { 450 for (i = 0; i < CIFS_NUM_PROT; i++) {
@@ -513,7 +517,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
513 (int)ts.tv_sec, (int)utc.tv_sec, 517 (int)ts.tv_sec, (int)utc.tv_sec,
514 (int)(utc.tv_sec - ts.tv_sec))); 518 (int)(utc.tv_sec - ts.tv_sec)));
515 val = (int)(utc.tv_sec - ts.tv_sec); 519 val = (int)(utc.tv_sec - ts.tv_sec);
516 seconds = val < 0 ? -val : val; 520 seconds = abs(val);
517 result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ; 521 result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ;
518 remain = seconds % MIN_TZ_ADJ; 522 remain = seconds % MIN_TZ_ADJ;
519 if (remain >= (MIN_TZ_ADJ / 2)) 523 if (remain >= (MIN_TZ_ADJ / 2))
@@ -574,7 +578,20 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
574 server->secType = NTLM; 578 server->secType = NTLM;
575 else if (secFlags & CIFSSEC_MAY_NTLMV2) 579 else if (secFlags & CIFSSEC_MAY_NTLMV2)
576 server->secType = NTLMv2; 580 server->secType = NTLMv2;
577 /* else krb5 ... any others ... */ 581 else if (secFlags & CIFSSEC_MAY_KRB5)
582 server->secType = Kerberos;
583 else if (secFlags & CIFSSEC_MAY_LANMAN)
584 server->secType = LANMAN;
585/* #ifdef CONFIG_CIFS_EXPERIMENTAL
586 else if (secFlags & CIFSSEC_MAY_PLNTXT)
587 server->secType = ??
588#endif */
589 else {
590 rc = -EOPNOTSUPP;
591 cERROR(1, ("Invalid security type"));
592 goto neg_err_exit;
593 }
594 /* else ... any others ...? */
578 595
579 /* one byte, so no need to convert this or EncryptionKeyLen from 596 /* one byte, so no need to convert this or EncryptionKeyLen from
580 little endian */ 597 little endian */
@@ -604,22 +621,26 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
604 if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) && 621 if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) &&
605 (server->capabilities & CAP_EXTENDED_SECURITY)) { 622 (server->capabilities & CAP_EXTENDED_SECURITY)) {
606 count = pSMBr->ByteCount; 623 count = pSMBr->ByteCount;
607 if (count < 16) 624 if (count < 16) {
608 rc = -EIO; 625 rc = -EIO;
609 else if (count == 16) { 626 goto neg_err_exit;
610 server->secType = RawNTLMSSP; 627 }
611 if (server->socketUseCount.counter > 1) { 628
612 if (memcmp(server->server_GUID, 629 if (server->socketUseCount.counter > 1) {
613 pSMBr->u.extended_response. 630 if (memcmp(server->server_GUID,
614 GUID, 16) != 0) { 631 pSMBr->u.extended_response.
615 cFYI(1, ("server UID changed")); 632 GUID, 16) != 0) {
616 memcpy(server->server_GUID, 633 cFYI(1, ("server UID changed"));
617 pSMBr->u.extended_response.GUID,
618 16);
619 }
620 } else
621 memcpy(server->server_GUID, 634 memcpy(server->server_GUID,
622 pSMBr->u.extended_response.GUID, 16); 635 pSMBr->u.extended_response.GUID,
636 16);
637 }
638 } else
639 memcpy(server->server_GUID,
640 pSMBr->u.extended_response.GUID, 16);
641
642 if (count == 16) {
643 server->secType = RawNTLMSSP;
623 } else { 644 } else {
624 rc = decode_negTokenInit(pSMBr->u.extended_response. 645 rc = decode_negTokenInit(pSMBr->u.extended_response.
625 SecurityBlob, 646 SecurityBlob,
@@ -642,10 +663,12 @@ signing_check:
642 /* MUST_SIGN already includes the MAY_SIGN FLAG 663 /* MUST_SIGN already includes the MAY_SIGN FLAG
643 so if this is zero it means that signing is disabled */ 664 so if this is zero it means that signing is disabled */
644 cFYI(1, ("Signing disabled")); 665 cFYI(1, ("Signing disabled"));
645 if (server->secMode & SECMODE_SIGN_REQUIRED) 666 if (server->secMode & SECMODE_SIGN_REQUIRED) {
646 cERROR(1, ("Server requires " 667 cERROR(1, ("Server requires "
647 "/proc/fs/cifs/PacketSigningEnabled " 668 "packet signing to be enabled in "
648 "to be on")); 669 "/proc/fs/cifs/SecurityFlags."));
670 rc = -EOPNOTSUPP;
671 }
649 server->secMode &= 672 server->secMode &=
650 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED); 673 ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
651 } else if ((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) { 674 } else if ((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) {
@@ -1052,7 +1075,7 @@ PsxCreat:
1052 InformationLevel) - 4; 1075 InformationLevel) - 4;
1053 offset = param_offset + params; 1076 offset = param_offset + params;
1054 pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset); 1077 pdata = (OPEN_PSX_REQ *)(((char *)&pSMB->hdr.Protocol) + offset);
1055 pdata->Level = SMB_QUERY_FILE_UNIX_BASIC; 1078 pdata->Level = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
1056 pdata->Permissions = cpu_to_le64(mode); 1079 pdata->Permissions = cpu_to_le64(mode);
1057 pdata->PosixOpenFlags = cpu_to_le32(posix_flags); 1080 pdata->PosixOpenFlags = cpu_to_le32(posix_flags);
1058 pdata->OpenFlags = cpu_to_le32(*pOplock); 1081 pdata->OpenFlags = cpu_to_le32(*pOplock);
@@ -1098,8 +1121,8 @@ PsxCreat:
1098 if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction) 1121 if (cpu_to_le32(FILE_CREATE) == psx_rsp->CreateAction)
1099 *pOplock |= CIFS_CREATE_ACTION; 1122 *pOplock |= CIFS_CREATE_ACTION;
1100 /* check to make sure response data is there */ 1123 /* check to make sure response data is there */
1101 if (psx_rsp->ReturnedLevel != SMB_QUERY_FILE_UNIX_BASIC) { 1124 if (psx_rsp->ReturnedLevel != cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC)) {
1102 pRetData->Type = -1; /* unknown */ 1125 pRetData->Type = cpu_to_le32(-1); /* unknown */
1103#ifdef CONFIG_CIFS_DEBUG2 1126#ifdef CONFIG_CIFS_DEBUG2
1104 cFYI(1, ("unknown type")); 1127 cFYI(1, ("unknown type"));
1105#endif 1128#endif
@@ -1107,12 +1130,12 @@ PsxCreat:
1107 if (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP) 1130 if (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP)
1108 + sizeof(FILE_UNIX_BASIC_INFO)) { 1131 + sizeof(FILE_UNIX_BASIC_INFO)) {
1109 cERROR(1, ("Open response data too small")); 1132 cERROR(1, ("Open response data too small"));
1110 pRetData->Type = -1; 1133 pRetData->Type = cpu_to_le32(-1);
1111 goto psx_create_err; 1134 goto psx_create_err;
1112 } 1135 }
1113 memcpy((char *) pRetData, 1136 memcpy((char *) pRetData,
1114 (char *)psx_rsp + sizeof(OPEN_PSX_RSP), 1137 (char *)psx_rsp + sizeof(OPEN_PSX_RSP),
1115 sizeof (FILE_UNIX_BASIC_INFO)); 1138 sizeof(FILE_UNIX_BASIC_INFO));
1116 } 1139 }
1117 1140
1118psx_create_err: 1141psx_create_err:
@@ -1193,9 +1216,9 @@ OldOpenRetry:
1193 } 1216 }
1194 if (*pOplock & REQ_OPLOCK) 1217 if (*pOplock & REQ_OPLOCK)
1195 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK); 1218 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
1196 else if (*pOplock & REQ_BATCHOPLOCK) { 1219 else if (*pOplock & REQ_BATCHOPLOCK)
1197 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK); 1220 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
1198 } 1221
1199 pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO); 1222 pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
1200 /* BB fixme add conversion for access_flags to bits 0 - 2 of mode */ 1223 /* BB fixme add conversion for access_flags to bits 0 - 2 of mode */
1201 /* 0 = read 1224 /* 0 = read
@@ -1310,9 +1333,8 @@ openRetry:
1310 } 1333 }
1311 if (*pOplock & REQ_OPLOCK) 1334 if (*pOplock & REQ_OPLOCK)
1312 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK); 1335 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1313 else if (*pOplock & REQ_BATCHOPLOCK) { 1336 else if (*pOplock & REQ_BATCHOPLOCK)
1314 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK); 1337 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1315 }
1316 pSMB->DesiredAccess = cpu_to_le32(access_flags); 1338 pSMB->DesiredAccess = cpu_to_le32(access_flags);
1317 pSMB->AllocationSize = 0; 1339 pSMB->AllocationSize = 0;
1318 /* set file as system file if special file such 1340 /* set file as system file if special file such
@@ -1424,9 +1446,8 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid,
1424 1446
1425 iov[0].iov_base = (char *)pSMB; 1447 iov[0].iov_base = (char *)pSMB;
1426 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4; 1448 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1427 rc = SendReceive2(xid, tcon->ses, iov, 1449 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1428 1 /* num iovecs */, 1450 &resp_buf_type, 0 /* not long op */, 1 /* log err */ );
1429 &resp_buf_type, 0);
1430 cifs_stats_inc(&tcon->num_reads); 1451 cifs_stats_inc(&tcon->num_reads);
1431 pSMBr = (READ_RSP *)iov[0].iov_base; 1452 pSMBr = (READ_RSP *)iov[0].iov_base;
1432 if (rc) { 1453 if (rc) {
@@ -1446,11 +1467,11 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid,
1446 *nbytes = 0; 1467 *nbytes = 0;
1447 } else { 1468 } else {
1448 pReadData = (char *) (&pSMBr->hdr.Protocol) + 1469 pReadData = (char *) (&pSMBr->hdr.Protocol) +
1449 le16_to_cpu(pSMBr->DataOffset); 1470 le16_to_cpu(pSMBr->DataOffset);
1450/* if (rc = copy_to_user(buf, pReadData, data_length)) { 1471/* if (rc = copy_to_user(buf, pReadData, data_length)) {
1451 cERROR(1,("Faulting on read rc = %d",rc)); 1472 cERROR(1,("Faulting on read rc = %d",rc));
1452 rc = -EFAULT; 1473 rc = -EFAULT;
1453 }*/ /* can not use copy_to_user when using page cache*/ 1474 }*/ /* can not use copy_to_user when using page cache*/
1454 if (*buf) 1475 if (*buf)
1455 memcpy(*buf, pReadData, data_length); 1476 memcpy(*buf, pReadData, data_length);
1456 } 1477 }
@@ -1645,7 +1666,7 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1645 1666
1646 1667
1647 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type, 1668 rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
1648 long_op); 1669 long_op, 0 /* do not log STATUS code */ );
1649 cifs_stats_inc(&tcon->num_writes); 1670 cifs_stats_inc(&tcon->num_writes);
1650 if (rc) { 1671 if (rc) {
1651 cFYI(1, ("Send error Write2 = %d", rc)); 1672 cFYI(1, ("Send error Write2 = %d", rc));
@@ -2538,7 +2559,7 @@ validate_ntransact(char *buf, char **ppparm, char **ppdata,
2538 cFYI(1, ("data starts after end of smb")); 2559 cFYI(1, ("data starts after end of smb"));
2539 return -EINVAL; 2560 return -EINVAL;
2540 } else if (data_count + *ppdata > end_of_smb) { 2561 } else if (data_count + *ppdata > end_of_smb) {
2541 cFYI(1,("data %p + count %d (%p) ends after end of smb %p start %p", 2562 cFYI(1, ("data %p + count %d (%p) ends after end of smb %p start %p",
2542 *ppdata, data_count, (data_count + *ppdata), 2563 *ppdata, data_count, (data_count + *ppdata),
2543 end_of_smb, pSMBr)); 2564 end_of_smb, pSMBr));
2544 return -EINVAL; 2565 return -EINVAL;
@@ -2615,7 +2636,7 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
2615 reparse_buf->TargetNameOffset + 2636 reparse_buf->TargetNameOffset +
2616 reparse_buf->TargetNameLen) > 2637 reparse_buf->TargetNameLen) >
2617 end_of_smb) { 2638 end_of_smb) {
2618 cFYI(1,("reparse buf goes beyond SMB")); 2639 cFYI(1, ("reparse buf beyond SMB"));
2619 rc = -EIO; 2640 rc = -EIO;
2620 goto qreparse_out; 2641 goto qreparse_out;
2621 } 2642 }
@@ -3042,25 +3063,12 @@ GetExtAttrOut:
3042 3063
3043#endif /* CONFIG_POSIX */ 3064#endif /* CONFIG_POSIX */
3044 3065
3045 3066#ifdef CONFIG_CIFS_EXPERIMENTAL
3046/* security id for everyone */
3047static const struct cifs_sid sid_everyone =
3048 {1, 1, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0}};
3049/* group users */
3050static const struct cifs_sid sid_user =
3051 {1, 2 , {0, 0, 0, 0, 0, 5}, {32, 545, 0, 0}};
3052
3053/* Convert CIFS ACL to POSIX form */
3054static int parse_sec_desc(struct cifs_sid *psec_desc, int acl_len)
3055{
3056 return 0;
3057}
3058
3059/* Get Security Descriptor (by handle) from remote server for a file or dir */ 3067/* Get Security Descriptor (by handle) from remote server for a file or dir */
3060int 3068int
3061CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid, 3069CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3062 /* BB fix up return info */ char *acl_inf, const int buflen, 3070 /* BB fix up return info */ char *acl_inf, const int buflen,
3063 const int acl_type /* ACCESS/DEFAULT not sure implication */) 3071 const int acl_type)
3064{ 3072{
3065 int rc = 0; 3073 int rc = 0;
3066 int buf_type = 0; 3074 int buf_type = 0;
@@ -3085,12 +3093,13 @@ CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3085 iov[0].iov_base = (char *)pSMB; 3093 iov[0].iov_base = (char *)pSMB;
3086 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4; 3094 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
3087 3095
3088 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type, 0); 3096 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
3097 0 /* not long op */, 0 /* do not log STATUS codes */ );
3089 cifs_stats_inc(&tcon->num_acl_get); 3098 cifs_stats_inc(&tcon->num_acl_get);
3090 if (rc) { 3099 if (rc) {
3091 cFYI(1, ("Send error in QuerySecDesc = %d", rc)); 3100 cFYI(1, ("Send error in QuerySecDesc = %d", rc));
3092 } else { /* decode response */ 3101 } else { /* decode response */
3093 struct cifs_sid *psec_desc; 3102 struct cifs_ntsd *psec_desc;
3094 __le32 * parm; 3103 __le32 * parm;
3095 int parm_len; 3104 int parm_len;
3096 int data_len; 3105 int data_len;
@@ -3105,8 +3114,7 @@ CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3105 goto qsec_out; 3114 goto qsec_out;
3106 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base; 3115 pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
3107 3116
3108 cERROR(1, ("smb %p parm %p data %p", 3117 cFYI(1, ("smb %p parm %p data %p", pSMBr, parm, psec_desc));
3109 pSMBr, parm, psec_desc)); /* BB removeme BB */
3110 3118
3111 if (le32_to_cpu(pSMBr->ParameterCount) != 4) { 3119 if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
3112 rc = -EIO; /* bad smb */ 3120 rc = -EIO; /* bad smb */
@@ -3115,7 +3123,7 @@ CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3115 3123
3116/* BB check that data area is minimum length and as big as acl_len */ 3124/* BB check that data area is minimum length and as big as acl_len */
3117 3125
3118 acl_len = le32_to_cpu(*(__le32 *)parm); 3126 acl_len = le32_to_cpu(*parm);
3119 /* BB check if (acl_len > bufsize) */ 3127 /* BB check if (acl_len > bufsize) */
3120 3128
3121 parse_sec_desc(psec_desc, acl_len); 3129 parse_sec_desc(psec_desc, acl_len);
@@ -3128,6 +3136,7 @@ qsec_out:
3128/* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */ 3136/* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
3129 return rc; 3137 return rc;
3130} 3138}
3139#endif /* CONFIG_CIFS_EXPERIMENTAL */
3131 3140
3132/* Legacy Query Path Information call for lookup to old servers such 3141/* Legacy Query Path Information call for lookup to old servers such
3133 as Win9x/WinME */ 3142 as Win9x/WinME */
@@ -3363,6 +3372,9 @@ UnixQPathInfoRetry:
3363 rc = validate_t2((struct smb_t2_rsp *)pSMBr); 3372 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3364 3373
3365 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) { 3374 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
3375 cERROR(1, ("Malformed FILE_UNIX_BASIC_INFO response.\n"
3376 "Unix Extensions can be disabled on mount "
3377 "by specifying the nosfu mount option."));
3366 rc = -EIO; /* bad smb */ 3378 rc = -EIO; /* bad smb */
3367 } else { 3379 } else {
3368 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); 3380 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
@@ -3883,12 +3895,10 @@ getDFSRetry:
3883 pSMB->hdr.Mid = GetNextMid(ses->server); 3895 pSMB->hdr.Mid = GetNextMid(ses->server);
3884 pSMB->hdr.Tid = ses->ipc_tid; 3896 pSMB->hdr.Tid = ses->ipc_tid;
3885 pSMB->hdr.Uid = ses->Suid; 3897 pSMB->hdr.Uid = ses->Suid;
3886 if (ses->capabilities & CAP_STATUS32) { 3898 if (ses->capabilities & CAP_STATUS32)
3887 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS; 3899 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
3888 } 3900 if (ses->capabilities & CAP_DFS)
3889 if (ses->capabilities & CAP_DFS) {
3890 pSMB->hdr.Flags2 |= SMBFLG2_DFS; 3901 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
3891 }
3892 3902
3893 if (ses->capabilities & CAP_UNICODE) { 3903 if (ses->capabilities & CAP_UNICODE) {
3894 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE; 3904 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
@@ -4060,10 +4070,6 @@ oldQFSInfoRetry:
4060 (void **) &pSMBr); 4070 (void **) &pSMBr);
4061 if (rc) 4071 if (rc)
4062 return rc; 4072 return rc;
4063 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4064 (void **) &pSMBr);
4065 if (rc)
4066 return rc;
4067 4073
4068 params = 2; /* level */ 4074 params = 2; /* level */
4069 pSMB->TotalDataCount = 0; 4075 pSMB->TotalDataCount = 0;
@@ -4265,7 +4271,7 @@ QFSAttributeRetry:
4265 *) (((char *) &pSMBr->hdr.Protocol) + 4271 *) (((char *) &pSMBr->hdr.Protocol) +
4266 data_offset); 4272 data_offset);
4267 memcpy(&tcon->fsAttrInfo, response_data, 4273 memcpy(&tcon->fsAttrInfo, response_data,
4268 sizeof (FILE_SYSTEM_ATTRIBUTE_INFO)); 4274 sizeof(FILE_SYSTEM_ATTRIBUTE_INFO));
4269 } 4275 }
4270 } 4276 }
4271 cifs_buf_release(pSMB); 4277 cifs_buf_release(pSMB);
@@ -4334,7 +4340,7 @@ QFSDeviceRetry:
4334 (((char *) &pSMBr->hdr.Protocol) + 4340 (((char *) &pSMBr->hdr.Protocol) +
4335 data_offset); 4341 data_offset);
4336 memcpy(&tcon->fsDevInfo, response_data, 4342 memcpy(&tcon->fsDevInfo, response_data,
4337 sizeof (FILE_SYSTEM_DEVICE_INFO)); 4343 sizeof(FILE_SYSTEM_DEVICE_INFO));
4338 } 4344 }
4339 } 4345 }
4340 cifs_buf_release(pSMB); 4346 cifs_buf_release(pSMB);
@@ -4402,7 +4408,7 @@ QFSUnixRetry:
4402 *) (((char *) &pSMBr->hdr.Protocol) + 4408 *) (((char *) &pSMBr->hdr.Protocol) +
4403 data_offset); 4409 data_offset);
4404 memcpy(&tcon->fsUnixInfo, response_data, 4410 memcpy(&tcon->fsUnixInfo, response_data,
4405 sizeof (FILE_SYSTEM_UNIX_INFO)); 4411 sizeof(FILE_SYSTEM_UNIX_INFO));
4406 } 4412 }
4407 } 4413 }
4408 cifs_buf_release(pSMB); 4414 cifs_buf_release(pSMB);
@@ -4612,7 +4618,7 @@ SetEOFRetry:
4612 strncpy(pSMB->FileName, fileName, name_len); 4618 strncpy(pSMB->FileName, fileName, name_len);
4613 } 4619 }
4614 params = 6 + name_len; 4620 params = 6 + name_len;
4615 data_count = sizeof (struct file_end_of_file_info); 4621 data_count = sizeof(struct file_end_of_file_info);
4616 pSMB->MaxParameterCount = cpu_to_le16(2); 4622 pSMB->MaxParameterCount = cpu_to_le16(2);
4617 pSMB->MaxDataCount = cpu_to_le16(4100); 4623 pSMB->MaxDataCount = cpu_to_le16(4100);
4618 pSMB->MaxSetupCount = 0; 4624 pSMB->MaxSetupCount = 0;
@@ -4800,7 +4806,7 @@ CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon,
4800 4806
4801 data_offset = (char *) (&pSMB->hdr.Protocol) + offset; 4807 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4802 4808
4803 count = sizeof (FILE_BASIC_INFO); 4809 count = sizeof(FILE_BASIC_INFO);
4804 pSMB->MaxParameterCount = cpu_to_le16(2); 4810 pSMB->MaxParameterCount = cpu_to_le16(2);
4805 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */ 4811 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
4806 pSMB->SetupCount = 1; 4812 pSMB->SetupCount = 1;
@@ -4871,7 +4877,7 @@ SetTimesRetry:
4871 } 4877 }
4872 4878
4873 params = 6 + name_len; 4879 params = 6 + name_len;
4874 count = sizeof (FILE_BASIC_INFO); 4880 count = sizeof(FILE_BASIC_INFO);
4875 pSMB->MaxParameterCount = cpu_to_le16(2); 4881 pSMB->MaxParameterCount = cpu_to_le16(2);
4876 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */ 4882 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4877 pSMB->MaxSetupCount = 0; 4883 pSMB->MaxSetupCount = 0;
@@ -4900,7 +4906,7 @@ SetTimesRetry:
4900 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO); 4906 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4901 pSMB->Reserved4 = 0; 4907 pSMB->Reserved4 = 0;
4902 pSMB->hdr.smb_buf_length += byte_count; 4908 pSMB->hdr.smb_buf_length += byte_count;
4903 memcpy(data_offset, data, sizeof (FILE_BASIC_INFO)); 4909 memcpy(data_offset, data, sizeof(FILE_BASIC_INFO));
4904 pSMB->ByteCount = cpu_to_le16(byte_count); 4910 pSMB->ByteCount = cpu_to_le16(byte_count);
4905 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 4911 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4906 (struct smb_hdr *) pSMBr, &bytes_returned, 0); 4912 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
@@ -5003,7 +5009,7 @@ setPermsRetry:
5003 } 5009 }
5004 5010
5005 params = 6 + name_len; 5011 params = 6 + name_len;
5006 count = sizeof (FILE_UNIX_BASIC_INFO); 5012 count = sizeof(FILE_UNIX_BASIC_INFO);
5007 pSMB->MaxParameterCount = cpu_to_le16(2); 5013 pSMB->MaxParameterCount = cpu_to_le16(2);
5008 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */ 5014 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
5009 pSMB->MaxSetupCount = 0; 5015 pSMB->MaxSetupCount = 0;
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 370866cb3d48..19ee11f7f35a 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -124,7 +124,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
124 struct mid_q_entry *mid_entry; 124 struct mid_q_entry *mid_entry;
125 125
126 spin_lock(&GlobalMid_Lock); 126 spin_lock(&GlobalMid_Lock);
127 if ( kthread_should_stop() ) { 127 if (kthread_should_stop()) {
128 /* the demux thread will exit normally 128 /* the demux thread will exit normally
129 next time through the loop */ 129 next time through the loop */
130 spin_unlock(&GlobalMid_Lock); 130 spin_unlock(&GlobalMid_Lock);
@@ -151,9 +151,8 @@ cifs_reconnect(struct TCP_Server_Info *server)
151 } 151 }
152 list_for_each(tmp, &GlobalTreeConnectionList) { 152 list_for_each(tmp, &GlobalTreeConnectionList) {
153 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList); 153 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
154 if ((tcon) && (tcon->ses) && (tcon->ses->server == server)) { 154 if ((tcon) && (tcon->ses) && (tcon->ses->server == server))
155 tcon->tidStatus = CifsNeedReconnect; 155 tcon->tidStatus = CifsNeedReconnect;
156 }
157 } 156 }
158 read_unlock(&GlobalSMBSeslock); 157 read_unlock(&GlobalSMBSeslock);
159 /* do not want to be sending data on a socket we are freeing */ 158 /* do not want to be sending data on a socket we are freeing */
@@ -187,7 +186,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
187 spin_unlock(&GlobalMid_Lock); 186 spin_unlock(&GlobalMid_Lock);
188 up(&server->tcpSem); 187 up(&server->tcpSem);
189 188
190 while ( (!kthread_should_stop()) && (server->tcpStatus != CifsGood)) { 189 while ((!kthread_should_stop()) && (server->tcpStatus != CifsGood)) {
191 try_to_freeze(); 190 try_to_freeze();
192 if (server->protocolType == IPV6) { 191 if (server->protocolType == IPV6) {
193 rc = ipv6_connect(&server->addr.sockAddr6, 192 rc = ipv6_connect(&server->addr.sockAddr6,
@@ -204,7 +203,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
204 } else { 203 } else {
205 atomic_inc(&tcpSesReconnectCount); 204 atomic_inc(&tcpSesReconnectCount);
206 spin_lock(&GlobalMid_Lock); 205 spin_lock(&GlobalMid_Lock);
207 if ( !kthread_should_stop() ) 206 if (!kthread_should_stop())
208 server->tcpStatus = CifsGood; 207 server->tcpStatus = CifsGood;
209 server->sequence_number = 0; 208 server->sequence_number = 0;
210 spin_unlock(&GlobalMid_Lock); 209 spin_unlock(&GlobalMid_Lock);
@@ -358,11 +357,9 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
358 length = tcpSesAllocCount.counter; 357 length = tcpSesAllocCount.counter;
359 write_unlock(&GlobalSMBSeslock); 358 write_unlock(&GlobalSMBSeslock);
360 complete(&cifsd_complete); 359 complete(&cifsd_complete);
361 if (length > 1) { 360 if (length > 1)
362 mempool_resize(cifs_req_poolp, 361 mempool_resize(cifs_req_poolp, length + cifs_min_rcv,
363 length + cifs_min_rcv, 362 GFP_KERNEL);
364 GFP_KERNEL);
365 }
366 363
367 set_freezable(); 364 set_freezable();
368 while (!kthread_should_stop()) { 365 while (!kthread_should_stop()) {
@@ -378,7 +375,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
378 } 375 }
379 } else if (isLargeBuf) { 376 } else if (isLargeBuf) {
380 /* we are reusing a dirty large buf, clear its start */ 377 /* we are reusing a dirty large buf, clear its start */
381 memset(bigbuf, 0, sizeof (struct smb_hdr)); 378 memset(bigbuf, 0, sizeof(struct smb_hdr));
382 } 379 }
383 380
384 if (smallbuf == NULL) { 381 if (smallbuf == NULL) {
@@ -391,7 +388,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
391 } 388 }
392 /* beginning of smb buffer is cleared in our buf_get */ 389 /* beginning of smb buffer is cleared in our buf_get */
393 } else /* if existing small buf clear beginning */ 390 } else /* if existing small buf clear beginning */
394 memset(smallbuf, 0, sizeof (struct smb_hdr)); 391 memset(smallbuf, 0, sizeof(struct smb_hdr));
395 392
396 isLargeBuf = FALSE; 393 isLargeBuf = FALSE;
397 isMultiRsp = FALSE; 394 isMultiRsp = FALSE;
@@ -400,11 +397,13 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
400 iov.iov_len = 4; 397 iov.iov_len = 4;
401 smb_msg.msg_control = NULL; 398 smb_msg.msg_control = NULL;
402 smb_msg.msg_controllen = 0; 399 smb_msg.msg_controllen = 0;
400 pdu_length = 4; /* enough to get RFC1001 header */
401incomplete_rcv:
403 length = 402 length =
404 kernel_recvmsg(csocket, &smb_msg, 403 kernel_recvmsg(csocket, &smb_msg,
405 &iov, 1, 4, 0 /* BB see socket.h flags */); 404 &iov, 1, pdu_length, 0 /* BB other flags? */);
406 405
407 if ( kthread_should_stop() ) { 406 if (kthread_should_stop()) {
408 break; 407 break;
409 } else if (server->tcpStatus == CifsNeedReconnect) { 408 } else if (server->tcpStatus == CifsNeedReconnect) {
410 cFYI(1, ("Reconnect after server stopped responding")); 409 cFYI(1, ("Reconnect after server stopped responding"));
@@ -416,7 +415,10 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
416 msleep(1); /* minimum sleep to prevent looping 415 msleep(1); /* minimum sleep to prevent looping
417 allowing socket to clear and app threads to set 416 allowing socket to clear and app threads to set
418 tcpStatus CifsNeedReconnect if server hung */ 417 tcpStatus CifsNeedReconnect if server hung */
419 continue; 418 if (pdu_length < 4)
419 goto incomplete_rcv;
420 else
421 continue;
420 } else if (length <= 0) { 422 } else if (length <= 0) {
421 if (server->tcpStatus == CifsNew) { 423 if (server->tcpStatus == CifsNew) {
422 cFYI(1, ("tcp session abend after SMBnegprot")); 424 cFYI(1, ("tcp session abend after SMBnegprot"));
@@ -437,13 +439,11 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
437 wake_up(&server->response_q); 439 wake_up(&server->response_q);
438 continue; 440 continue;
439 } else if (length < 4) { 441 } else if (length < 4) {
440 cFYI(1, 442 cFYI(1, ("less than four bytes received (%d bytes)",
441 ("Frame under four bytes received (%d bytes long)",
442 length)); 443 length));
443 cifs_reconnect(server); 444 pdu_length -= length;
444 csocket = server->ssocket; 445 msleep(1);
445 wake_up(&server->response_q); 446 goto incomplete_rcv;
446 continue;
447 } 447 }
448 448
449 /* The right amount was read from socket - 4 bytes */ 449 /* The right amount was read from socket - 4 bytes */
@@ -504,7 +504,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
504 504
505 /* else we have an SMB response */ 505 /* else we have an SMB response */
506 if ((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) || 506 if ((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) ||
507 (pdu_length < sizeof (struct smb_hdr) - 1 - 4)) { 507 (pdu_length < sizeof(struct smb_hdr) - 1 - 4)) {
508 cERROR(1, ("Invalid size SMB length %d pdu_length %d", 508 cERROR(1, ("Invalid size SMB length %d pdu_length %d",
509 length, pdu_length+4)); 509 length, pdu_length+4));
510 cifs_reconnect(server); 510 cifs_reconnect(server);
@@ -528,7 +528,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
528 total_read += length) { 528 total_read += length) {
529 length = kernel_recvmsg(csocket, &smb_msg, &iov, 1, 529 length = kernel_recvmsg(csocket, &smb_msg, &iov, 1,
530 pdu_length - total_read, 0); 530 pdu_length - total_read, 0);
531 if ( kthread_should_stop() || 531 if (kthread_should_stop() ||
532 (length == -EINTR)) { 532 (length == -EINTR)) {
533 /* then will exit */ 533 /* then will exit */
534 reconnect = 2; 534 reconnect = 2;
@@ -546,6 +546,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
546 allowing socket to clear and app 546 allowing socket to clear and app
547 threads to set tcpStatus 547 threads to set tcpStatus
548 CifsNeedReconnect if server hung*/ 548 CifsNeedReconnect if server hung*/
549 length = 0;
549 continue; 550 continue;
550 } else if (length <= 0) { 551 } else if (length <= 0) {
551 cERROR(1, ("Received no data, expecting %d", 552 cERROR(1, ("Received no data, expecting %d",
@@ -631,9 +632,9 @@ multi_t2_fnd:
631 /* Was previous buf put in mpx struct for multi-rsp? */ 632 /* Was previous buf put in mpx struct for multi-rsp? */
632 if (!isMultiRsp) { 633 if (!isMultiRsp) {
633 /* smb buffer will be freed by user thread */ 634 /* smb buffer will be freed by user thread */
634 if (isLargeBuf) { 635 if (isLargeBuf)
635 bigbuf = NULL; 636 bigbuf = NULL;
636 } else 637 else
637 smallbuf = NULL; 638 smallbuf = NULL;
638 } 639 }
639 wake_up_process(task_to_wake); 640 wake_up_process(task_to_wake);
@@ -676,9 +677,8 @@ multi_t2_fnd:
676 server->ssocket = NULL; 677 server->ssocket = NULL;
677 } 678 }
678 /* buffer usuallly freed in free_mid - need to free it here on exit */ 679 /* buffer usuallly freed in free_mid - need to free it here on exit */
679 if (bigbuf != NULL) 680 cifs_buf_release(bigbuf);
680 cifs_buf_release(bigbuf); 681 if (smallbuf) /* no sense logging a debug message if NULL */
681 if (smallbuf != NULL)
682 cifs_small_buf_release(smallbuf); 682 cifs_small_buf_release(smallbuf);
683 683
684 read_lock(&GlobalSMBSeslock); 684 read_lock(&GlobalSMBSeslock);
@@ -702,9 +702,8 @@ multi_t2_fnd:
702 list_for_each(tmp, &GlobalSMBSessionList) { 702 list_for_each(tmp, &GlobalSMBSessionList) {
703 ses = list_entry(tmp, struct cifsSesInfo, 703 ses = list_entry(tmp, struct cifsSesInfo,
704 cifsSessionList); 704 cifsSessionList);
705 if (ses->server == server) { 705 if (ses->server == server)
706 ses->status = CifsExiting; 706 ses->status = CifsExiting;
707 }
708 } 707 }
709 708
710 spin_lock(&GlobalMid_Lock); 709 spin_lock(&GlobalMid_Lock);
@@ -714,9 +713,8 @@ multi_t2_fnd:
714 cFYI(1, ("Clearing Mid 0x%x - waking up ", 713 cFYI(1, ("Clearing Mid 0x%x - waking up ",
715 mid_entry->mid)); 714 mid_entry->mid));
716 task_to_wake = mid_entry->tsk; 715 task_to_wake = mid_entry->tsk;
717 if (task_to_wake) { 716 if (task_to_wake)
718 wake_up_process(task_to_wake); 717 wake_up_process(task_to_wake);
719 }
720 } 718 }
721 } 719 }
722 spin_unlock(&GlobalMid_Lock); 720 spin_unlock(&GlobalMid_Lock);
@@ -749,18 +747,15 @@ multi_t2_fnd:
749 list_for_each(tmp, &GlobalSMBSessionList) { 747 list_for_each(tmp, &GlobalSMBSessionList) {
750 ses = list_entry(tmp, struct cifsSesInfo, 748 ses = list_entry(tmp, struct cifsSesInfo,
751 cifsSessionList); 749 cifsSessionList);
752 if (ses->server == server) { 750 if (ses->server == server)
753 ses->server = NULL; 751 ses->server = NULL;
754 }
755 } 752 }
756 write_unlock(&GlobalSMBSeslock); 753 write_unlock(&GlobalSMBSeslock);
757 754
758 kfree(server); 755 kfree(server);
759 if (length > 0) { 756 if (length > 0)
760 mempool_resize(cifs_req_poolp, 757 mempool_resize(cifs_req_poolp, length + cifs_min_rcv,
761 length + cifs_min_rcv, 758 GFP_KERNEL);
762 GFP_KERNEL);
763 }
764 759
765 return 0; 760 return 0;
766} 761}
@@ -1477,7 +1472,7 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
1477 if (psin_server->sin_port) { /* user overrode default port */ 1472 if (psin_server->sin_port) { /* user overrode default port */
1478 rc = (*csocket)->ops->connect(*csocket, 1473 rc = (*csocket)->ops->connect(*csocket,
1479 (struct sockaddr *) psin_server, 1474 (struct sockaddr *) psin_server,
1480 sizeof (struct sockaddr_in), 0); 1475 sizeof(struct sockaddr_in), 0);
1481 if (rc >= 0) 1476 if (rc >= 0)
1482 connected = 1; 1477 connected = 1;
1483 } 1478 }
@@ -1493,7 +1488,7 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
1493 1488
1494 rc = (*csocket)->ops->connect(*csocket, 1489 rc = (*csocket)->ops->connect(*csocket,
1495 (struct sockaddr *) psin_server, 1490 (struct sockaddr *) psin_server,
1496 sizeof (struct sockaddr_in), 0); 1491 sizeof(struct sockaddr_in), 0);
1497 if (rc >= 0) 1492 if (rc >= 0)
1498 connected = 1; 1493 connected = 1;
1499 } 1494 }
@@ -1502,7 +1497,7 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
1502 psin_server->sin_port = htons(RFC1001_PORT); 1497 psin_server->sin_port = htons(RFC1001_PORT);
1503 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *) 1498 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
1504 psin_server, 1499 psin_server,
1505 sizeof (struct sockaddr_in), 0); 1500 sizeof(struct sockaddr_in), 0);
1506 if (rc >= 0) 1501 if (rc >= 0)
1507 connected = 1; 1502 connected = 1;
1508 } 1503 }
@@ -1610,7 +1605,7 @@ ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
1610 if (psin_server->sin6_port) { /* user overrode default port */ 1605 if (psin_server->sin6_port) { /* user overrode default port */
1611 rc = (*csocket)->ops->connect(*csocket, 1606 rc = (*csocket)->ops->connect(*csocket,
1612 (struct sockaddr *) psin_server, 1607 (struct sockaddr *) psin_server,
1613 sizeof (struct sockaddr_in6), 0); 1608 sizeof(struct sockaddr_in6), 0);
1614 if (rc >= 0) 1609 if (rc >= 0)
1615 connected = 1; 1610 connected = 1;
1616 } 1611 }
@@ -1626,7 +1621,7 @@ ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
1626 1621
1627 rc = (*csocket)->ops->connect(*csocket, 1622 rc = (*csocket)->ops->connect(*csocket,
1628 (struct sockaddr *) psin_server, 1623 (struct sockaddr *) psin_server,
1629 sizeof (struct sockaddr_in6), 0); 1624 sizeof(struct sockaddr_in6), 0);
1630 if (rc >= 0) 1625 if (rc >= 0)
1631 connected = 1; 1626 connected = 1;
1632 } 1627 }
@@ -1634,7 +1629,7 @@ ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
1634 if (!connected) { 1629 if (!connected) {
1635 psin_server->sin6_port = htons(RFC1001_PORT); 1630 psin_server->sin6_port = htons(RFC1001_PORT);
1636 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *) 1631 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
1637 psin_server, sizeof (struct sockaddr_in6), 0); 1632 psin_server, sizeof(struct sockaddr_in6), 0);
1638 if (rc >= 0) 1633 if (rc >= 0)
1639 connected = 1; 1634 connected = 1;
1640 } 1635 }
@@ -1750,7 +1745,16 @@ void reset_cifs_unix_caps(int xid, struct cifsTconInfo *tcon,
1750 cFYI(1, ("very large write cap")); 1745 cFYI(1, ("very large write cap"));
1751#endif /* CIFS_DEBUG2 */ 1746#endif /* CIFS_DEBUG2 */
1752 if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) { 1747 if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
1753 cFYI(1, ("setting capabilities failed")); 1748 if (vol_info == NULL) {
1749 cFYI(1, ("resetting capabilities failed"));
1750 } else
1751 cERROR(1, ("Negotiating Unix capabilities "
1752 "with the server failed. Consider "
1753 "mounting with the Unix Extensions\n"
1754 "disabled, if problems are found, "
1755 "by specifying the nounix mount "
1756 "option."));
1757
1754 } 1758 }
1755 } 1759 }
1756} 1760}
@@ -1909,8 +1913,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1909 return rc; 1913 return rc;
1910 } 1914 }
1911 1915
1912 srvTcp = kmalloc(sizeof (struct TCP_Server_Info), GFP_KERNEL); 1916 srvTcp = kzalloc(sizeof(struct TCP_Server_Info), GFP_KERNEL);
1913 if (srvTcp == NULL) { 1917 if (!srvTcp) {
1914 rc = -ENOMEM; 1918 rc = -ENOMEM;
1915 sock_release(csocket); 1919 sock_release(csocket);
1916 kfree(volume_info.UNC); 1920 kfree(volume_info.UNC);
@@ -1919,9 +1923,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1919 FreeXid(xid); 1923 FreeXid(xid);
1920 return rc; 1924 return rc;
1921 } else { 1925 } else {
1922 memset(srvTcp, 0, sizeof (struct TCP_Server_Info));
1923 memcpy(&srvTcp->addr.sockAddr, &sin_server, 1926 memcpy(&srvTcp->addr.sockAddr, &sin_server,
1924 sizeof (struct sockaddr_in)); 1927 sizeof(struct sockaddr_in));
1925 atomic_set(&srvTcp->inFlight, 0); 1928 atomic_set(&srvTcp->inFlight, 0);
1926 /* BB Add code for ipv6 case too */ 1929 /* BB Add code for ipv6 case too */
1927 srvTcp->ssocket = csocket; 1930 srvTcp->ssocket = csocket;
@@ -2173,8 +2176,18 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
2173 if (tsk) 2176 if (tsk)
2174 kthread_stop(tsk); 2177 kthread_stop(tsk);
2175 } 2178 }
2176 } else 2179 } else {
2177 cFYI(1, ("No session or bad tcon")); 2180 cFYI(1, ("No session or bad tcon"));
2181 if ((pSesInfo->server) &&
2182 (pSesInfo->server->tsk)) {
2183 struct task_struct *tsk;
2184 force_sig(SIGKILL,
2185 pSesInfo->server->tsk);
2186 tsk = pSesInfo->server->tsk;
2187 if (tsk)
2188 kthread_stop(tsk);
2189 }
2190 }
2178 sesInfoFree(pSesInfo); 2191 sesInfoFree(pSesInfo);
2179 /* pSesInfo = NULL; */ 2192 /* pSesInfo = NULL; */
2180 } 2193 }
@@ -2185,8 +2198,10 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
2185 tcon->ses = pSesInfo; 2198 tcon->ses = pSesInfo;
2186 2199
2187 /* do not care if following two calls succeed - informational */ 2200 /* do not care if following two calls succeed - informational */
2188 CIFSSMBQFSDeviceInfo(xid, tcon); 2201 if (!tcon->ipc) {
2189 CIFSSMBQFSAttributeInfo(xid, tcon); 2202 CIFSSMBQFSDeviceInfo(xid, tcon);
2203 CIFSSMBQFSAttributeInfo(xid, tcon);
2204 }
2190 2205
2191 /* tell server which Unix caps we support */ 2206 /* tell server which Unix caps we support */
2192 if (tcon->ses->capabilities & CAP_UNIX) 2207 if (tcon->ses->capabilities & CAP_UNIX)
@@ -2526,8 +2541,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2526sesssetup_nomem: /* do not return an error on nomem for the info strings, 2541sesssetup_nomem: /* do not return an error on nomem for the info strings,
2527 since that could make reconnection harder, and 2542 since that could make reconnection harder, and
2528 reconnection might be needed to free memory */ 2543 reconnection might be needed to free memory */
2529 if (smb_buffer) 2544 cifs_buf_release(smb_buffer);
2530 cifs_buf_release(smb_buffer);
2531 2545
2532 return rc; 2546 return rc;
2533} 2547}
@@ -2547,7 +2561,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2547 int remaining_words = 0; 2561 int remaining_words = 0;
2548 int bytes_returned = 0; 2562 int bytes_returned = 0;
2549 int len; 2563 int len;
2550 int SecurityBlobLength = sizeof (NEGOTIATE_MESSAGE); 2564 int SecurityBlobLength = sizeof(NEGOTIATE_MESSAGE);
2551 PNEGOTIATE_MESSAGE SecurityBlob; 2565 PNEGOTIATE_MESSAGE SecurityBlob;
2552 PCHALLENGE_MESSAGE SecurityBlob2; 2566 PCHALLENGE_MESSAGE SecurityBlob2;
2553 __u32 negotiate_flags, capabilities; 2567 __u32 negotiate_flags, capabilities;
@@ -2865,15 +2879,14 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2865 rc = -EIO; 2879 rc = -EIO;
2866 } 2880 }
2867 2881
2868 if (smb_buffer) 2882 cifs_buf_release(smb_buffer);
2869 cifs_buf_release(smb_buffer);
2870 2883
2871 return rc; 2884 return rc;
2872} 2885}
2873static int 2886static int
2874CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, 2887CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2875 char *ntlm_session_key, int ntlmv2_flag, 2888 char *ntlm_session_key, int ntlmv2_flag,
2876 const struct nls_table *nls_codepage) 2889 const struct nls_table *nls_codepage)
2877{ 2890{
2878 struct smb_hdr *smb_buffer; 2891 struct smb_hdr *smb_buffer;
2879 struct smb_hdr *smb_buffer_response; 2892 struct smb_hdr *smb_buffer_response;
@@ -2886,7 +2899,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2886 int remaining_words = 0; 2899 int remaining_words = 0;
2887 int bytes_returned = 0; 2900 int bytes_returned = 0;
2888 int len; 2901 int len;
2889 int SecurityBlobLength = sizeof (AUTHENTICATE_MESSAGE); 2902 int SecurityBlobLength = sizeof(AUTHENTICATE_MESSAGE);
2890 PAUTHENTICATE_MESSAGE SecurityBlob; 2903 PAUTHENTICATE_MESSAGE SecurityBlob;
2891 __u32 negotiate_flags, capabilities; 2904 __u32 negotiate_flags, capabilities;
2892 __u16 count; 2905 __u16 count;
@@ -2901,8 +2914,8 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2901 return -ENOMEM; 2914 return -ENOMEM;
2902 } 2915 }
2903 smb_buffer_response = smb_buffer; 2916 smb_buffer_response = smb_buffer;
2904 pSMB = (SESSION_SETUP_ANDX *) smb_buffer; 2917 pSMB = (SESSION_SETUP_ANDX *)smb_buffer;
2905 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response; 2918 pSMBr = (SESSION_SETUP_ANDX *)smb_buffer_response;
2906 2919
2907 /* send SMBsessionSetup here */ 2920 /* send SMBsessionSetup here */
2908 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX, 2921 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
@@ -2921,7 +2934,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2921 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; 2934 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2922 2935
2923 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS | 2936 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2924 CAP_EXTENDED_SECURITY; 2937 CAP_EXTENDED_SECURITY;
2925 if (ses->capabilities & CAP_UNICODE) { 2938 if (ses->capabilities & CAP_UNICODE) {
2926 smb_buffer->Flags2 |= SMBFLG2_UNICODE; 2939 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2927 capabilities |= CAP_UNICODE; 2940 capabilities |= CAP_UNICODE;
@@ -2936,15 +2949,14 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2936 } 2949 }
2937 pSMB->req.Capabilities = cpu_to_le32(capabilities); 2950 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2938 2951
2939 bcc_ptr = (char *) &pSMB->req.SecurityBlob; 2952 bcc_ptr = (char *)&pSMB->req.SecurityBlob;
2940 SecurityBlob = (PAUTHENTICATE_MESSAGE) bcc_ptr; 2953 SecurityBlob = (PAUTHENTICATE_MESSAGE)bcc_ptr;
2941 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8); 2954 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2942 SecurityBlob->MessageType = NtLmAuthenticate; 2955 SecurityBlob->MessageType = NtLmAuthenticate;
2943 bcc_ptr += SecurityBlobLength; 2956 bcc_ptr += SecurityBlobLength;
2944 negotiate_flags = 2957 negotiate_flags = NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET |
2945 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET | 2958 NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO |
2946 NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO | 2959 0x80000000 | NTLMSSP_NEGOTIATE_128;
2947 0x80000000 | NTLMSSP_NEGOTIATE_128;
2948 if (sign_CIFS_PDUs) 2960 if (sign_CIFS_PDUs)
2949 negotiate_flags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN; 2961 negotiate_flags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN;
2950 if (ntlmv2_flag) 2962 if (ntlmv2_flag)
@@ -2979,36 +2991,32 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2979 SecurityBlob->DomainName.Length = 0; 2991 SecurityBlob->DomainName.Length = 0;
2980 SecurityBlob->DomainName.MaximumLength = 0; 2992 SecurityBlob->DomainName.MaximumLength = 0;
2981 } else { 2993 } else {
2982 __u16 len = 2994 __u16 ln = cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64,
2983 cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64,
2984 nls_codepage); 2995 nls_codepage);
2985 len *= 2; 2996 ln *= 2;
2986 SecurityBlob->DomainName.MaximumLength = 2997 SecurityBlob->DomainName.MaximumLength =
2987 cpu_to_le16(len); 2998 cpu_to_le16(ln);
2988 SecurityBlob->DomainName.Buffer = 2999 SecurityBlob->DomainName.Buffer =
2989 cpu_to_le32(SecurityBlobLength); 3000 cpu_to_le32(SecurityBlobLength);
2990 bcc_ptr += len; 3001 bcc_ptr += ln;
2991 SecurityBlobLength += len; 3002 SecurityBlobLength += ln;
2992 SecurityBlob->DomainName.Length = 3003 SecurityBlob->DomainName.Length = cpu_to_le16(ln);
2993 cpu_to_le16(len);
2994 } 3004 }
2995 if (user == NULL) { 3005 if (user == NULL) {
2996 SecurityBlob->UserName.Buffer = 0; 3006 SecurityBlob->UserName.Buffer = 0;
2997 SecurityBlob->UserName.Length = 0; 3007 SecurityBlob->UserName.Length = 0;
2998 SecurityBlob->UserName.MaximumLength = 0; 3008 SecurityBlob->UserName.MaximumLength = 0;
2999 } else { 3009 } else {
3000 __u16 len = 3010 __u16 ln = cifs_strtoUCS((__le16 *) bcc_ptr, user, 64,
3001 cifs_strtoUCS((__le16 *) bcc_ptr, user, 64,
3002 nls_codepage); 3011 nls_codepage);
3003 len *= 2; 3012 ln *= 2;
3004 SecurityBlob->UserName.MaximumLength = 3013 SecurityBlob->UserName.MaximumLength =
3005 cpu_to_le16(len); 3014 cpu_to_le16(ln);
3006 SecurityBlob->UserName.Buffer = 3015 SecurityBlob->UserName.Buffer =
3007 cpu_to_le32(SecurityBlobLength); 3016 cpu_to_le32(SecurityBlobLength);
3008 bcc_ptr += len; 3017 bcc_ptr += ln;
3009 SecurityBlobLength += len; 3018 SecurityBlobLength += ln;
3010 SecurityBlob->UserName.Length = 3019 SecurityBlob->UserName.Length = cpu_to_le16(ln);
3011 cpu_to_le16(len);
3012 } 3020 }
3013 3021
3014 /* SecurityBlob->WorkstationName.Length = 3022 /* SecurityBlob->WorkstationName.Length =
@@ -3052,33 +3060,32 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
3052 SecurityBlob->DomainName.Length = 0; 3060 SecurityBlob->DomainName.Length = 0;
3053 SecurityBlob->DomainName.MaximumLength = 0; 3061 SecurityBlob->DomainName.MaximumLength = 0;
3054 } else { 3062 } else {
3055 __u16 len; 3063 __u16 ln;
3056 negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED; 3064 negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
3057 strncpy(bcc_ptr, domain, 63); 3065 strncpy(bcc_ptr, domain, 63);
3058 len = strnlen(domain, 64); 3066 ln = strnlen(domain, 64);
3059 SecurityBlob->DomainName.MaximumLength = 3067 SecurityBlob->DomainName.MaximumLength =
3060 cpu_to_le16(len); 3068 cpu_to_le16(ln);
3061 SecurityBlob->DomainName.Buffer = 3069 SecurityBlob->DomainName.Buffer =
3062 cpu_to_le32(SecurityBlobLength); 3070 cpu_to_le32(SecurityBlobLength);
3063 bcc_ptr += len; 3071 bcc_ptr += ln;
3064 SecurityBlobLength += len; 3072 SecurityBlobLength += ln;
3065 SecurityBlob->DomainName.Length = cpu_to_le16(len); 3073 SecurityBlob->DomainName.Length = cpu_to_le16(ln);
3066 } 3074 }
3067 if (user == NULL) { 3075 if (user == NULL) {
3068 SecurityBlob->UserName.Buffer = 0; 3076 SecurityBlob->UserName.Buffer = 0;
3069 SecurityBlob->UserName.Length = 0; 3077 SecurityBlob->UserName.Length = 0;
3070 SecurityBlob->UserName.MaximumLength = 0; 3078 SecurityBlob->UserName.MaximumLength = 0;
3071 } else { 3079 } else {
3072 __u16 len; 3080 __u16 ln;
3073 strncpy(bcc_ptr, user, 63); 3081 strncpy(bcc_ptr, user, 63);
3074 len = strnlen(user, 64); 3082 ln = strnlen(user, 64);
3075 SecurityBlob->UserName.MaximumLength = 3083 SecurityBlob->UserName.MaximumLength = cpu_to_le16(ln);
3076 cpu_to_le16(len);
3077 SecurityBlob->UserName.Buffer = 3084 SecurityBlob->UserName.Buffer =
3078 cpu_to_le32(SecurityBlobLength); 3085 cpu_to_le32(SecurityBlobLength);
3079 bcc_ptr += len; 3086 bcc_ptr += ln;
3080 SecurityBlobLength += len; 3087 SecurityBlobLength += ln;
3081 SecurityBlob->UserName.Length = cpu_to_le16(len); 3088 SecurityBlob->UserName.Length = cpu_to_le16(ln);
3082 } 3089 }
3083 /* BB fill in our workstation name if known BB */ 3090 /* BB fill in our workstation name if known BB */
3084 3091
@@ -3100,12 +3107,11 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
3100 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, 3107 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
3101 &bytes_returned, 1); 3108 &bytes_returned, 1);
3102 if (rc) { 3109 if (rc) {
3103/* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */ 3110/* rc = map_smb_to_linux_error(smb_buffer_response) done in SendReceive now */
3104 } else if ((smb_buffer_response->WordCount == 3) 3111 } else if ((smb_buffer_response->WordCount == 3) ||
3105 || (smb_buffer_response->WordCount == 4)) { 3112 (smb_buffer_response->WordCount == 4)) {
3106 __u16 action = le16_to_cpu(pSMBr->resp.Action); 3113 __u16 action = le16_to_cpu(pSMBr->resp.Action);
3107 __u16 blob_len = 3114 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
3108 le16_to_cpu(pSMBr->resp.SecurityBlobLength);
3109 if (action & GUEST_LOGIN) 3115 if (action & GUEST_LOGIN)
3110 cFYI(1, (" Guest login")); /* BB Should we set anything 3116 cFYI(1, (" Guest login")); /* BB Should we set anything
3111 in SesInfo struct ? */ 3117 in SesInfo struct ? */
@@ -3145,8 +3151,8 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
3145 } else { 3151 } else {
3146 remaining_words = BCC(smb_buffer_response) / 2; 3152 remaining_words = BCC(smb_buffer_response) / 2;
3147 } 3153 }
3148 len = 3154 len = UniStrnlen((wchar_t *) bcc_ptr,
3149 UniStrnlen((wchar_t *) bcc_ptr,remaining_words - 1); 3155 remaining_words - 1);
3150/* We look for obvious messed up bcc or strings in response so we do not go off 3156/* We look for obvious messed up bcc or strings in response so we do not go off
3151 the end since (at least) WIN2K and Windows XP have a major bug in not null 3157 the end since (at least) WIN2K and Windows XP have a major bug in not null
3152 terminating last Unicode string in response */ 3158 terminating last Unicode string in response */
@@ -3230,7 +3236,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
3230 <= BCC(smb_buffer_response)) { 3236 <= BCC(smb_buffer_response)) {
3231 if (ses->serverOS) 3237 if (ses->serverOS)
3232 kfree(ses->serverOS); 3238 kfree(ses->serverOS);
3233 ses->serverOS = kzalloc(len + 1,GFP_KERNEL); 3239 ses->serverOS = kzalloc(len + 1, GFP_KERNEL);
3234 strncpy(ses->serverOS,bcc_ptr, len); 3240 strncpy(ses->serverOS,bcc_ptr, len);
3235 3241
3236 bcc_ptr += len; 3242 bcc_ptr += len;
@@ -3259,28 +3265,24 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
3259 bcc_ptr[0] = 0; 3265 bcc_ptr[0] = 0;
3260 bcc_ptr++; 3266 bcc_ptr++;
3261 } else 3267 } else
3262 cFYI(1, 3268 cFYI(1, ("field of length %d "
3263 ("field of length %d "
3264 "extends beyond end of smb ", 3269 "extends beyond end of smb ",
3265 len)); 3270 len));
3266 } 3271 }
3267 } else { 3272 } else {
3268 cERROR(1, 3273 cERROR(1, ("Security Blob extends beyond end "
3269 (" Security Blob extends beyond end "
3270 "of SMB")); 3274 "of SMB"));
3271 } 3275 }
3272 } else { 3276 } else {
3273 cERROR(1, ("No session structure passed in.")); 3277 cERROR(1, ("No session structure passed in."));
3274 } 3278 }
3275 } else { 3279 } else {
3276 cERROR(1, 3280 cERROR(1, ("Invalid Word count %d: ",
3277 (" Invalid Word count %d: ",
3278 smb_buffer_response->WordCount)); 3281 smb_buffer_response->WordCount));
3279 rc = -EIO; 3282 rc = -EIO;
3280 } 3283 }
3281 3284
3282 if (smb_buffer) 3285 cifs_buf_release(smb_buffer);
3283 cifs_buf_release(smb_buffer);
3284 3286
3285 return rc; 3287 return rc;
3286} 3288}
@@ -3389,6 +3391,18 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
3389 bcc_ptr = pByteArea(smb_buffer_response); 3391 bcc_ptr = pByteArea(smb_buffer_response);
3390 length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2); 3392 length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2);
3391 /* skip service field (NB: this field is always ASCII) */ 3393 /* skip service field (NB: this field is always ASCII) */
3394 if (length == 3) {
3395 if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') &&
3396 (bcc_ptr[2] == 'C')) {
3397 cFYI(1, ("IPC connection"));
3398 tcon->ipc = 1;
3399 }
3400 } else if (length == 2) {
3401 if ((bcc_ptr[0] == 'A') && (bcc_ptr[1] == ':')) {
3402 /* the most common case */
3403 cFYI(1, ("disk share connection"));
3404 }
3405 }
3392 bcc_ptr += length + 1; 3406 bcc_ptr += length + 1;
3393 strncpy(tcon->treeName, tree, MAX_TREE_SIZE); 3407 strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
3394 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) { 3408 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
@@ -3399,9 +3413,11 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
3399 kfree(tcon->nativeFileSystem); 3413 kfree(tcon->nativeFileSystem);
3400 tcon->nativeFileSystem = 3414 tcon->nativeFileSystem =
3401 kzalloc(length + 2, GFP_KERNEL); 3415 kzalloc(length + 2, GFP_KERNEL);
3402 cifs_strfromUCS_le(tcon->nativeFileSystem, 3416 if (tcon->nativeFileSystem)
3403 (__le16 *) bcc_ptr, 3417 cifs_strfromUCS_le(
3404 length, nls_codepage); 3418 tcon->nativeFileSystem,
3419 (__le16 *) bcc_ptr,
3420 length, nls_codepage);
3405 bcc_ptr += 2 * length; 3421 bcc_ptr += 2 * length;
3406 bcc_ptr[0] = 0; /* null terminate the string */ 3422 bcc_ptr[0] = 0; /* null terminate the string */
3407 bcc_ptr[1] = 0; 3423 bcc_ptr[1] = 0;
@@ -3416,8 +3432,9 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
3416 kfree(tcon->nativeFileSystem); 3432 kfree(tcon->nativeFileSystem);
3417 tcon->nativeFileSystem = 3433 tcon->nativeFileSystem =
3418 kzalloc(length + 1, GFP_KERNEL); 3434 kzalloc(length + 1, GFP_KERNEL);
3419 strncpy(tcon->nativeFileSystem, bcc_ptr, 3435 if (tcon->nativeFileSystem)
3420 length); 3436 strncpy(tcon->nativeFileSystem, bcc_ptr,
3437 length);
3421 } 3438 }
3422 /* else do not bother copying these information fields*/ 3439 /* else do not bother copying these information fields*/
3423 } 3440 }
@@ -3433,8 +3450,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
3433 ses->ipc_tid = smb_buffer_response->Tid; 3450 ses->ipc_tid = smb_buffer_response->Tid;
3434 } 3451 }
3435 3452
3436 if (smb_buffer) 3453 cifs_buf_release(smb_buffer);
3437 cifs_buf_release(smb_buffer);
3438 return rc; 3454 return rc;
3439} 3455}
3440 3456
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 4830acc86d74..793404b10925 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -3,7 +3,7 @@
3 * 3 *
4 * vfs operations that deal with dentries 4 * vfs operations that deal with dentries
5 * 5 *
6 * Copyright (C) International Business Machines Corp., 2002,2005 6 * Copyright (C) International Business Machines Corp., 2002,2007
7 * Author(s): Steve French (sfrench@us.ibm.com) 7 * Author(s): Steve French (sfrench@us.ibm.com)
8 * 8 *
9 * This library is free software; you can redistribute it and/or modify 9 * This library is free software; you can redistribute it and/or modify
@@ -269,7 +269,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
269 CIFSSMBClose(xid, pTcon, fileHandle); 269 CIFSSMBClose(xid, pTcon, fileHandle);
270 } else if (newinode) { 270 } else if (newinode) {
271 pCifsFile = 271 pCifsFile =
272 kzalloc(sizeof (struct cifsFileInfo), GFP_KERNEL); 272 kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
273 273
274 if (pCifsFile == NULL) 274 if (pCifsFile == NULL)
275 goto cifs_create_out; 275 goto cifs_create_out;
@@ -397,7 +397,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
397 /* BB Do not bother to decode buf since no 397 /* BB Do not bother to decode buf since no
398 local inode yet to put timestamps in, 398 local inode yet to put timestamps in,
399 but we can reuse it safely */ 399 but we can reuse it safely */
400 int bytes_written; 400 unsigned int bytes_written;
401 struct win_dev *pdev; 401 struct win_dev *pdev;
402 pdev = (struct win_dev *)buf; 402 pdev = (struct win_dev *)buf;
403 if (S_ISCHR(mode)) { 403 if (S_ISCHR(mode)) {
@@ -450,8 +450,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
450 450
451 xid = GetXid(); 451 xid = GetXid();
452 452
453 cFYI(1, 453 cFYI(1, (" parent inode = 0x%p name is: %s and dentry = 0x%p",
454 (" parent inode = 0x%p name is: %s and dentry = 0x%p",
455 parent_dir_inode, direntry->d_name.name, direntry)); 454 parent_dir_inode, direntry->d_name.name, direntry));
456 455
457 /* check whether path exists */ 456 /* check whether path exists */
diff --git a/fs/cifs/export.c b/fs/cifs/export.c
index 893fd0aebff8..d614b91caeca 100644
--- a/fs/cifs/export.c
+++ b/fs/cifs/export.c
@@ -43,6 +43,7 @@
43#include <linux/exportfs.h> 43#include <linux/exportfs.h>
44#include "cifsglob.h" 44#include "cifsglob.h"
45#include "cifs_debug.h" 45#include "cifs_debug.h"
46#include "cifsfs.h"
46 47
47#ifdef CONFIG_CIFS_EXPERIMENTAL 48#ifdef CONFIG_CIFS_EXPERIMENTAL
48static struct dentry *cifs_get_parent(struct dentry *dentry) 49static struct dentry *cifs_get_parent(struct dentry *dentry)
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 894b1f7b299d..1e7e4c06d9e3 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -467,7 +467,7 @@ reopen_error_exit:
467int cifs_close(struct inode *inode, struct file *file) 467int cifs_close(struct inode *inode, struct file *file)
468{ 468{
469 int rc = 0; 469 int rc = 0;
470 int xid; 470 int xid, timeout;
471 struct cifs_sb_info *cifs_sb; 471 struct cifs_sb_info *cifs_sb;
472 struct cifsTconInfo *pTcon; 472 struct cifsTconInfo *pTcon;
473 struct cifsFileInfo *pSMBFile = 473 struct cifsFileInfo *pSMBFile =
@@ -485,9 +485,9 @@ int cifs_close(struct inode *inode, struct file *file)
485 /* no sense reconnecting to close a file that is 485 /* no sense reconnecting to close a file that is
486 already closed */ 486 already closed */
487 if (pTcon->tidStatus != CifsNeedReconnect) { 487 if (pTcon->tidStatus != CifsNeedReconnect) {
488 int timeout = 2; 488 timeout = 2;
489 while ((atomic_read(&pSMBFile->wrtPending) != 0) 489 while ((atomic_read(&pSMBFile->wrtPending) != 0)
490 && (timeout < 1000) ) { 490 && (timeout <= 2048)) {
491 /* Give write a better chance to get to 491 /* Give write a better chance to get to
492 server ahead of the close. We do not 492 server ahead of the close. We do not
493 want to add a wait_q here as it would 493 want to add a wait_q here as it would
@@ -522,12 +522,30 @@ int cifs_close(struct inode *inode, struct file *file)
522 list_del(&pSMBFile->flist); 522 list_del(&pSMBFile->flist);
523 list_del(&pSMBFile->tlist); 523 list_del(&pSMBFile->tlist);
524 write_unlock(&GlobalSMBSeslock); 524 write_unlock(&GlobalSMBSeslock);
525 timeout = 10;
526 /* We waited above to give the SMBWrite a chance to issue
527 on the wire (so we do not get SMBWrite returning EBADF
528 if writepages is racing with close. Note that writepages
529 does not specify a file handle, so it is possible for a file
530 to be opened twice, and the application close the "wrong"
531 file handle - in these cases we delay long enough to allow
532 the SMBWrite to get on the wire before the SMB Close.
533 We allow total wait here over 45 seconds, more than
534 oplock break time, and more than enough to allow any write
535 to complete on the server, or to time out on the client */
536 while ((atomic_read(&pSMBFile->wrtPending) != 0)
537 && (timeout <= 50000)) {
538 cERROR(1, ("writes pending, delay free of handle"));
539 msleep(timeout);
540 timeout *= 8;
541 }
525 kfree(pSMBFile->search_resume_name); 542 kfree(pSMBFile->search_resume_name);
526 kfree(file->private_data); 543 kfree(file->private_data);
527 file->private_data = NULL; 544 file->private_data = NULL;
528 } else 545 } else
529 rc = -EBADF; 546 rc = -EBADF;
530 547
548 read_lock(&GlobalSMBSeslock);
531 if (list_empty(&(CIFS_I(inode)->openFileList))) { 549 if (list_empty(&(CIFS_I(inode)->openFileList))) {
532 cFYI(1, ("closing last open instance for inode %p", inode)); 550 cFYI(1, ("closing last open instance for inode %p", inode));
533 /* if the file is not open we do not know if we can cache info 551 /* if the file is not open we do not know if we can cache info
@@ -535,6 +553,7 @@ int cifs_close(struct inode *inode, struct file *file)
535 CIFS_I(inode)->clientCanCacheRead = FALSE; 553 CIFS_I(inode)->clientCanCacheRead = FALSE;
536 CIFS_I(inode)->clientCanCacheAll = FALSE; 554 CIFS_I(inode)->clientCanCacheAll = FALSE;
537 } 555 }
556 read_unlock(&GlobalSMBSeslock);
538 if ((rc == 0) && CIFS_I(inode)->write_behind_rc) 557 if ((rc == 0) && CIFS_I(inode)->write_behind_rc)
539 rc = CIFS_I(inode)->write_behind_rc; 558 rc = CIFS_I(inode)->write_behind_rc;
540 FreeXid(xid); 559 FreeXid(xid);
@@ -767,7 +786,8 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
767 mutex_lock(&fid->lock_mutex); 786 mutex_lock(&fid->lock_mutex);
768 list_for_each_entry_safe(li, tmp, &fid->llist, llist) { 787 list_for_each_entry_safe(li, tmp, &fid->llist, llist) {
769 if (pfLock->fl_start <= li->offset && 788 if (pfLock->fl_start <= li->offset &&
770 length >= li->length) { 789 (pfLock->fl_start + length) >=
790 (li->offset + li->length)) {
771 stored_rc = CIFSSMBLock(xid, pTcon, 791 stored_rc = CIFSSMBLock(xid, pTcon,
772 netfid, 792 netfid,
773 li->length, li->offset, 793 li->length, li->offset,
@@ -1022,6 +1042,7 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode)
1022 } 1042 }
1023 1043
1024 read_lock(&GlobalSMBSeslock); 1044 read_lock(&GlobalSMBSeslock);
1045refind_writable:
1025 list_for_each_entry(open_file, &cifs_inode->openFileList, flist) { 1046 list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
1026 if (open_file->closePend) 1047 if (open_file->closePend)
1027 continue; 1048 continue;
@@ -1029,24 +1050,49 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode)
1029 ((open_file->pfile->f_flags & O_RDWR) || 1050 ((open_file->pfile->f_flags & O_RDWR) ||
1030 (open_file->pfile->f_flags & O_WRONLY))) { 1051 (open_file->pfile->f_flags & O_WRONLY))) {
1031 atomic_inc(&open_file->wrtPending); 1052 atomic_inc(&open_file->wrtPending);
1053
1054 if (!open_file->invalidHandle) {
1055 /* found a good writable file */
1056 read_unlock(&GlobalSMBSeslock);
1057 return open_file;
1058 }
1059
1032 read_unlock(&GlobalSMBSeslock); 1060 read_unlock(&GlobalSMBSeslock);
1033 if ((open_file->invalidHandle) && 1061 /* Had to unlock since following call can block */
1034 (!open_file->closePend) /* BB fixme -since the second clause can not be true remove it BB */) { 1062 rc = cifs_reopen_file(open_file->pfile, FALSE);
1035 rc = cifs_reopen_file(open_file->pfile, FALSE); 1063 if (!rc) {
1036 /* if it fails, try another handle - might be */ 1064 if (!open_file->closePend)
1037 /* dangerous to hold up writepages with retry */ 1065 return open_file;
1038 if (rc) { 1066 else { /* start over in case this was deleted */
1039 cFYI(1, 1067 /* since the list could be modified */
1040 ("failed on reopen file in wp"));
1041 read_lock(&GlobalSMBSeslock); 1068 read_lock(&GlobalSMBSeslock);
1042 /* can not use this handle, no write 1069 atomic_dec(&open_file->wrtPending);
1043 pending on this one after all */ 1070 goto refind_writable;
1044 atomic_dec
1045 (&open_file->wrtPending);
1046 continue;
1047 } 1071 }
1048 } 1072 }
1049 return open_file; 1073
1074 /* if it fails, try another handle if possible -
1075 (we can not do this if closePending since
1076 loop could be modified - in which case we
1077 have to start at the beginning of the list
1078 again. Note that it would be bad
1079 to hold up writepages here (rather than
1080 in caller) with continuous retries */
1081 cFYI(1, ("wp failed on reopen file"));
1082 read_lock(&GlobalSMBSeslock);
1083 /* can not use this handle, no write
1084 pending on this one after all */
1085 atomic_dec(&open_file->wrtPending);
1086
1087 if (open_file->closePend) /* list could have changed */
1088 goto refind_writable;
1089 /* else we simply continue to the next entry. Thus
1090 we do not loop on reopen errors. If we
1091 can not reopen the file, for example if we
1092 reconnected to a server with another client
1093 racing to delete or lock the file we would not
1094 make progress if we restarted before the beginning
1095 of the loop here. */
1050 } 1096 }
1051 } 1097 }
1052 read_unlock(&GlobalSMBSeslock); 1098 read_unlock(&GlobalSMBSeslock);
@@ -1709,7 +1755,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
1709 struct page *page; 1755 struct page *page;
1710 struct cifs_sb_info *cifs_sb; 1756 struct cifs_sb_info *cifs_sb;
1711 struct cifsTconInfo *pTcon; 1757 struct cifsTconInfo *pTcon;
1712 int bytes_read = 0; 1758 unsigned int bytes_read = 0;
1713 unsigned int read_size, i; 1759 unsigned int read_size, i;
1714 char *smb_read_data = NULL; 1760 char *smb_read_data = NULL;
1715 struct smb_com_read_rsp *pSMBr; 1761 struct smb_com_read_rsp *pSMBr;
@@ -1803,7 +1849,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
1803 1849
1804 i += bytes_read >> PAGE_CACHE_SHIFT; 1850 i += bytes_read >> PAGE_CACHE_SHIFT;
1805 cifs_stats_bytes_read(pTcon, bytes_read); 1851 cifs_stats_bytes_read(pTcon, bytes_read);
1806 if ((int)(bytes_read & PAGE_CACHE_MASK) != bytes_read) { 1852 if ((bytes_read & PAGE_CACHE_MASK) != bytes_read) {
1807 i++; /* account for partial page */ 1853 i++; /* account for partial page */
1808 1854
1809 /* server copy of file can have smaller size 1855 /* server copy of file can have smaller size
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 279f3c5e0ce3..5e8b388be3b6 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -115,7 +115,7 @@ int cifs_get_inode_info_unix(struct inode **pinode,
115 inode->i_mode = le64_to_cpu(findData.Permissions); 115 inode->i_mode = le64_to_cpu(findData.Permissions);
116 /* since we set the inode type below we need to mask off 116 /* since we set the inode type below we need to mask off
117 to avoid strange results if bits set above */ 117 to avoid strange results if bits set above */
118 inode->i_mode &= ~S_IFMT; 118 inode->i_mode &= ~S_IFMT;
119 if (type == UNIX_FILE) { 119 if (type == UNIX_FILE) {
120 inode->i_mode |= S_IFREG; 120 inode->i_mode |= S_IFREG;
121 } else if (type == UNIX_SYMLINK) { 121 } else if (type == UNIX_SYMLINK) {
@@ -575,19 +575,33 @@ int cifs_get_inode_info(struct inode **pinode,
575 return rc; 575 return rc;
576} 576}
577 577
578static const struct inode_operations cifs_ipc_inode_ops = {
579 .lookup = cifs_lookup,
580};
581
578/* gets root inode */ 582/* gets root inode */
579void cifs_read_inode(struct inode *inode) 583void cifs_read_inode(struct inode *inode)
580{ 584{
581 int xid; 585 int xid, rc;
582 struct cifs_sb_info *cifs_sb; 586 struct cifs_sb_info *cifs_sb;
583 587
584 cifs_sb = CIFS_SB(inode->i_sb); 588 cifs_sb = CIFS_SB(inode->i_sb);
585 xid = GetXid(); 589 xid = GetXid();
586 590
587 if (cifs_sb->tcon->unix_ext) 591 if (cifs_sb->tcon->unix_ext)
588 cifs_get_inode_info_unix(&inode, "", inode->i_sb, xid); 592 rc = cifs_get_inode_info_unix(&inode, "", inode->i_sb, xid);
589 else 593 else
590 cifs_get_inode_info(&inode, "", NULL, inode->i_sb, xid); 594 rc = cifs_get_inode_info(&inode, "", NULL, inode->i_sb, xid);
595 if (rc && cifs_sb->tcon->ipc) {
596 cFYI(1, ("ipc connection - fake read inode"));
597 inode->i_mode |= S_IFDIR;
598 inode->i_nlink = 2;
599 inode->i_op = &cifs_ipc_inode_ops;
600 inode->i_fop = &simple_dir_operations;
601 inode->i_uid = cifs_sb->mnt_uid;
602 inode->i_gid = cifs_sb->mnt_gid;
603 }
604
591 /* can not call macro FreeXid here since in a void func */ 605 /* can not call macro FreeXid here since in a void func */
592 _FreeXid(xid); 606 _FreeXid(xid);
593} 607}
@@ -919,18 +933,25 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
919 goto mkdir_out; 933 goto mkdir_out;
920 } 934 }
921 935
936 mode &= ~current->fs->umask;
922 rc = CIFSPOSIXCreate(xid, pTcon, SMB_O_DIRECTORY | SMB_O_CREAT, 937 rc = CIFSPOSIXCreate(xid, pTcon, SMB_O_DIRECTORY | SMB_O_CREAT,
923 mode, NULL /* netfid */, pInfo, &oplock, 938 mode, NULL /* netfid */, pInfo, &oplock,
924 full_path, cifs_sb->local_nls, 939 full_path, cifs_sb->local_nls,
925 cifs_sb->mnt_cifs_flags & 940 cifs_sb->mnt_cifs_flags &
926 CIFS_MOUNT_MAP_SPECIAL_CHR); 941 CIFS_MOUNT_MAP_SPECIAL_CHR);
927 if (rc) { 942 if (rc == -EOPNOTSUPP) {
943 kfree(pInfo);
944 goto mkdir_retry_old;
945 } else if (rc) {
928 cFYI(1, ("posix mkdir returned 0x%x", rc)); 946 cFYI(1, ("posix mkdir returned 0x%x", rc));
929 d_drop(direntry); 947 d_drop(direntry);
930 } else { 948 } else {
931 int obj_type; 949 int obj_type;
932 if (pInfo->Type == -1) /* no return info - go query */ 950 if (pInfo->Type == cpu_to_le32(-1)) {
951 /* no return info, go query for it */
952 kfree(pInfo);
933 goto mkdir_get_info; 953 goto mkdir_get_info;
954 }
934/*BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if need 955/*BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if need
935 to set uid/gid */ 956 to set uid/gid */
936 inc_nlink(inode); 957 inc_nlink(inode);
@@ -940,8 +961,10 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
940 direntry->d_op = &cifs_dentry_ops; 961 direntry->d_op = &cifs_dentry_ops;
941 962
942 newinode = new_inode(inode->i_sb); 963 newinode = new_inode(inode->i_sb);
943 if (newinode == NULL) 964 if (newinode == NULL) {
965 kfree(pInfo);
944 goto mkdir_get_info; 966 goto mkdir_get_info;
967 }
945 /* Is an i_ino of zero legal? */ 968 /* Is an i_ino of zero legal? */
946 /* Are there sanity checks we can use to ensure that 969 /* Are there sanity checks we can use to ensure that
947 the server is really filling in that field? */ 970 the server is really filling in that field? */
@@ -972,7 +995,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
972 kfree(pInfo); 995 kfree(pInfo);
973 goto mkdir_out; 996 goto mkdir_out;
974 } 997 }
975 998mkdir_retry_old:
976 /* BB add setting the equivalent of mode via CreateX w/ACLs */ 999 /* BB add setting the equivalent of mode via CreateX w/ACLs */
977 rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls, 1000 rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls,
978 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 1001 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
@@ -1377,8 +1400,17 @@ static int cifs_vmtruncate(struct inode *inode, loff_t offset)
1377 } 1400 }
1378 i_size_write(inode, offset); 1401 i_size_write(inode, offset);
1379 spin_unlock(&inode->i_lock); 1402 spin_unlock(&inode->i_lock);
1403 /*
1404 * unmap_mapping_range is called twice, first simply for efficiency
1405 * so that truncate_inode_pages does fewer single-page unmaps. However
1406 * after this first call, and before truncate_inode_pages finishes,
1407 * it is possible for private pages to be COWed, which remain after
1408 * truncate_inode_pages finishes, hence the second unmap_mapping_range
1409 * call must be made for correctness.
1410 */
1380 unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1); 1411 unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1);
1381 truncate_inode_pages(mapping, offset); 1412 truncate_inode_pages(mapping, offset);
1413 unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1);
1382 goto out_truncate; 1414 goto out_truncate;
1383 1415
1384do_expand: 1416do_expand:
@@ -1469,7 +1501,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
1469 atomic_dec(&open_file->wrtPending); 1501 atomic_dec(&open_file->wrtPending);
1470 cFYI(1, ("SetFSize for attrs rc = %d", rc)); 1502 cFYI(1, ("SetFSize for attrs rc = %d", rc));
1471 if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) { 1503 if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
1472 int bytes_written; 1504 unsigned int bytes_written;
1473 rc = CIFSSMBWrite(xid, pTcon, 1505 rc = CIFSSMBWrite(xid, pTcon,
1474 nfid, 0, attrs->ia_size, 1506 nfid, 0, attrs->ia_size,
1475 &bytes_written, NULL, NULL, 1507 &bytes_written, NULL, NULL,
@@ -1502,7 +1534,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
1502 cifs_sb->mnt_cifs_flags & 1534 cifs_sb->mnt_cifs_flags &
1503 CIFS_MOUNT_MAP_SPECIAL_CHR); 1535 CIFS_MOUNT_MAP_SPECIAL_CHR);
1504 if (rc == 0) { 1536 if (rc == 0) {
1505 int bytes_written; 1537 unsigned int bytes_written;
1506 rc = CIFSSMBWrite(xid, pTcon, 1538 rc = CIFSSMBWrite(xid, pTcon,
1507 netfid, 0, 1539 netfid, 0,
1508 attrs->ia_size, 1540 attrs->ia_size,
diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index 6a85ef7b8797..11f265726db7 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -237,7 +237,7 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen)
237 char *tmp_path = NULL; 237 char *tmp_path = NULL;
238 char *tmpbuffer; 238 char *tmpbuffer;
239 unsigned char *referrals = NULL; 239 unsigned char *referrals = NULL;
240 int num_referrals = 0; 240 unsigned int num_referrals = 0;
241 int len; 241 int len;
242 __u16 fid; 242 __u16 fid;
243 243
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index 0bcec0844bee..51ec681fe74a 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -169,7 +169,6 @@ cifs_buf_get(void)
169void 169void
170cifs_buf_release(void *buf_to_free) 170cifs_buf_release(void *buf_to_free)
171{ 171{
172
173 if (buf_to_free == NULL) { 172 if (buf_to_free == NULL) {
174 /* cFYI(1, ("Null buffer passed to cifs_buf_release"));*/ 173 /* cFYI(1, ("Null buffer passed to cifs_buf_release"));*/
175 return; 174 return;
diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c
index 2bfed3f45d0f..f06359cb22ee 100644
--- a/fs/cifs/netmisc.c
+++ b/fs/cifs/netmisc.c
@@ -114,10 +114,16 @@ static const struct smb_to_posix_error mapping_table_ERRSRV[] = {
114 {ERRusempx, -EIO}, 114 {ERRusempx, -EIO},
115 {ERRusestd, -EIO}, 115 {ERRusestd, -EIO},
116 {ERR_NOTIFY_ENUM_DIR, -ENOBUFS}, 116 {ERR_NOTIFY_ENUM_DIR, -ENOBUFS},
117 {ERRaccountexpired, -EACCES}, 117 {ERRnoSuchUser, -EACCES},
118/* {ERRaccountexpired, -EACCES},
118 {ERRbadclient, -EACCES}, 119 {ERRbadclient, -EACCES},
119 {ERRbadLogonTime, -EACCES}, 120 {ERRbadLogonTime, -EACCES},
120 {ERRpasswordExpired, -EACCES}, 121 {ERRpasswordExpired, -EACCES},*/
122 {ERRaccountexpired, -EKEYEXPIRED},
123 {ERRbadclient, -EACCES},
124 {ERRbadLogonTime, -EACCES},
125 {ERRpasswordExpired, -EKEYEXPIRED},
126
121 {ERRnosupport, -EINVAL}, 127 {ERRnosupport, -EINVAL},
122 {0, 0} 128 {0, 0}
123}; 129};
@@ -270,7 +276,7 @@ static const struct {
270 from NT_STATUS_NO_SUCH_USER to NT_STATUS_LOGON_FAILURE 276 from NT_STATUS_NO_SUCH_USER to NT_STATUS_LOGON_FAILURE
271 during the session setup } */ 277 during the session setup } */
272 { 278 {
273 ERRDOS, ERRnoaccess, NT_STATUS_NO_SUCH_USER}, { 279 ERRDOS, ERRnoaccess, NT_STATUS_NO_SUCH_USER}, { /* could map to 2238 */
274 ERRHRD, ERRgeneral, NT_STATUS_GROUP_EXISTS}, { 280 ERRHRD, ERRgeneral, NT_STATUS_GROUP_EXISTS}, {
275 ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_GROUP}, { 281 ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_GROUP}, {
276 ERRHRD, ERRgeneral, NT_STATUS_MEMBER_IN_GROUP}, { 282 ERRHRD, ERRgeneral, NT_STATUS_MEMBER_IN_GROUP}, {
@@ -285,10 +291,10 @@ static const struct {
285 ERRHRD, ERRgeneral, NT_STATUS_PASSWORD_RESTRICTION}, { 291 ERRHRD, ERRgeneral, NT_STATUS_PASSWORD_RESTRICTION}, {
286 ERRDOS, ERRnoaccess, NT_STATUS_LOGON_FAILURE}, { 292 ERRDOS, ERRnoaccess, NT_STATUS_LOGON_FAILURE}, {
287 ERRHRD, ERRgeneral, NT_STATUS_ACCOUNT_RESTRICTION}, { 293 ERRHRD, ERRgeneral, NT_STATUS_ACCOUNT_RESTRICTION}, {
288 ERRSRV, 2241, NT_STATUS_INVALID_LOGON_HOURS}, { 294 ERRSRV, ERRbadLogonTime, NT_STATUS_INVALID_LOGON_HOURS}, {
289 ERRSRV, 2240, NT_STATUS_INVALID_WORKSTATION}, { 295 ERRSRV, ERRbadclient, NT_STATUS_INVALID_WORKSTATION}, {
290 ERRSRV, ERRpasswordExpired, NT_STATUS_PASSWORD_EXPIRED}, { 296 ERRSRV, ERRpasswordExpired, NT_STATUS_PASSWORD_EXPIRED}, {
291 ERRSRV, 2239, NT_STATUS_ACCOUNT_DISABLED}, { 297 ERRSRV, ERRaccountexpired, NT_STATUS_ACCOUNT_DISABLED}, {
292 ERRHRD, ERRgeneral, NT_STATUS_NONE_MAPPED}, { 298 ERRHRD, ERRgeneral, NT_STATUS_NONE_MAPPED}, {
293 ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_LUIDS_REQUESTED}, { 299 ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_LUIDS_REQUESTED}, {
294 ERRHRD, ERRgeneral, NT_STATUS_LUIDS_EXHAUSTED}, { 300 ERRHRD, ERRgeneral, NT_STATUS_LUIDS_EXHAUSTED}, {
@@ -585,7 +591,7 @@ static const struct {
585 ERRDOS, ERRnoaccess, NT_STATUS_TRUST_FAILURE}, { 591 ERRDOS, ERRnoaccess, NT_STATUS_TRUST_FAILURE}, {
586 ERRHRD, ERRgeneral, NT_STATUS_MUTANT_LIMIT_EXCEEDED}, { 592 ERRHRD, ERRgeneral, NT_STATUS_MUTANT_LIMIT_EXCEEDED}, {
587 ERRDOS, ERRnetlogonNotStarted, NT_STATUS_NETLOGON_NOT_STARTED}, { 593 ERRDOS, ERRnetlogonNotStarted, NT_STATUS_NETLOGON_NOT_STARTED}, {
588 ERRSRV, 2239, NT_STATUS_ACCOUNT_EXPIRED}, { 594 ERRSRV, ERRaccountexpired, NT_STATUS_ACCOUNT_EXPIRED}, {
589 ERRHRD, ERRgeneral, NT_STATUS_POSSIBLE_DEADLOCK}, { 595 ERRHRD, ERRgeneral, NT_STATUS_POSSIBLE_DEADLOCK}, {
590 ERRHRD, ERRgeneral, NT_STATUS_NETWORK_CREDENTIAL_CONFLICT}, { 596 ERRHRD, ERRgeneral, NT_STATUS_NETWORK_CREDENTIAL_CONFLICT}, {
591 ERRHRD, ERRgeneral, NT_STATUS_REMOTE_SESSION_LIMIT}, { 597 ERRHRD, ERRgeneral, NT_STATUS_REMOTE_SESSION_LIMIT}, {
@@ -754,7 +760,7 @@ ntstatus_to_dos(__u32 ntstatus, __u8 * eclass, __u16 * ecode)
754} 760}
755 761
756int 762int
757map_smb_to_linux_error(struct smb_hdr *smb) 763map_smb_to_linux_error(struct smb_hdr *smb, int logErr)
758{ 764{
759 unsigned int i; 765 unsigned int i;
760 int rc = -EIO; /* if transport error smb error may not be set */ 766 int rc = -EIO; /* if transport error smb error may not be set */
@@ -771,7 +777,9 @@ map_smb_to_linux_error(struct smb_hdr *smb)
771 /* translate the newer STATUS codes to old style SMB errors 777 /* translate the newer STATUS codes to old style SMB errors
772 * and then to POSIX errors */ 778 * and then to POSIX errors */
773 __u32 err = le32_to_cpu(smb->Status.CifsError); 779 __u32 err = le32_to_cpu(smb->Status.CifsError);
774 if (cifsFYI & CIFS_RC) 780 if (logErr && (err != (NT_STATUS_MORE_PROCESSING_REQUIRED)))
781 cifs_print_status(err);
782 else if (cifsFYI & CIFS_RC)
775 cifs_print_status(err); 783 cifs_print_status(err);
776 ntstatus_to_dos(err, &smberrclass, &smberrcode); 784 ntstatus_to_dos(err, &smberrclass, &smberrcode);
777 } else { 785 } else {
@@ -813,7 +821,7 @@ map_smb_to_linux_error(struct smb_hdr *smb)
813 } 821 }
814 /* else ERRHRD class errors or junk - return EIO */ 822 /* else ERRHRD class errors or junk - return EIO */
815 823
816 cFYI(1, (" !!Mapping smb error code %d to POSIX err %d !!", 824 cFYI(1, ("Mapping smb error code %d to POSIX err %d",
817 smberrcode, rc)); 825 smberrcode, rc));
818 826
819 /* generic corrective action e.g. reconnect SMB session on 827 /* generic corrective action e.g. reconnect SMB session on
@@ -899,8 +907,11 @@ struct timespec cnvrtDosUnixTm(__u16 date, __u16 time)
899 cERROR(1, ("illegal hours %d", st->Hours)); 907 cERROR(1, ("illegal hours %d", st->Hours));
900 days = sd->Day; 908 days = sd->Day;
901 month = sd->Month; 909 month = sd->Month;
902 if ((days > 31) || (month > 12)) 910 if ((days > 31) || (month > 12)) {
903 cERROR(1, ("illegal date, month %d day: %d", month, days)); 911 cERROR(1, ("illegal date, month %d day: %d", month, days));
912 if (month > 12)
913 month = 12;
914 }
904 month -= 1; 915 month -= 1;
905 days += total_days_of_prev_months[month]; 916 days += total_days_of_prev_months[month];
906 days += 3652; /* account for difference in days between 1980 and 1970 */ 917 days += 3652; /* account for difference in days between 1980 and 1970 */
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index 916df9431336..3746580e9701 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -121,7 +121,7 @@ static void AdjustForTZ(struct cifsTconInfo *tcon, struct inode *inode)
121 121
122 122
123static void fill_in_inode(struct inode *tmp_inode, int new_buf_type, 123static void fill_in_inode(struct inode *tmp_inode, int new_buf_type,
124 char *buf, int *pobject_type, int isNewInode) 124 char *buf, unsigned int *pobject_type, int isNewInode)
125{ 125{
126 loff_t local_size; 126 loff_t local_size;
127 struct timespec local_mtime; 127 struct timespec local_mtime;
@@ -294,7 +294,7 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type,
294} 294}
295 295
296static void unix_fill_in_inode(struct inode *tmp_inode, 296static void unix_fill_in_inode(struct inode *tmp_inode,
297 FILE_UNIX_INFO *pfindData, int *pobject_type, int isNewInode) 297 FILE_UNIX_INFO *pfindData, unsigned int *pobject_type, int isNewInode)
298{ 298{
299 loff_t local_size; 299 loff_t local_size;
300 struct timespec local_mtime; 300 struct timespec local_mtime;
@@ -826,7 +826,7 @@ static int cifs_filldir(char *pfindEntry, struct file *file,
826 int rc = 0; 826 int rc = 0;
827 struct qstr qstring; 827 struct qstr qstring;
828 struct cifsFileInfo *pCifsF; 828 struct cifsFileInfo *pCifsF;
829 unsigned obj_type; 829 unsigned int obj_type;
830 ino_t inum; 830 ino_t inum;
831 struct cifs_sb_info *cifs_sb; 831 struct cifs_sb_info *cifs_sb;
832 struct inode *tmp_inode; 832 struct inode *tmp_inode;
@@ -1067,7 +1067,7 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
1067 for (i = 0; (i < num_to_fill) && (rc == 0); i++) { 1067 for (i = 0; (i < num_to_fill) && (rc == 0); i++) {
1068 if (current_entry == NULL) { 1068 if (current_entry == NULL) {
1069 /* evaluate whether this case is an error */ 1069 /* evaluate whether this case is an error */
1070 cERROR(1,("past end of SMB num to fill %d i %d", 1070 cERROR(1, ("past SMB end, num to fill %d i %d",
1071 num_to_fill, i)); 1071 num_to_fill, i));
1072 break; 1072 break;
1073 } 1073 }
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
index 892be9b4d1f3..899dc6078d9a 100644
--- a/fs/cifs/sess.c
+++ b/fs/cifs/sess.c
@@ -67,14 +67,59 @@ static __u32 cifs_ssetup_hdr(struct cifsSesInfo *ses, SESSION_SETUP_ANDX *pSMB)
67 pSMB->req.hdr.Flags2 |= SMBFLG2_DFS; 67 pSMB->req.hdr.Flags2 |= SMBFLG2_DFS;
68 capabilities |= CAP_DFS; 68 capabilities |= CAP_DFS;
69 } 69 }
70 if (ses->capabilities & CAP_UNIX) { 70 if (ses->capabilities & CAP_UNIX)
71 capabilities |= CAP_UNIX; 71 capabilities |= CAP_UNIX;
72 }
73 72
74 /* BB check whether to init vcnum BB */ 73 /* BB check whether to init vcnum BB */
75 return capabilities; 74 return capabilities;
76} 75}
77 76
77static void
78unicode_oslm_strings(char **pbcc_area, const struct nls_table *nls_cp)
79{
80 char *bcc_ptr = *pbcc_area;
81 int bytes_ret = 0;
82
83 /* Copy OS version */
84 bytes_ret = cifs_strtoUCS((__le16 *)bcc_ptr, "Linux version ", 32,
85 nls_cp);
86 bcc_ptr += 2 * bytes_ret;
87 bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, init_utsname()->release,
88 32, nls_cp);
89 bcc_ptr += 2 * bytes_ret;
90 bcc_ptr += 2; /* trailing null */
91
92 bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
93 32, nls_cp);
94 bcc_ptr += 2 * bytes_ret;
95 bcc_ptr += 2; /* trailing null */
96
97 *pbcc_area = bcc_ptr;
98}
99
100static void unicode_domain_string(char **pbcc_area, struct cifsSesInfo *ses,
101 const struct nls_table *nls_cp)
102{
103 char *bcc_ptr = *pbcc_area;
104 int bytes_ret = 0;
105
106 /* copy domain */
107 if (ses->domainName == NULL) {
108 /* Sending null domain better than using a bogus domain name (as
109 we did briefly in 2.6.18) since server will use its default */
110 *bcc_ptr = 0;
111 *(bcc_ptr+1) = 0;
112 bytes_ret = 0;
113 } else
114 bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->domainName,
115 256, nls_cp);
116 bcc_ptr += 2 * bytes_ret;
117 bcc_ptr += 2; /* account for null terminator */
118
119 *pbcc_area = bcc_ptr;
120}
121
122
78static void unicode_ssetup_strings(char **pbcc_area, struct cifsSesInfo *ses, 123static void unicode_ssetup_strings(char **pbcc_area, struct cifsSesInfo *ses,
79 const struct nls_table *nls_cp) 124 const struct nls_table *nls_cp)
80{ 125{
@@ -100,32 +145,9 @@ static void unicode_ssetup_strings(char **pbcc_area, struct cifsSesInfo *ses,
100 } 145 }
101 bcc_ptr += 2 * bytes_ret; 146 bcc_ptr += 2 * bytes_ret;
102 bcc_ptr += 2; /* account for null termination */ 147 bcc_ptr += 2; /* account for null termination */
103 /* copy domain */
104 if (ses->domainName == NULL) {
105 /* Sending null domain better than using a bogus domain name (as
106 we did briefly in 2.6.18) since server will use its default */
107 *bcc_ptr = 0;
108 *(bcc_ptr+1) = 0;
109 bytes_ret = 0;
110 } else
111 bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->domainName,
112 256, nls_cp);
113 bcc_ptr += 2 * bytes_ret;
114 bcc_ptr += 2; /* account for null terminator */
115
116 /* Copy OS version */
117 bytes_ret = cifs_strtoUCS((__le16 *)bcc_ptr, "Linux version ", 32,
118 nls_cp);
119 bcc_ptr += 2 * bytes_ret;
120 bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, init_utsname()->release,
121 32, nls_cp);
122 bcc_ptr += 2 * bytes_ret;
123 bcc_ptr += 2; /* trailing null */
124 148
125 bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS, 149 unicode_domain_string(&bcc_ptr, ses, nls_cp);
126 32, nls_cp); 150 unicode_oslm_strings(&bcc_ptr, nls_cp);
127 bcc_ptr += 2 * bytes_ret;
128 bcc_ptr += 2; /* trailing null */
129 151
130 *pbcc_area = bcc_ptr; 152 *pbcc_area = bcc_ptr;
131} 153}
@@ -203,14 +225,11 @@ static int decode_unicode_ssetup(char **pbcc_area, int bleft,
203 if (len >= words_left) 225 if (len >= words_left)
204 return rc; 226 return rc;
205 227
206 if (ses->serverOS) 228 kfree(ses->serverOS);
207 kfree(ses->serverOS);
208 /* UTF-8 string will not grow more than four times as big as UCS-16 */ 229 /* UTF-8 string will not grow more than four times as big as UCS-16 */
209 ses->serverOS = kzalloc(4 * len, GFP_KERNEL); 230 ses->serverOS = kzalloc(4 * len, GFP_KERNEL);
210 if (ses->serverOS != NULL) { 231 if (ses->serverOS != NULL)
211 cifs_strfromUCS_le(ses->serverOS, (__le16 *)data, len, 232 cifs_strfromUCS_le(ses->serverOS, (__le16 *)data, len, nls_cp);
212 nls_cp);
213 }
214 data += 2 * (len + 1); 233 data += 2 * (len + 1);
215 words_left -= len + 1; 234 words_left -= len + 1;
216 235
@@ -220,8 +239,7 @@ static int decode_unicode_ssetup(char **pbcc_area, int bleft,
220 if (len >= words_left) 239 if (len >= words_left)
221 return rc; 240 return rc;
222 241
223 if (ses->serverNOS) 242 kfree(ses->serverNOS);
224 kfree(ses->serverNOS);
225 ses->serverNOS = kzalloc(4 * len, GFP_KERNEL); /* BB this is wrong length FIXME BB */ 243 ses->serverNOS = kzalloc(4 * len, GFP_KERNEL); /* BB this is wrong length FIXME BB */
226 if (ses->serverNOS != NULL) { 244 if (ses->serverNOS != NULL) {
227 cifs_strfromUCS_le(ses->serverNOS, (__le16 *)data, len, 245 cifs_strfromUCS_le(ses->serverNOS, (__le16 *)data, len,
@@ -240,8 +258,7 @@ static int decode_unicode_ssetup(char **pbcc_area, int bleft,
240 if (len > words_left) 258 if (len > words_left)
241 return rc; 259 return rc;
242 260
243 if (ses->serverDomain) 261 kfree(ses->serverDomain);
244 kfree(ses->serverDomain);
245 ses->serverDomain = kzalloc(2 * (len + 1), GFP_KERNEL); /* BB FIXME wrong length */ 262 ses->serverDomain = kzalloc(2 * (len + 1), GFP_KERNEL); /* BB FIXME wrong length */
246 if (ses->serverDomain != NULL) { 263 if (ses->serverDomain != NULL) {
247 cifs_strfromUCS_le(ses->serverDomain, (__le16 *)data, len, 264 cifs_strfromUCS_le(ses->serverDomain, (__le16 *)data, len,
@@ -271,8 +288,7 @@ static int decode_ascii_ssetup(char **pbcc_area, int bleft,
271 if (len >= bleft) 288 if (len >= bleft)
272 return rc; 289 return rc;
273 290
274 if (ses->serverOS) 291 kfree(ses->serverOS);
275 kfree(ses->serverOS);
276 292
277 ses->serverOS = kzalloc(len + 1, GFP_KERNEL); 293 ses->serverOS = kzalloc(len + 1, GFP_KERNEL);
278 if (ses->serverOS) 294 if (ses->serverOS)
@@ -289,8 +305,7 @@ static int decode_ascii_ssetup(char **pbcc_area, int bleft,
289 if (len >= bleft) 305 if (len >= bleft)
290 return rc; 306 return rc;
291 307
292 if (ses->serverNOS) 308 kfree(ses->serverNOS);
293 kfree(ses->serverNOS);
294 309
295 ses->serverNOS = kzalloc(len + 1, GFP_KERNEL); 310 ses->serverNOS = kzalloc(len + 1, GFP_KERNEL);
296 if (ses->serverNOS) 311 if (ses->serverNOS)
@@ -479,7 +494,8 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
479 if (ses->capabilities & CAP_UNICODE) { 494 if (ses->capabilities & CAP_UNICODE) {
480 if (iov[0].iov_len % 2) { 495 if (iov[0].iov_len % 2) {
481 *bcc_ptr = 0; 496 *bcc_ptr = 0;
482 } bcc_ptr++; 497 bcc_ptr++;
498 }
483 unicode_ssetup_strings(&bcc_ptr, ses, nls_cp); 499 unicode_ssetup_strings(&bcc_ptr, ses, nls_cp);
484 } else 500 } else
485 ascii_ssetup_strings(&bcc_ptr, ses, nls_cp); 501 ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
@@ -497,7 +513,8 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
497 513
498 iov[1].iov_base = str_area; 514 iov[1].iov_base = str_area;
499 iov[1].iov_len = count; 515 iov[1].iov_len = count;
500 rc = SendReceive2(xid, ses, iov, 2 /* num_iovecs */, &resp_buf_type, 0); 516 rc = SendReceive2(xid, ses, iov, 2 /* num_iovecs */, &resp_buf_type,
517 0 /* not long op */, 1 /* log NT STATUS if any */ );
501 /* SMB request buf freed in SendReceive2 */ 518 /* SMB request buf freed in SendReceive2 */
502 519
503 cFYI(1, ("ssetup rc from sendrecv2 is %d", rc)); 520 cFYI(1, ("ssetup rc from sendrecv2 is %d", rc));
diff --git a/fs/cifs/smberr.h b/fs/cifs/smberr.h
index 2ef0be288820..7f50e8577c1c 100644
--- a/fs/cifs/smberr.h
+++ b/fs/cifs/smberr.h
@@ -173,9 +173,10 @@
173#define ERRusestd 251 /* temporarily unable to use either raw 173#define ERRusestd 251 /* temporarily unable to use either raw
174 or mpx */ 174 or mpx */
175#define ERR_NOTIFY_ENUM_DIR 1024 175#define ERR_NOTIFY_ENUM_DIR 1024
176#define ERRnoSuchUser 2238 /* user account does not exist */
176#define ERRaccountexpired 2239 177#define ERRaccountexpired 2239
177#define ERRbadclient 2240 178#define ERRbadclient 2240 /* can not logon from this client */
178#define ERRbadLogonTime 2241 179#define ERRbadLogonTime 2241 /* logon hours do not allow this */
179#define ERRpasswordExpired 2242 180#define ERRpasswordExpired 2242
180#define ERRnetlogonNotStarted 2455 181#define ERRnetlogonNotStarted 2455
181#define ERRnosupport 0xFFFF 182#define ERRnosupport 0xFFFF
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index 746bc9405db1..7ed32b3cb781 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -55,7 +55,7 @@ AllocMidQEntry(const struct smb_hdr *smb_buffer, struct cifsSesInfo *ses)
55 if (temp == NULL) 55 if (temp == NULL)
56 return temp; 56 return temp;
57 else { 57 else {
58 memset(temp, 0, sizeof (struct mid_q_entry)); 58 memset(temp, 0, sizeof(struct mid_q_entry));
59 temp->mid = smb_buffer->Mid; /* always LE */ 59 temp->mid = smb_buffer->Mid; /* always LE */
60 temp->pid = current->pid; 60 temp->pid = current->pid;
61 temp->command = smb_buffer->Command; 61 temp->command = smb_buffer->Command;
@@ -158,7 +158,7 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
158 iov.iov_len = len; 158 iov.iov_len = len;
159 159
160 smb_msg.msg_name = sin; 160 smb_msg.msg_name = sin;
161 smb_msg.msg_namelen = sizeof (struct sockaddr); 161 smb_msg.msg_namelen = sizeof(struct sockaddr);
162 smb_msg.msg_control = NULL; 162 smb_msg.msg_control = NULL;
163 smb_msg.msg_controllen = 0; 163 smb_msg.msg_controllen = 0;
164 smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; /* BB add more flags?*/ 164 smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; /* BB add more flags?*/
@@ -228,7 +228,7 @@ smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec,
228 return -ENOTSOCK; /* BB eventually add reconnect code here */ 228 return -ENOTSOCK; /* BB eventually add reconnect code here */
229 229
230 smb_msg.msg_name = sin; 230 smb_msg.msg_name = sin;
231 smb_msg.msg_namelen = sizeof (struct sockaddr); 231 smb_msg.msg_namelen = sizeof(struct sockaddr);
232 smb_msg.msg_control = NULL; 232 smb_msg.msg_control = NULL;
233 smb_msg.msg_controllen = 0; 233 smb_msg.msg_controllen = 0;
234 smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; /* BB add more flags?*/ 234 smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; /* BB add more flags?*/
@@ -363,9 +363,8 @@ static int allocate_mid(struct cifsSesInfo *ses, struct smb_hdr *in_buf,
363 } /* else ok - we are setting up session */ 363 } /* else ok - we are setting up session */
364 } 364 }
365 *ppmidQ = AllocMidQEntry(in_buf, ses); 365 *ppmidQ = AllocMidQEntry(in_buf, ses);
366 if (*ppmidQ == NULL) { 366 if (*ppmidQ == NULL)
367 return -ENOMEM; 367 return -ENOMEM;
368 }
369 return 0; 368 return 0;
370} 369}
371 370
@@ -419,7 +418,7 @@ static int wait_for_response(struct cifsSesInfo *ses,
419int 418int
420SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, 419SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
421 struct kvec *iov, int n_vec, int *pRespBufType /* ret */, 420 struct kvec *iov, int n_vec, int *pRespBufType /* ret */,
422 const int long_op) 421 const int long_op, const int logError)
423{ 422{
424 int rc = 0; 423 int rc = 0;
425 unsigned int receive_len; 424 unsigned int receive_len;
@@ -465,7 +464,6 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
465 wake_up(&ses->server->request_q); 464 wake_up(&ses->server->request_q);
466 return rc; 465 return rc;
467 } 466 }
468
469 rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number); 467 rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number);
470 468
471 midQ->midState = MID_REQUEST_SUBMITTED; 469 midQ->midState = MID_REQUEST_SUBMITTED;
@@ -568,13 +566,11 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
568 } 566 }
569 567
570 /* BB special case reconnect tid and uid here? */ 568 /* BB special case reconnect tid and uid here? */
571 /* BB special case Errbadpassword and pwdexpired here */ 569 rc = map_smb_to_linux_error(midQ->resp_buf, logError);
572 rc = map_smb_to_linux_error(midQ->resp_buf);
573 570
574 /* convert ByteCount if necessary */ 571 /* convert ByteCount if necessary */
575 if (receive_len >= 572 if (receive_len >= sizeof(struct smb_hdr) - 4
576 sizeof (struct smb_hdr) - 573 /* do not count RFC1001 header */ +
577 4 /* do not count RFC1001 header */ +
578 (2 * midQ->resp_buf->WordCount) + 2 /* bcc */ ) 574 (2 * midQ->resp_buf->WordCount) + 2 /* bcc */ )
579 BCC(midQ->resp_buf) = 575 BCC(midQ->resp_buf) =
580 le16_to_cpu(BCC_LE(midQ->resp_buf)); 576 le16_to_cpu(BCC_LE(midQ->resp_buf));
@@ -749,12 +745,11 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
749 *pbytes_returned = out_buf->smb_buf_length; 745 *pbytes_returned = out_buf->smb_buf_length;
750 746
751 /* BB special case reconnect tid and uid here? */ 747 /* BB special case reconnect tid and uid here? */
752 rc = map_smb_to_linux_error(out_buf); 748 rc = map_smb_to_linux_error(out_buf, 0 /* no log */ );
753 749
754 /* convert ByteCount if necessary */ 750 /* convert ByteCount if necessary */
755 if (receive_len >= 751 if (receive_len >= sizeof(struct smb_hdr) - 4
756 sizeof (struct smb_hdr) - 752 /* do not count RFC1001 header */ +
757 4 /* do not count RFC1001 header */ +
758 (2 * out_buf->WordCount) + 2 /* bcc */ ) 753 (2 * out_buf->WordCount) + 2 /* bcc */ )
759 BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf)); 754 BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
760 } else { 755 } else {
@@ -993,12 +988,11 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
993 *pbytes_returned = out_buf->smb_buf_length; 988 *pbytes_returned = out_buf->smb_buf_length;
994 989
995 /* BB special case reconnect tid and uid here? */ 990 /* BB special case reconnect tid and uid here? */
996 rc = map_smb_to_linux_error(out_buf); 991 rc = map_smb_to_linux_error(out_buf, 0 /* no log */ );
997 992
998 /* convert ByteCount if necessary */ 993 /* convert ByteCount if necessary */
999 if (receive_len >= 994 if (receive_len >= sizeof(struct smb_hdr) - 4
1000 sizeof (struct smb_hdr) - 995 /* do not count RFC1001 header */ +
1001 4 /* do not count RFC1001 header */ +
1002 (2 * out_buf->WordCount) + 2 /* bcc */ ) 996 (2 * out_buf->WordCount) + 2 /* bcc */ )
1003 BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf)); 997 BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
1004 } else { 998 } else {
diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c
index f61e433d281c..369e838bebd3 100644
--- a/fs/cifs/xattr.c
+++ b/fs/cifs/xattr.c
@@ -261,21 +261,26 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name,
261 cifs_sb->local_nls, 261 cifs_sb->local_nls,
262 cifs_sb->mnt_cifs_flags & 262 cifs_sb->mnt_cifs_flags &
263 CIFS_MOUNT_MAP_SPECIAL_CHR); 263 CIFS_MOUNT_MAP_SPECIAL_CHR);
264/* else if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { 264#ifdef CONFIG_CIFS_EXPERIMENTAL
265 else if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
265 __u16 fid; 266 __u16 fid;
266 int oplock = FALSE; 267 int oplock = FALSE;
267 rc = CIFSSMBOpen(xid, pTcon, full_path, 268 if (experimEnabled)
268 FILE_OPEN, GENERIC_READ, 0, &fid, 269 rc = CIFSSMBOpen(xid, pTcon, full_path,
269 &oplock, NULL, cifs_sb->local_nls, 270 FILE_OPEN, GENERIC_READ, 0, &fid,
270 cifs_sb->mnt_cifs_flags & 271 &oplock, NULL, cifs_sb->local_nls,
271 CIFS_MOUNT_MAP_SPECIAL_CHR); 272 cifs_sb->mnt_cifs_flags &
273 CIFS_MOUNT_MAP_SPECIAL_CHR);
274 /* else rc is EOPNOTSUPP from above */
275
272 if(rc == 0) { 276 if(rc == 0) {
273 rc = CIFSSMBGetCIFSACL(xid, pTcon, fid, 277 rc = CIFSSMBGetCIFSACL(xid, pTcon, fid,
274 ea_value, buf_size, 278 ea_value, buf_size,
275 ACL_TYPE_ACCESS); 279 ACL_TYPE_ACCESS);
276 CIFSSMBClose(xid, pTcon, fid); 280 CIFSSMBClose(xid, pTcon, fid);
277 } 281 }
278 } */ /* BB enable after fixing up return data */ 282 }
283#endif /* EXPERIMENTAL */
279#else 284#else
280 cFYI(1, ("query POSIX ACL not supported yet")); 285 cFYI(1, ("query POSIX ACL not supported yet"));
281#endif /* CONFIG_CIFS_POSIX */ 286#endif /* CONFIG_CIFS_POSIX */