diff options
| author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-19 15:00:58 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-19 15:00:58 -0400 |
| commit | 2843483d2eb02ad104edbe8b2429fb6a39d25063 (patch) | |
| tree | 7a63d1fa408ab50277666b2d73d2553ea4cfc7a7 | |
| parent | 26790656d7dc34206f78eeca0f4be5caede788ce (diff) | |
| parent | a761ac579b89bc1f00212a42401398108deba65c (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
...
| -rw-r--r-- | fs/cifs/CHANGES | 21 | ||||
| -rw-r--r-- | fs/cifs/Makefile | 2 | ||||
| -rw-r--r-- | fs/cifs/asn1.c | 10 | ||||
| -rw-r--r-- | fs/cifs/cifs_debug.c | 28 | ||||
| -rw-r--r-- | fs/cifs/cifsacl.c | 333 | ||||
| -rw-r--r-- | fs/cifs/cifsacl.h | 64 | ||||
| -rw-r--r-- | fs/cifs/cifsencrypt.c | 5 | ||||
| -rw-r--r-- | fs/cifs/cifsfs.c | 38 | ||||
| -rw-r--r-- | fs/cifs/cifsfs.h | 11 | ||||
| -rw-r--r-- | fs/cifs/cifsglob.h | 31 | ||||
| -rw-r--r-- | fs/cifs/cifspdu.h | 20 | ||||
| -rw-r--r-- | fs/cifs/cifsproto.h | 8 | ||||
| -rw-r--r-- | fs/cifs/cifssmb.c | 158 | ||||
| -rw-r--r-- | fs/cifs/connect.c | 262 | ||||
| -rw-r--r-- | fs/cifs/dir.c | 9 | ||||
| -rw-r--r-- | fs/cifs/export.c | 1 | ||||
| -rw-r--r-- | fs/cifs/file.c | 86 | ||||
| -rw-r--r-- | fs/cifs/inode.c | 52 | ||||
| -rw-r--r-- | fs/cifs/link.c | 2 | ||||
| -rw-r--r-- | fs/cifs/misc.c | 1 | ||||
| -rw-r--r-- | fs/cifs/netmisc.c | 33 | ||||
| -rw-r--r-- | fs/cifs/readdir.c | 8 | ||||
| -rw-r--r-- | fs/cifs/sess.c | 103 | ||||
| -rw-r--r-- | fs/cifs/smberr.h | 5 | ||||
| -rw-r--r-- | fs/cifs/transport.c | 34 | ||||
| -rw-r--r-- | fs/cifs/xattr.c | 19 |
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 @@ | |||
| 1 | Version 1.51 | ||
| 2 | ------------ | ||
| 3 | Fix memory leak in statfs when mounted to very old servers (e.g. | ||
| 4 | Windows 9x). Add new feature "POSIX open" which allows servers | ||
| 5 | which support the current POSIX Extensions to provide better semantics | ||
| 6 | (e.g. delete for open files opened with posix open). Take into | ||
| 7 | account umask on posix mkdir not just older style mkdir. Add | ||
| 8 | ability to mount to IPC$ share (which allows CIFS named pipes to be | ||
| 9 | opened, read and written as if they were files). When 1st tree | ||
| 10 | connect fails (e.g. due to signing negotiation failure) fix | ||
| 11 | leak that causes cifsd not to stop and rmmod to fail to cleanup | ||
| 12 | cifs_request_buffers pool. Fix problem with POSIX Open/Mkdir on | ||
| 13 | bigendian architectures. Fix possible memory corruption when | ||
| 14 | EAGAIN returned on kern_recvmsg. Return better error if server | ||
| 15 | requires packet signing but client has disabled it. | ||
| 16 | |||
| 1 | Version 1.50 | 17 | Version 1.50 |
| 2 | ------------ | 18 | ------------ |
| 3 | Fix NTLMv2 signing. NFS server mounted over cifs works (if cifs mount is | 19 | Fix 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 | |||
| 6 | Samba supports newer POSIX CIFS Protocol Extensions). Add "nounix" | 22 | Samba supports newer POSIX CIFS Protocol Extensions). Add "nounix" |
| 7 | mount option to allow disabling the CIFS Unix Extensions for just | 23 | mount option to allow disabling the CIFS Unix Extensions for just |
| 8 | that mount. Fix hang on spinlock in find_writable_file (race when | 24 | that mount. Fix hang on spinlock in find_writable_file (race when |
| 9 | reopening file after session crash). | 25 | reopening file after session crash). Byte range unlock request to |
| 26 | windows server could unlock more bytes (on server copy of file) | ||
| 27 | than intended if start of unlock request is well before start of | ||
| 28 | a previous byte range lock that we issued. | ||
| 10 | 29 | ||
| 11 | Version 1.49 | 30 | Version 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 | # |
| 4 | obj-$(CONFIG_CIFS) += cifs.o | 4 | obj-$(CONFIG_CIFS) += cifs.o |
| 5 | 5 | ||
| 6 | cifs-objs := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o md4.o md5.o cifs_unicode.o nterr.o xattr.o cifsencrypt.o fcntl.o readdir.o ioctl.o sess.o export.o | 6 | cifs-objs := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o md4.o md5.o cifs_unicode.o nterr.o xattr.o cifsencrypt.o fcntl.o readdir.o ioctl.o 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 | |||
| 34 | static 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 */ | ||
| 46 | static const struct cifs_sid sid_everyone = | ||
| 47 | {1, 1, {0, 0, 0, 0, 0, 0}, {} }; | ||
| 48 | /* group users */ | ||
| 49 | static const struct cifs_sid sid_user = | ||
| 50 | {1, 2 , {0, 0, 0, 0, 0, 5}, {} }; | ||
| 51 | |||
| 52 | |||
| 53 | int 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 */ | ||
| 100 | int 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 | |||
| 133 | static 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 | |||
| 166 | static 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 | |||
| 184 | static 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 | |||
| 258 | static 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 */ | ||
| 292 | int 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 | |||
| 38 | struct 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 | |||
| 25 | struct cifs_sid { | 47 | struct 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 | |||
| 54 | struct cifs_acl { | ||
| 55 | __le16 revision; /* revision level */ | ||
| 56 | __le16 size; | ||
| 57 | __le32 num_aces; | ||
| 58 | } __attribute__((packed)); | ||
| 59 | |||
| 60 | struct 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 | |||
| 67 | struct 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 */ | 74 | struct 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 | |||
| 81 | extern int match_sid(struct cifs_sid *); | ||
| 82 | extern 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 @@ | |||
| 49 | static struct quotactl_ops cifs_quotactl_ops; | 49 | static struct quotactl_ops cifs_quotactl_ops; |
| 50 | #endif /* QUOTA */ | 50 | #endif /* QUOTA */ |
| 51 | 51 | ||
| 52 | #ifdef CONFIG_CIFS_EXPERIMENTAL | ||
| 53 | extern struct export_operations cifs_export_ops; | ||
| 54 | #endif /* EXPERIMENTAL */ | ||
| 55 | |||
| 56 | int cifsFYI = 0; | 52 | int cifsFYI = 0; |
| 57 | int cifsERROR = 1; | 53 | int cifsERROR = 1; |
| 58 | int traceSMB = 0; | 54 | int 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 | |||
| 716 | cifs_init_inodecache(void) | 712 | cifs_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 | |||
| 816 | cifs_init_mids(void) | 812 | cifs_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); |
| 100 | extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t); | 100 | extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t); |
| 101 | extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); | 101 | extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); |
| 102 | extern int cifs_ioctl (struct inode *inode, struct file *filep, | 102 | extern 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 | ||
| 106 | extern 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 | ||
| 91 | enum securityEnum { | 92 | enum 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 | ||
| 120 | struct 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 | |||
| 719 | typedef struct smb_com_open_req { /* also handles create */ | 733 | typedef 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); |
| 51 | extern int SendReceive2(const unsigned int /* xid */ , struct cifsSesInfo *, | 51 | extern 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*/ ); | ||
| 54 | extern int SendReceiveBlockingLock(const unsigned int /* xid */ , | 55 | extern 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); | |||
| 65 | extern int decode_negTokenInit(unsigned char *security_blob, int length, | 66 | extern int decode_negTokenInit(unsigned char *security_blob, int length, |
| 66 | enum securityEnum *secType); | 67 | enum securityEnum *secType); |
| 67 | extern int cifs_inet_pton(int, char *source, void *dst); | 68 | extern int cifs_inet_pton(int, char *source, void *dst); |
| 68 | extern int map_smb_to_linux_error(struct smb_hdr *smb); | 69 | extern int map_smb_to_linux_error(struct smb_hdr *smb, int logErr); |
| 69 | extern void header_assemble(struct smb_hdr *, char /* command */ , | 70 | extern 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); |
| 305 | extern int CalcNTLMv2_partial_mac_key(struct cifsSesInfo *, | 306 | extern int CalcNTLMv2_partial_mac_key(struct cifsSesInfo *, |
| 306 | const struct nls_table *); | 307 | const struct nls_table *); |
| 307 | extern void CalcNTLMv2_response(const struct cifsSesInfo *, char * ); | 308 | extern void CalcNTLMv2_response(const struct cifsSesInfo *, char *); |
| 308 | extern void setup_ntlmv2_rsp(struct cifsSesInfo *, char *, | 309 | extern 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 |
| 311 | extern void calc_lanman_hash(struct cifsSesInfo *ses, char *lnm_session_key); | 312 | extern void calc_lanman_hash(struct cifsSesInfo *ses, char *lnm_session_key); |
| 312 | #endif /* CIFS_WEAK_PW_HASH */ | 313 | #endif /* CIFS_WEAK_PW_HASH */ |
| 314 | extern int parse_sec_desc(struct cifs_ntsd *, int); | ||
| 313 | extern int CIFSSMBCopy(int xid, | 315 | extern 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 |
| 43 | static struct { | 43 | static 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 | ||
| 1118 | psx_create_err: | 1141 | psx_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 */ | ||
| 3047 | static const struct cifs_sid sid_everyone = | ||
| 3048 | {1, 1, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0}}; | ||
| 3049 | /* group users */ | ||
| 3050 | static 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 */ | ||
| 3054 | static 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 */ |
| 3060 | int | 3068 | int |
| 3061 | CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid, | 3069 | CIFSSMBGetCIFSACL(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 */ | ||
| 401 | incomplete_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, | |||
| 2526 | sesssetup_nomem: /* do not return an error on nomem for the info strings, | 2541 | sesssetup_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 | } |
| 2873 | static int | 2886 | static int |
| 2874 | CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, | 2887 | CIFSNTLMSSPAuthSessSetup(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 |
| 48 | static struct dentry *cifs_get_parent(struct dentry *dentry) | 49 | static 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: | |||
| 467 | int cifs_close(struct inode *inode, struct file *file) | 467 | int 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); |
| 1045 | refind_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 | ||
| 578 | static const struct inode_operations cifs_ipc_inode_ops = { | ||
| 579 | .lookup = cifs_lookup, | ||
| 580 | }; | ||
| 581 | |||
| 578 | /* gets root inode */ | 582 | /* gets root inode */ |
| 579 | void cifs_read_inode(struct inode *inode) | 583 | void 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 | 998 | mkdir_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 | ||
| 1384 | do_expand: | 1416 | do_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) | |||
| 169 | void | 169 | void |
| 170 | cifs_buf_release(void *buf_to_free) | 170 | cifs_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 | ||
| 756 | int | 762 | int |
| 757 | map_smb_to_linux_error(struct smb_hdr *smb) | 763 | map_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 | ||
| 123 | static void fill_in_inode(struct inode *tmp_inode, int new_buf_type, | 123 | static 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 | ||
| 296 | static void unix_fill_in_inode(struct inode *tmp_inode, | 296 | static 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 | ||
| 77 | static void | ||
| 78 | unicode_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 | |||
| 100 | static 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 | |||
| 78 | static void unicode_ssetup_strings(char **pbcc_area, struct cifsSesInfo *ses, | 123 | static 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, | |||
| 419 | int | 418 | int |
| 420 | SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, | 419 | SendReceive2(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 */ |
