diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-05-20 16:37:49 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-05-20 16:37:49 -0400 |
commit | 91444f47b2a0e50a15849f49db8c15382cd8de1b (patch) | |
tree | f565abed6640cc07607729969643551202f77e57 | |
parent | bc091c93a0f60717aa99e25c406892cd8c0187dc (diff) | |
parent | 156ecb2d8b06589098f6ce3012e6a10fef07c416 (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: (32 commits)
[CIFS] Fix to problem with getattr caused by invalidate simplification patch
[CIFS] Remove sparse warning
[CIFS] Update cifs to version 1.72
cifs: Change key name to cifs.idmap, misc. clean-up
cifs: Unconditionally copy mount options to superblock info
cifs: Use kstrndup for cifs_sb->mountdata
cifs: Simplify handling of submount options in cifs_mount.
cifs: cifs_parse_mount_options: do not tokenize mount options in-place
cifs: Add support for mounting Windows 2008 DFS shares
cifs: Extract DFS referral expansion logic to separate function
cifs: turn BCC into a static inlined function
cifs: keep BCC in little-endian format
cifs: fix some unused variable warnings in id_rb_search
CIFS: Simplify invalidate part (try #5)
CIFS: directio read/write cleanups
consistently use smb_buf_length as be32 for cifs (try 3)
cifs: Invoke id mapping functions (try #17 repost)
cifs: Add idmap key and related data structures and functions (try #17 repost)
CIFS: Add launder_page operation (try #3)
Introduce smb2 mounts as vers=2
...
-rw-r--r-- | fs/cifs/Kconfig | 35 | ||||
-rw-r--r-- | fs/cifs/Makefile | 2 | ||||
-rw-r--r-- | fs/cifs/README | 12 | ||||
-rw-r--r-- | fs/cifs/cifs_debug.c | 2 | ||||
-rw-r--r-- | fs/cifs/cifs_fs_sb.h | 4 | ||||
-rw-r--r-- | fs/cifs/cifs_unicode.h | 3 | ||||
-rw-r--r-- | fs/cifs/cifsacl.c | 483 | ||||
-rw-r--r-- | fs/cifs/cifsacl.h | 25 | ||||
-rw-r--r-- | fs/cifs/cifsencrypt.c | 12 | ||||
-rw-r--r-- | fs/cifs/cifsfs.c | 119 | ||||
-rw-r--r-- | fs/cifs/cifsfs.h | 20 | ||||
-rw-r--r-- | fs/cifs/cifsglob.h | 10 | ||||
-rw-r--r-- | fs/cifs/cifspdu.h | 37 | ||||
-rw-r--r-- | fs/cifs/cifsproto.h | 30 | ||||
-rw-r--r-- | fs/cifs/cifssmb.c | 377 | ||||
-rw-r--r-- | fs/cifs/connect.c | 279 | ||||
-rw-r--r-- | fs/cifs/export.c | 4 | ||||
-rw-r--r-- | fs/cifs/file.c | 167 | ||||
-rw-r--r-- | fs/cifs/inode.c | 129 | ||||
-rw-r--r-- | fs/cifs/misc.c | 12 | ||||
-rw-r--r-- | fs/cifs/netmisc.c | 7 | ||||
-rw-r--r-- | fs/cifs/sess.c | 9 | ||||
-rw-r--r-- | fs/cifs/smbdes.c | 418 | ||||
-rw-r--r-- | fs/cifs/smbencrypt.c | 124 | ||||
-rw-r--r-- | fs/cifs/transport.c | 66 | ||||
-rw-r--r-- | fs/cifs/xattr.c | 20 | ||||
-rw-r--r-- | fs/super.c | 3 |
27 files changed, 1289 insertions, 1120 deletions
diff --git a/fs/cifs/Kconfig b/fs/cifs/Kconfig index 7cb0f7f847e4..75c47cd8d086 100644 --- a/fs/cifs/Kconfig +++ b/fs/cifs/Kconfig | |||
@@ -7,6 +7,7 @@ config CIFS | |||
7 | select CRYPTO_MD5 | 7 | select CRYPTO_MD5 |
8 | select CRYPTO_HMAC | 8 | select CRYPTO_HMAC |
9 | select CRYPTO_ARC4 | 9 | select CRYPTO_ARC4 |
10 | select CRYPTO_DES | ||
10 | help | 11 | help |
11 | This is the client VFS module for the Common Internet File System | 12 | This is the client VFS module for the Common Internet File System |
12 | (CIFS) protocol which is the successor to the Server Message Block | 13 | (CIFS) protocol which is the successor to the Server Message Block |
@@ -152,16 +153,28 @@ config CIFS_ACL | |||
152 | Allows to fetch CIFS/NTFS ACL from the server. The DACL blob | 153 | Allows to fetch CIFS/NTFS ACL from the server. The DACL blob |
153 | is handed over to the application/caller. | 154 | is handed over to the application/caller. |
154 | 155 | ||
155 | config CIFS_EXPERIMENTAL | 156 | config CIFS_SMB2 |
156 | bool "CIFS Experimental Features (EXPERIMENTAL)" | 157 | bool "SMB2 network file system support (EXPERIMENTAL)" |
158 | depends on EXPERIMENTAL && INET && BROKEN | ||
159 | select NLS | ||
160 | select KEYS | ||
161 | select FSCACHE | ||
162 | select DNS_RESOLVER | ||
163 | |||
164 | help | ||
165 | This enables experimental support for the SMB2 (Server Message Block | ||
166 | version 2) protocol. The SMB2 protocol is the successor to the | ||
167 | popular CIFS and SMB network file sharing protocols. SMB2 is the | ||
168 | native file sharing mechanism for recent versions of Windows | ||
169 | operating systems (since Vista). SMB2 enablement will eventually | ||
170 | allow users better performance, security and features, than would be | ||
171 | possible with cifs. Note that smb2 mount options also are simpler | ||
172 | (compared to cifs) due to protocol improvements. | ||
173 | |||
174 | Unless you are a developer or tester, say N. | ||
175 | |||
176 | config CIFS_NFSD_EXPORT | ||
177 | bool "Allow nfsd to export CIFS file system (EXPERIMENTAL)" | ||
157 | depends on CIFS && EXPERIMENTAL | 178 | depends on CIFS && EXPERIMENTAL |
158 | help | 179 | help |
159 | Enables cifs features under testing. These features are | 180 | Allows NFS server to export a CIFS mounted share (nfsd over cifs) |
160 | experimental and currently include DFS support and directory | ||
161 | change notification ie fcntl(F_DNOTIFY), as well as the upcall | ||
162 | mechanism which will be used for Kerberos session negotiation | ||
163 | and uid remapping. Some of these features also may depend on | ||
164 | setting a value of 1 to the pseudo-file /proc/fs/cifs/Experimental | ||
165 | (which is disabled by default). See the file fs/cifs/README | ||
166 | for more details. If unsure, say N. | ||
167 | |||
diff --git a/fs/cifs/Makefile b/fs/cifs/Makefile index d87558448e3d..005d524c3a4a 100644 --- a/fs/cifs/Makefile +++ b/fs/cifs/Makefile | |||
@@ -4,7 +4,7 @@ | |||
4 | obj-$(CONFIG_CIFS) += cifs.o | 4 | obj-$(CONFIG_CIFS) += cifs.o |
5 | 5 | ||
6 | cifs-y := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o \ | 6 | cifs-y := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o \ |
7 | link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o \ | 7 | link.o misc.o netmisc.o smbencrypt.o transport.o asn1.o \ |
8 | cifs_unicode.o nterr.o xattr.o cifsencrypt.o \ | 8 | cifs_unicode.o nterr.o xattr.o cifsencrypt.o \ |
9 | readdir.o ioctl.o sess.o export.o | 9 | readdir.o ioctl.o sess.o export.o |
10 | 10 | ||
diff --git a/fs/cifs/README b/fs/cifs/README index 74ab165fc646..4a3ca0e5ca24 100644 --- a/fs/cifs/README +++ b/fs/cifs/README | |||
@@ -704,18 +704,6 @@ the start of smb requests and responses can be enabled via: | |||
704 | 704 | ||
705 | echo 1 > /proc/fs/cifs/traceSMB | 705 | echo 1 > /proc/fs/cifs/traceSMB |
706 | 706 | ||
707 | Two other experimental features are under development. To test these | ||
708 | requires enabling CONFIG_CIFS_EXPERIMENTAL | ||
709 | |||
710 | cifsacl support needed to retrieve approximated mode bits based on | ||
711 | the contents on the CIFS ACL. | ||
712 | |||
713 | lease support: cifs will check the oplock state before calling into | ||
714 | the vfs to see if we can grant a lease on a file. | ||
715 | |||
716 | DNOTIFY fcntl: needed for support of directory change | ||
717 | notification and perhaps later for file leases) | ||
718 | |||
719 | Per share (per client mount) statistics are available in /proc/fs/cifs/Stats | 707 | Per share (per client mount) statistics are available in /proc/fs/cifs/Stats |
720 | if the kernel was configured with cifs statistics enabled. The statistics | 708 | if the kernel was configured with cifs statistics enabled. The statistics |
721 | represent the number of successful (ie non-zero return code from the server) | 709 | represent the number of successful (ie non-zero return code from the server) |
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c index 30d01bc90855..18f4272d9047 100644 --- a/fs/cifs/cifs_debug.c +++ b/fs/cifs/cifs_debug.c | |||
@@ -63,7 +63,7 @@ void cifs_dump_detail(struct smb_hdr *smb) | |||
63 | cERROR(1, "Cmd: %d Err: 0x%x Flags: 0x%x Flgs2: 0x%x Mid: %d Pid: %d", | 63 | cERROR(1, "Cmd: %d Err: 0x%x Flags: 0x%x Flgs2: 0x%x Mid: %d Pid: %d", |
64 | smb->Command, smb->Status.CifsError, | 64 | smb->Command, smb->Status.CifsError, |
65 | smb->Flags, smb->Flags2, smb->Mid, smb->Pid); | 65 | smb->Flags, smb->Flags2, smb->Mid, smb->Pid); |
66 | cERROR(1, "smb buf %p len %d", smb, smbCalcSize_LE(smb)); | 66 | cERROR(1, "smb buf %p len %d", smb, smbCalcSize(smb)); |
67 | } | 67 | } |
68 | 68 | ||
69 | 69 | ||
diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h index ac51cd2d33ae..a9d5692e0c20 100644 --- a/fs/cifs/cifs_fs_sb.h +++ b/fs/cifs/cifs_fs_sb.h | |||
@@ -58,9 +58,7 @@ struct cifs_sb_info { | |||
58 | unsigned int mnt_cifs_flags; | 58 | unsigned int mnt_cifs_flags; |
59 | int prepathlen; | 59 | int prepathlen; |
60 | char *prepath; /* relative path under the share to mount to */ | 60 | char *prepath; /* relative path under the share to mount to */ |
61 | #ifdef CONFIG_CIFS_DFS_UPCALL | 61 | char *mountdata; /* options received at mount time or via DFS refs */ |
62 | char *mountdata; /* mount options received at mount time */ | ||
63 | #endif | ||
64 | struct backing_dev_info bdi; | 62 | struct backing_dev_info bdi; |
65 | struct delayed_work prune_tlinks; | 63 | struct delayed_work prune_tlinks; |
66 | }; | 64 | }; |
diff --git a/fs/cifs/cifs_unicode.h b/fs/cifs/cifs_unicode.h index 644dd882a560..6d02fd560566 100644 --- a/fs/cifs/cifs_unicode.h +++ b/fs/cifs/cifs_unicode.h | |||
@@ -82,6 +82,9 @@ int cifs_strtoUCS(__le16 *, const char *, int, const struct nls_table *); | |||
82 | char *cifs_strndup_from_ucs(const char *src, const int maxlen, | 82 | char *cifs_strndup_from_ucs(const char *src, const int maxlen, |
83 | const bool is_unicode, | 83 | const bool is_unicode, |
84 | const struct nls_table *codepage); | 84 | const struct nls_table *codepage); |
85 | extern int cifsConvertToUCS(__le16 *target, const char *source, int maxlen, | ||
86 | const struct nls_table *cp, int mapChars); | ||
87 | |||
85 | #endif | 88 | #endif |
86 | 89 | ||
87 | /* | 90 | /* |
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c index beeebf194234..f3c6fb9942ac 100644 --- a/fs/cifs/cifsacl.c +++ b/fs/cifs/cifsacl.c | |||
@@ -23,24 +23,16 @@ | |||
23 | 23 | ||
24 | #include <linux/fs.h> | 24 | #include <linux/fs.h> |
25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
26 | #include <linux/string.h> | ||
27 | #include <linux/keyctl.h> | ||
28 | #include <linux/key-type.h> | ||
29 | #include <keys/user-type.h> | ||
26 | #include "cifspdu.h" | 30 | #include "cifspdu.h" |
27 | #include "cifsglob.h" | 31 | #include "cifsglob.h" |
28 | #include "cifsacl.h" | 32 | #include "cifsacl.h" |
29 | #include "cifsproto.h" | 33 | #include "cifsproto.h" |
30 | #include "cifs_debug.h" | 34 | #include "cifs_debug.h" |
31 | 35 | ||
32 | |||
33 | static struct cifs_wksid wksidarr[NUM_WK_SIDS] = { | ||
34 | {{1, 0, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0} }, "null user"}, | ||
35 | {{1, 1, {0, 0, 0, 0, 0, 1}, {0, 0, 0, 0, 0} }, "nobody"}, | ||
36 | {{1, 1, {0, 0, 0, 0, 0, 5}, {__constant_cpu_to_le32(11), 0, 0, 0, 0} }, "net-users"}, | ||
37 | {{1, 1, {0, 0, 0, 0, 0, 5}, {__constant_cpu_to_le32(18), 0, 0, 0, 0} }, "sys"}, | ||
38 | {{1, 2, {0, 0, 0, 0, 0, 5}, {__constant_cpu_to_le32(32), __constant_cpu_to_le32(544), 0, 0, 0} }, "root"}, | ||
39 | {{1, 2, {0, 0, 0, 0, 0, 5}, {__constant_cpu_to_le32(32), __constant_cpu_to_le32(545), 0, 0, 0} }, "users"}, | ||
40 | {{1, 2, {0, 0, 0, 0, 0, 5}, {__constant_cpu_to_le32(32), __constant_cpu_to_le32(546), 0, 0, 0} }, "guest"} } | ||
41 | ; | ||
42 | |||
43 | |||
44 | /* security id for everyone/world system group */ | 36 | /* security id for everyone/world system group */ |
45 | static const struct cifs_sid sid_everyone = { | 37 | static const struct cifs_sid sid_everyone = { |
46 | 1, 1, {0, 0, 0, 0, 0, 1}, {0} }; | 38 | 1, 1, {0, 0, 0, 0, 0, 1}, {0} }; |
@@ -50,50 +42,385 @@ static const struct cifs_sid sid_authusers = { | |||
50 | /* group users */ | 42 | /* group users */ |
51 | static const struct cifs_sid sid_user = {1, 2 , {0, 0, 0, 0, 0, 5}, {} }; | 43 | static const struct cifs_sid sid_user = {1, 2 , {0, 0, 0, 0, 0, 5}, {} }; |
52 | 44 | ||
45 | const struct cred *root_cred; | ||
53 | 46 | ||
54 | int match_sid(struct cifs_sid *ctsid) | 47 | static void |
48 | shrink_idmap_tree(struct rb_root *root, int nr_to_scan, int *nr_rem, | ||
49 | int *nr_del) | ||
55 | { | 50 | { |
56 | int i, j; | 51 | struct rb_node *node; |
57 | int num_subauth, num_sat, num_saw; | 52 | struct rb_node *tmp; |
58 | struct cifs_sid *cwsid; | 53 | struct cifs_sid_id *psidid; |
54 | |||
55 | node = rb_first(root); | ||
56 | while (node) { | ||
57 | tmp = node; | ||
58 | node = rb_next(tmp); | ||
59 | psidid = rb_entry(tmp, struct cifs_sid_id, rbnode); | ||
60 | if (nr_to_scan == 0 || *nr_del == nr_to_scan) | ||
61 | ++(*nr_rem); | ||
62 | else { | ||
63 | if (time_after(jiffies, psidid->time + SID_MAP_EXPIRE) | ||
64 | && psidid->refcount == 0) { | ||
65 | rb_erase(tmp, root); | ||
66 | ++(*nr_del); | ||
67 | } else | ||
68 | ++(*nr_rem); | ||
69 | } | ||
70 | } | ||
71 | } | ||
72 | |||
73 | /* | ||
74 | * Run idmap cache shrinker. | ||
75 | */ | ||
76 | static int | ||
77 | cifs_idmap_shrinker(struct shrinker *shrink, int nr_to_scan, gfp_t gfp_mask) | ||
78 | { | ||
79 | int nr_del = 0; | ||
80 | int nr_rem = 0; | ||
81 | struct rb_root *root; | ||
82 | |||
83 | root = &uidtree; | ||
84 | spin_lock(&siduidlock); | ||
85 | shrink_idmap_tree(root, nr_to_scan, &nr_rem, &nr_del); | ||
86 | spin_unlock(&siduidlock); | ||
87 | |||
88 | root = &gidtree; | ||
89 | spin_lock(&sidgidlock); | ||
90 | shrink_idmap_tree(root, nr_to_scan, &nr_rem, &nr_del); | ||
91 | spin_unlock(&sidgidlock); | ||
92 | |||
93 | return nr_rem; | ||
94 | } | ||
95 | |||
96 | static struct shrinker cifs_shrinker = { | ||
97 | .shrink = cifs_idmap_shrinker, | ||
98 | .seeks = DEFAULT_SEEKS, | ||
99 | }; | ||
100 | |||
101 | static int | ||
102 | cifs_idmap_key_instantiate(struct key *key, const void *data, size_t datalen) | ||
103 | { | ||
104 | char *payload; | ||
105 | |||
106 | payload = kmalloc(datalen, GFP_KERNEL); | ||
107 | if (!payload) | ||
108 | return -ENOMEM; | ||
109 | |||
110 | memcpy(payload, data, datalen); | ||
111 | key->payload.data = payload; | ||
112 | return 0; | ||
113 | } | ||
114 | |||
115 | static inline void | ||
116 | cifs_idmap_key_destroy(struct key *key) | ||
117 | { | ||
118 | kfree(key->payload.data); | ||
119 | } | ||
59 | 120 | ||
60 | if (!ctsid) | 121 | struct key_type cifs_idmap_key_type = { |
61 | return -1; | 122 | .name = "cifs.idmap", |
123 | .instantiate = cifs_idmap_key_instantiate, | ||
124 | .destroy = cifs_idmap_key_destroy, | ||
125 | .describe = user_describe, | ||
126 | .match = user_match, | ||
127 | }; | ||
128 | |||
129 | static void | ||
130 | sid_to_str(struct cifs_sid *sidptr, char *sidstr) | ||
131 | { | ||
132 | int i; | ||
133 | unsigned long saval; | ||
134 | char *strptr; | ||
62 | 135 | ||
63 | for (i = 0; i < NUM_WK_SIDS; ++i) { | 136 | strptr = sidstr; |
64 | cwsid = &(wksidarr[i].cifssid); | ||
65 | 137 | ||
66 | /* compare the revision */ | 138 | sprintf(strptr, "%s", "S"); |
67 | if (ctsid->revision != cwsid->revision) | 139 | strptr = sidstr + strlen(sidstr); |
68 | continue; | ||
69 | 140 | ||
70 | /* compare all of the six auth values */ | 141 | sprintf(strptr, "-%d", sidptr->revision); |
71 | for (j = 0; j < 6; ++j) { | 142 | strptr = sidstr + strlen(sidstr); |
72 | if (ctsid->authority[j] != cwsid->authority[j]) | 143 | |
73 | break; | 144 | for (i = 0; i < 6; ++i) { |
145 | if (sidptr->authority[i]) { | ||
146 | sprintf(strptr, "-%d", sidptr->authority[i]); | ||
147 | strptr = sidstr + strlen(sidstr); | ||
74 | } | 148 | } |
75 | if (j < 6) | 149 | } |
76 | continue; /* all of the auth values did not match */ | 150 | |
77 | 151 | for (i = 0; i < sidptr->num_subauth; ++i) { | |
78 | /* compare all of the subauth values if any */ | 152 | saval = le32_to_cpu(sidptr->sub_auth[i]); |
79 | num_sat = ctsid->num_subauth; | 153 | sprintf(strptr, "-%ld", saval); |
80 | num_saw = cwsid->num_subauth; | 154 | strptr = sidstr + strlen(sidstr); |
81 | num_subauth = num_sat < num_saw ? num_sat : num_saw; | 155 | } |
82 | if (num_subauth) { | 156 | } |
83 | for (j = 0; j < num_subauth; ++j) { | 157 | |
84 | if (ctsid->sub_auth[j] != cwsid->sub_auth[j]) | 158 | static void |
85 | break; | 159 | id_rb_insert(struct rb_root *root, struct cifs_sid *sidptr, |
86 | } | 160 | struct cifs_sid_id **psidid, char *typestr) |
87 | if (j < num_subauth) | 161 | { |
88 | continue; /* all sub_auth values do not match */ | 162 | int rc; |
163 | char *strptr; | ||
164 | struct rb_node *node = root->rb_node; | ||
165 | struct rb_node *parent = NULL; | ||
166 | struct rb_node **linkto = &(root->rb_node); | ||
167 | struct cifs_sid_id *lsidid; | ||
168 | |||
169 | while (node) { | ||
170 | lsidid = rb_entry(node, struct cifs_sid_id, rbnode); | ||
171 | parent = node; | ||
172 | rc = compare_sids(sidptr, &((lsidid)->sid)); | ||
173 | if (rc > 0) { | ||
174 | linkto = &(node->rb_left); | ||
175 | node = node->rb_left; | ||
176 | } else if (rc < 0) { | ||
177 | linkto = &(node->rb_right); | ||
178 | node = node->rb_right; | ||
179 | } | ||
180 | } | ||
181 | |||
182 | memcpy(&(*psidid)->sid, sidptr, sizeof(struct cifs_sid)); | ||
183 | (*psidid)->time = jiffies - (SID_MAP_RETRY + 1); | ||
184 | (*psidid)->refcount = 0; | ||
185 | |||
186 | sprintf((*psidid)->sidstr, "%s", typestr); | ||
187 | strptr = (*psidid)->sidstr + strlen((*psidid)->sidstr); | ||
188 | sid_to_str(&(*psidid)->sid, strptr); | ||
189 | |||
190 | clear_bit(SID_ID_PENDING, &(*psidid)->state); | ||
191 | clear_bit(SID_ID_MAPPED, &(*psidid)->state); | ||
192 | |||
193 | rb_link_node(&(*psidid)->rbnode, parent, linkto); | ||
194 | rb_insert_color(&(*psidid)->rbnode, root); | ||
195 | } | ||
196 | |||
197 | static struct cifs_sid_id * | ||
198 | id_rb_search(struct rb_root *root, struct cifs_sid *sidptr) | ||
199 | { | ||
200 | int rc; | ||
201 | struct rb_node *node = root->rb_node; | ||
202 | struct cifs_sid_id *lsidid; | ||
203 | |||
204 | while (node) { | ||
205 | lsidid = rb_entry(node, struct cifs_sid_id, rbnode); | ||
206 | rc = compare_sids(sidptr, &((lsidid)->sid)); | ||
207 | if (rc > 0) { | ||
208 | node = node->rb_left; | ||
209 | } else if (rc < 0) { | ||
210 | node = node->rb_right; | ||
211 | } else /* node found */ | ||
212 | return lsidid; | ||
213 | } | ||
214 | |||
215 | return NULL; | ||
216 | } | ||
217 | |||
218 | static int | ||
219 | sidid_pending_wait(void *unused) | ||
220 | { | ||
221 | schedule(); | ||
222 | return signal_pending(current) ? -ERESTARTSYS : 0; | ||
223 | } | ||
224 | |||
225 | static int | ||
226 | sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid, | ||
227 | struct cifs_fattr *fattr, uint sidtype) | ||
228 | { | ||
229 | int rc; | ||
230 | unsigned long cid; | ||
231 | struct key *idkey; | ||
232 | const struct cred *saved_cred; | ||
233 | struct cifs_sid_id *psidid, *npsidid; | ||
234 | struct rb_root *cidtree; | ||
235 | spinlock_t *cidlock; | ||
236 | |||
237 | if (sidtype == SIDOWNER) { | ||
238 | cid = cifs_sb->mnt_uid; /* default uid, in case upcall fails */ | ||
239 | cidlock = &siduidlock; | ||
240 | cidtree = &uidtree; | ||
241 | } else if (sidtype == SIDGROUP) { | ||
242 | cid = cifs_sb->mnt_gid; /* default gid, in case upcall fails */ | ||
243 | cidlock = &sidgidlock; | ||
244 | cidtree = &gidtree; | ||
245 | } else | ||
246 | return -ENOENT; | ||
247 | |||
248 | spin_lock(cidlock); | ||
249 | psidid = id_rb_search(cidtree, psid); | ||
250 | |||
251 | if (!psidid) { /* node does not exist, allocate one & attempt adding */ | ||
252 | spin_unlock(cidlock); | ||
253 | npsidid = kzalloc(sizeof(struct cifs_sid_id), GFP_KERNEL); | ||
254 | if (!npsidid) | ||
255 | return -ENOMEM; | ||
256 | |||
257 | npsidid->sidstr = kmalloc(SIDLEN, GFP_KERNEL); | ||
258 | if (!npsidid->sidstr) { | ||
259 | kfree(npsidid); | ||
260 | return -ENOMEM; | ||
261 | } | ||
262 | |||
263 | spin_lock(cidlock); | ||
264 | psidid = id_rb_search(cidtree, psid); | ||
265 | if (psidid) { /* node happened to get inserted meanwhile */ | ||
266 | ++psidid->refcount; | ||
267 | spin_unlock(cidlock); | ||
268 | kfree(npsidid->sidstr); | ||
269 | kfree(npsidid); | ||
270 | } else { | ||
271 | psidid = npsidid; | ||
272 | id_rb_insert(cidtree, psid, &psidid, | ||
273 | sidtype == SIDOWNER ? "os:" : "gs:"); | ||
274 | ++psidid->refcount; | ||
275 | spin_unlock(cidlock); | ||
89 | } | 276 | } |
277 | } else { | ||
278 | ++psidid->refcount; | ||
279 | spin_unlock(cidlock); | ||
280 | } | ||
281 | |||
282 | /* | ||
283 | * If we are here, it is safe to access psidid and its fields | ||
284 | * since a reference was taken earlier while holding the spinlock. | ||
285 | * A reference on the node is put without holding the spinlock | ||
286 | * and it is OK to do so in this case, shrinker will not erase | ||
287 | * this node until all references are put and we do not access | ||
288 | * any fields of the node after a reference is put . | ||
289 | */ | ||
290 | if (test_bit(SID_ID_MAPPED, &psidid->state)) { | ||
291 | cid = psidid->id; | ||
292 | psidid->time = jiffies; /* update ts for accessing */ | ||
293 | goto sid_to_id_out; | ||
294 | } | ||
90 | 295 | ||
91 | cFYI(1, "matching sid: %s\n", wksidarr[i].sidname); | 296 | if (time_after(psidid->time + SID_MAP_RETRY, jiffies)) |
92 | return 0; /* sids compare/match */ | 297 | goto sid_to_id_out; |
298 | |||
299 | if (!test_and_set_bit(SID_ID_PENDING, &psidid->state)) { | ||
300 | saved_cred = override_creds(root_cred); | ||
301 | idkey = request_key(&cifs_idmap_key_type, psidid->sidstr, ""); | ||
302 | if (IS_ERR(idkey)) | ||
303 | cFYI(1, "%s: Can't map SID to an id", __func__); | ||
304 | else { | ||
305 | cid = *(unsigned long *)idkey->payload.value; | ||
306 | psidid->id = cid; | ||
307 | set_bit(SID_ID_MAPPED, &psidid->state); | ||
308 | key_put(idkey); | ||
309 | kfree(psidid->sidstr); | ||
310 | } | ||
311 | revert_creds(saved_cred); | ||
312 | psidid->time = jiffies; /* update ts for accessing */ | ||
313 | clear_bit(SID_ID_PENDING, &psidid->state); | ||
314 | wake_up_bit(&psidid->state, SID_ID_PENDING); | ||
315 | } else { | ||
316 | rc = wait_on_bit(&psidid->state, SID_ID_PENDING, | ||
317 | sidid_pending_wait, TASK_INTERRUPTIBLE); | ||
318 | if (rc) { | ||
319 | cFYI(1, "%s: sidid_pending_wait interrupted %d", | ||
320 | __func__, rc); | ||
321 | --psidid->refcount; /* decremented without spinlock */ | ||
322 | return rc; | ||
323 | } | ||
324 | if (test_bit(SID_ID_MAPPED, &psidid->state)) | ||
325 | cid = psidid->id; | ||
93 | } | 326 | } |
94 | 327 | ||
95 | cFYI(1, "No matching sid"); | 328 | sid_to_id_out: |
96 | return -1; | 329 | --psidid->refcount; /* decremented without spinlock */ |
330 | if (sidtype == SIDOWNER) | ||
331 | fattr->cf_uid = cid; | ||
332 | else | ||
333 | fattr->cf_gid = cid; | ||
334 | |||
335 | return 0; | ||
336 | } | ||
337 | |||
338 | int | ||
339 | init_cifs_idmap(void) | ||
340 | { | ||
341 | struct cred *cred; | ||
342 | struct key *keyring; | ||
343 | int ret; | ||
344 | |||
345 | cFYI(1, "Registering the %s key type\n", cifs_idmap_key_type.name); | ||
346 | |||
347 | /* create an override credential set with a special thread keyring in | ||
348 | * which requests are cached | ||
349 | * | ||
350 | * this is used to prevent malicious redirections from being installed | ||
351 | * with add_key(). | ||
352 | */ | ||
353 | cred = prepare_kernel_cred(NULL); | ||
354 | if (!cred) | ||
355 | return -ENOMEM; | ||
356 | |||
357 | keyring = key_alloc(&key_type_keyring, ".cifs_idmap", 0, 0, cred, | ||
358 | (KEY_POS_ALL & ~KEY_POS_SETATTR) | | ||
359 | KEY_USR_VIEW | KEY_USR_READ, | ||
360 | KEY_ALLOC_NOT_IN_QUOTA); | ||
361 | if (IS_ERR(keyring)) { | ||
362 | ret = PTR_ERR(keyring); | ||
363 | goto failed_put_cred; | ||
364 | } | ||
365 | |||
366 | ret = key_instantiate_and_link(keyring, NULL, 0, NULL, NULL); | ||
367 | if (ret < 0) | ||
368 | goto failed_put_key; | ||
369 | |||
370 | ret = register_key_type(&cifs_idmap_key_type); | ||
371 | if (ret < 0) | ||
372 | goto failed_put_key; | ||
373 | |||
374 | /* instruct request_key() to use this special keyring as a cache for | ||
375 | * the results it looks up */ | ||
376 | cred->thread_keyring = keyring; | ||
377 | cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING; | ||
378 | root_cred = cred; | ||
379 | |||
380 | spin_lock_init(&siduidlock); | ||
381 | uidtree = RB_ROOT; | ||
382 | spin_lock_init(&sidgidlock); | ||
383 | gidtree = RB_ROOT; | ||
384 | |||
385 | register_shrinker(&cifs_shrinker); | ||
386 | |||
387 | cFYI(1, "cifs idmap keyring: %d\n", key_serial(keyring)); | ||
388 | return 0; | ||
389 | |||
390 | failed_put_key: | ||
391 | key_put(keyring); | ||
392 | failed_put_cred: | ||
393 | put_cred(cred); | ||
394 | return ret; | ||
395 | } | ||
396 | |||
397 | void | ||
398 | exit_cifs_idmap(void) | ||
399 | { | ||
400 | key_revoke(root_cred->thread_keyring); | ||
401 | unregister_key_type(&cifs_idmap_key_type); | ||
402 | put_cred(root_cred); | ||
403 | unregister_shrinker(&cifs_shrinker); | ||
404 | cFYI(1, "Unregistered %s key type\n", cifs_idmap_key_type.name); | ||
405 | } | ||
406 | |||
407 | void | ||
408 | cifs_destroy_idmaptrees(void) | ||
409 | { | ||
410 | struct rb_root *root; | ||
411 | struct rb_node *node; | ||
412 | |||
413 | root = &uidtree; | ||
414 | spin_lock(&siduidlock); | ||
415 | while ((node = rb_first(root))) | ||
416 | rb_erase(node, root); | ||
417 | spin_unlock(&siduidlock); | ||
418 | |||
419 | root = &gidtree; | ||
420 | spin_lock(&sidgidlock); | ||
421 | while ((node = rb_first(root))) | ||
422 | rb_erase(node, root); | ||
423 | spin_unlock(&sidgidlock); | ||
97 | } | 424 | } |
98 | 425 | ||
99 | /* if the two SIDs (roughly equivalent to a UUID for a user or group) are | 426 | /* if the two SIDs (roughly equivalent to a UUID for a user or group) are |
@@ -104,16 +431,24 @@ int compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid) | |||
104 | int num_subauth, num_sat, num_saw; | 431 | int num_subauth, num_sat, num_saw; |
105 | 432 | ||
106 | if ((!ctsid) || (!cwsid)) | 433 | if ((!ctsid) || (!cwsid)) |
107 | return 0; | 434 | return 1; |
108 | 435 | ||
109 | /* compare the revision */ | 436 | /* compare the revision */ |
110 | if (ctsid->revision != cwsid->revision) | 437 | if (ctsid->revision != cwsid->revision) { |
111 | return 0; | 438 | if (ctsid->revision > cwsid->revision) |
439 | return 1; | ||
440 | else | ||
441 | return -1; | ||
442 | } | ||
112 | 443 | ||
113 | /* compare all of the six auth values */ | 444 | /* compare all of the six auth values */ |
114 | for (i = 0; i < 6; ++i) { | 445 | for (i = 0; i < 6; ++i) { |
115 | if (ctsid->authority[i] != cwsid->authority[i]) | 446 | if (ctsid->authority[i] != cwsid->authority[i]) { |
116 | return 0; | 447 | if (ctsid->authority[i] > cwsid->authority[i]) |
448 | return 1; | ||
449 | else | ||
450 | return -1; | ||
451 | } | ||
117 | } | 452 | } |
118 | 453 | ||
119 | /* compare all of the subauth values if any */ | 454 | /* compare all of the subauth values if any */ |
@@ -122,12 +457,16 @@ int compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid) | |||
122 | num_subauth = num_sat < num_saw ? num_sat : num_saw; | 457 | num_subauth = num_sat < num_saw ? num_sat : num_saw; |
123 | if (num_subauth) { | 458 | if (num_subauth) { |
124 | for (i = 0; i < num_subauth; ++i) { | 459 | for (i = 0; i < num_subauth; ++i) { |
125 | if (ctsid->sub_auth[i] != cwsid->sub_auth[i]) | 460 | if (ctsid->sub_auth[i] != cwsid->sub_auth[i]) { |
126 | return 0; | 461 | if (ctsid->sub_auth[i] > cwsid->sub_auth[i]) |
462 | return 1; | ||
463 | else | ||
464 | return -1; | ||
465 | } | ||
127 | } | 466 | } |
128 | } | 467 | } |
129 | 468 | ||
130 | return 1; /* sids compare/match */ | 469 | return 0; /* sids compare/match */ |
131 | } | 470 | } |
132 | 471 | ||
133 | 472 | ||
@@ -382,22 +721,22 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl, | |||
382 | #ifdef CONFIG_CIFS_DEBUG2 | 721 | #ifdef CONFIG_CIFS_DEBUG2 |
383 | dump_ace(ppace[i], end_of_acl); | 722 | dump_ace(ppace[i], end_of_acl); |
384 | #endif | 723 | #endif |
385 | if (compare_sids(&(ppace[i]->sid), pownersid)) | 724 | if (compare_sids(&(ppace[i]->sid), pownersid) == 0) |
386 | access_flags_to_mode(ppace[i]->access_req, | 725 | access_flags_to_mode(ppace[i]->access_req, |
387 | ppace[i]->type, | 726 | ppace[i]->type, |
388 | &fattr->cf_mode, | 727 | &fattr->cf_mode, |
389 | &user_mask); | 728 | &user_mask); |
390 | if (compare_sids(&(ppace[i]->sid), pgrpsid)) | 729 | if (compare_sids(&(ppace[i]->sid), pgrpsid) == 0) |
391 | access_flags_to_mode(ppace[i]->access_req, | 730 | access_flags_to_mode(ppace[i]->access_req, |
392 | ppace[i]->type, | 731 | ppace[i]->type, |
393 | &fattr->cf_mode, | 732 | &fattr->cf_mode, |
394 | &group_mask); | 733 | &group_mask); |
395 | if (compare_sids(&(ppace[i]->sid), &sid_everyone)) | 734 | if (compare_sids(&(ppace[i]->sid), &sid_everyone) == 0) |
396 | access_flags_to_mode(ppace[i]->access_req, | 735 | access_flags_to_mode(ppace[i]->access_req, |
397 | ppace[i]->type, | 736 | ppace[i]->type, |
398 | &fattr->cf_mode, | 737 | &fattr->cf_mode, |
399 | &other_mask); | 738 | &other_mask); |
400 | if (compare_sids(&(ppace[i]->sid), &sid_authusers)) | 739 | if (compare_sids(&(ppace[i]->sid), &sid_authusers) == 0) |
401 | access_flags_to_mode(ppace[i]->access_req, | 740 | access_flags_to_mode(ppace[i]->access_req, |
402 | ppace[i]->type, | 741 | ppace[i]->type, |
403 | &fattr->cf_mode, | 742 | &fattr->cf_mode, |
@@ -475,10 +814,10 @@ static int parse_sid(struct cifs_sid *psid, char *end_of_acl) | |||
475 | 814 | ||
476 | 815 | ||
477 | /* Convert CIFS ACL to POSIX form */ | 816 | /* Convert CIFS ACL to POSIX form */ |
478 | static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len, | 817 | static int parse_sec_desc(struct cifs_sb_info *cifs_sb, |
479 | struct cifs_fattr *fattr) | 818 | struct cifs_ntsd *pntsd, int acl_len, struct cifs_fattr *fattr) |
480 | { | 819 | { |
481 | int rc; | 820 | int rc = 0; |
482 | struct cifs_sid *owner_sid_ptr, *group_sid_ptr; | 821 | struct cifs_sid *owner_sid_ptr, *group_sid_ptr; |
483 | struct cifs_acl *dacl_ptr; /* no need for SACL ptr */ | 822 | struct cifs_acl *dacl_ptr; /* no need for SACL ptr */ |
484 | char *end_of_acl = ((char *)pntsd) + acl_len; | 823 | char *end_of_acl = ((char *)pntsd) + acl_len; |
@@ -500,12 +839,26 @@ static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len, | |||
500 | le32_to_cpu(pntsd->sacloffset), dacloffset); | 839 | le32_to_cpu(pntsd->sacloffset), dacloffset); |
501 | /* cifs_dump_mem("owner_sid: ", owner_sid_ptr, 64); */ | 840 | /* cifs_dump_mem("owner_sid: ", owner_sid_ptr, 64); */ |
502 | rc = parse_sid(owner_sid_ptr, end_of_acl); | 841 | rc = parse_sid(owner_sid_ptr, end_of_acl); |
503 | if (rc) | 842 | if (rc) { |
843 | cFYI(1, "%s: Error %d parsing Owner SID", __func__, rc); | ||
844 | return rc; | ||
845 | } | ||
846 | rc = sid_to_id(cifs_sb, owner_sid_ptr, fattr, SIDOWNER); | ||
847 | if (rc) { | ||
848 | cFYI(1, "%s: Error %d mapping Owner SID to uid", __func__, rc); | ||
504 | return rc; | 849 | return rc; |
850 | } | ||
505 | 851 | ||
506 | rc = parse_sid(group_sid_ptr, end_of_acl); | 852 | rc = parse_sid(group_sid_ptr, end_of_acl); |
507 | if (rc) | 853 | if (rc) { |
854 | cFYI(1, "%s: Error %d mapping Owner SID to gid", __func__, rc); | ||
508 | return rc; | 855 | return rc; |
856 | } | ||
857 | rc = sid_to_id(cifs_sb, group_sid_ptr, fattr, SIDGROUP); | ||
858 | if (rc) { | ||
859 | cFYI(1, "%s: Error %d mapping Group SID to gid", __func__, rc); | ||
860 | return rc; | ||
861 | } | ||
509 | 862 | ||
510 | if (dacloffset) | 863 | if (dacloffset) |
511 | parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr, | 864 | parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr, |
@@ -520,7 +873,7 @@ static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len, | |||
520 | memcpy((void *)(&(cifscred->gsid)), (void *)group_sid_ptr, | 873 | memcpy((void *)(&(cifscred->gsid)), (void *)group_sid_ptr, |
521 | sizeof(struct cifs_sid)); */ | 874 | sizeof(struct cifs_sid)); */ |
522 | 875 | ||
523 | return 0; | 876 | return rc; |
524 | } | 877 | } |
525 | 878 | ||
526 | 879 | ||
@@ -688,7 +1041,7 @@ out: | |||
688 | } | 1041 | } |
689 | 1042 | ||
690 | /* Set an ACL on the server */ | 1043 | /* Set an ACL on the server */ |
691 | static int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen, | 1044 | int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen, |
692 | struct inode *inode, const char *path) | 1045 | struct inode *inode, const char *path) |
693 | { | 1046 | { |
694 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | 1047 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); |
@@ -727,7 +1080,7 @@ cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, | |||
727 | rc = PTR_ERR(pntsd); | 1080 | rc = PTR_ERR(pntsd); |
728 | cERROR(1, "%s: error %d getting sec desc", __func__, rc); | 1081 | cERROR(1, "%s: error %d getting sec desc", __func__, rc); |
729 | } else { | 1082 | } else { |
730 | rc = parse_sec_desc(pntsd, acllen, fattr); | 1083 | rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr); |
731 | kfree(pntsd); | 1084 | kfree(pntsd); |
732 | if (rc) | 1085 | if (rc) |
733 | cERROR(1, "parse sec desc failed rc = %d", rc); | 1086 | cERROR(1, "parse sec desc failed rc = %d", rc); |
diff --git a/fs/cifs/cifsacl.h b/fs/cifs/cifsacl.h index c4ae7d036563..5c902c7ce524 100644 --- a/fs/cifs/cifsacl.h +++ b/fs/cifs/cifsacl.h | |||
@@ -39,6 +39,15 @@ | |||
39 | #define ACCESS_ALLOWED 0 | 39 | #define ACCESS_ALLOWED 0 |
40 | #define ACCESS_DENIED 1 | 40 | #define ACCESS_DENIED 1 |
41 | 41 | ||
42 | #define SIDOWNER 1 | ||
43 | #define SIDGROUP 2 | ||
44 | #define SIDLEN 150 /* S- 1 revision- 6 authorities- max 5 sub authorities */ | ||
45 | |||
46 | #define SID_ID_MAPPED 0 | ||
47 | #define SID_ID_PENDING 1 | ||
48 | #define SID_MAP_EXPIRE (3600 * HZ) /* map entry expires after one hour */ | ||
49 | #define SID_MAP_RETRY (300 * HZ) /* wait 5 minutes for next attempt to map */ | ||
50 | |||
42 | struct cifs_ntsd { | 51 | struct cifs_ntsd { |
43 | __le16 revision; /* revision level */ | 52 | __le16 revision; /* revision level */ |
44 | __le16 type; | 53 | __le16 type; |
@@ -74,7 +83,21 @@ struct cifs_wksid { | |||
74 | char sidname[SIDNAMELENGTH]; | 83 | char sidname[SIDNAMELENGTH]; |
75 | } __attribute__((packed)); | 84 | } __attribute__((packed)); |
76 | 85 | ||
77 | extern int match_sid(struct cifs_sid *); | 86 | struct cifs_sid_id { |
87 | unsigned int refcount; /* increment with spinlock, decrement without */ | ||
88 | unsigned long id; | ||
89 | unsigned long time; | ||
90 | unsigned long state; | ||
91 | char *sidstr; | ||
92 | struct rb_node rbnode; | ||
93 | struct cifs_sid sid; | ||
94 | }; | ||
95 | |||
96 | #ifdef __KERNEL__ | ||
97 | extern struct key_type cifs_idmap_key_type; | ||
98 | extern const struct cred *root_cred; | ||
99 | #endif /* KERNEL */ | ||
100 | |||
78 | extern int compare_sids(const struct cifs_sid *, const struct cifs_sid *); | 101 | extern int compare_sids(const struct cifs_sid *, const struct cifs_sid *); |
79 | 102 | ||
80 | #endif /* _CIFSACL_H */ | 103 | #endif /* _CIFSACL_H */ |
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c index d1a016be73ba..45c3f78c8f81 100644 --- a/fs/cifs/cifsencrypt.c +++ b/fs/cifs/cifsencrypt.c | |||
@@ -60,7 +60,7 @@ static int cifs_calculate_signature(const struct smb_hdr *cifs_pdu, | |||
60 | server->session_key.response, server->session_key.len); | 60 | server->session_key.response, server->session_key.len); |
61 | 61 | ||
62 | crypto_shash_update(&server->secmech.sdescmd5->shash, | 62 | crypto_shash_update(&server->secmech.sdescmd5->shash, |
63 | cifs_pdu->Protocol, cifs_pdu->smb_buf_length); | 63 | cifs_pdu->Protocol, be32_to_cpu(cifs_pdu->smb_buf_length)); |
64 | 64 | ||
65 | rc = crypto_shash_final(&server->secmech.sdescmd5->shash, signature); | 65 | rc = crypto_shash_final(&server->secmech.sdescmd5->shash, signature); |
66 | 66 | ||
@@ -268,10 +268,11 @@ int setup_ntlm_response(struct cifsSesInfo *ses) | |||
268 | } | 268 | } |
269 | 269 | ||
270 | #ifdef CONFIG_CIFS_WEAK_PW_HASH | 270 | #ifdef CONFIG_CIFS_WEAK_PW_HASH |
271 | void calc_lanman_hash(const char *password, const char *cryptkey, bool encrypt, | 271 | int calc_lanman_hash(const char *password, const char *cryptkey, bool encrypt, |
272 | char *lnm_session_key) | 272 | char *lnm_session_key) |
273 | { | 273 | { |
274 | int i; | 274 | int i; |
275 | int rc; | ||
275 | char password_with_pad[CIFS_ENCPWD_SIZE]; | 276 | char password_with_pad[CIFS_ENCPWD_SIZE]; |
276 | 277 | ||
277 | memset(password_with_pad, 0, CIFS_ENCPWD_SIZE); | 278 | memset(password_with_pad, 0, CIFS_ENCPWD_SIZE); |
@@ -282,7 +283,7 @@ void calc_lanman_hash(const char *password, const char *cryptkey, bool encrypt, | |||
282 | memset(lnm_session_key, 0, CIFS_SESS_KEY_SIZE); | 283 | memset(lnm_session_key, 0, CIFS_SESS_KEY_SIZE); |
283 | memcpy(lnm_session_key, password_with_pad, | 284 | memcpy(lnm_session_key, password_with_pad, |
284 | CIFS_ENCPWD_SIZE); | 285 | CIFS_ENCPWD_SIZE); |
285 | return; | 286 | return 0; |
286 | } | 287 | } |
287 | 288 | ||
288 | /* calculate old style session key */ | 289 | /* calculate old style session key */ |
@@ -299,10 +300,9 @@ void calc_lanman_hash(const char *password, const char *cryptkey, bool encrypt, | |||
299 | for (i = 0; i < CIFS_ENCPWD_SIZE; i++) | 300 | for (i = 0; i < CIFS_ENCPWD_SIZE; i++) |
300 | password_with_pad[i] = toupper(password_with_pad[i]); | 301 | password_with_pad[i] = toupper(password_with_pad[i]); |
301 | 302 | ||
302 | SMBencrypt(password_with_pad, cryptkey, lnm_session_key); | 303 | rc = SMBencrypt(password_with_pad, cryptkey, lnm_session_key); |
303 | 304 | ||
304 | /* clear password before we return/free memory */ | 305 | return rc; |
305 | memset(password_with_pad, 0, CIFS_ENCPWD_SIZE); | ||
306 | } | 306 | } |
307 | #endif /* CIFS_WEAK_PW_HASH */ | 307 | #endif /* CIFS_WEAK_PW_HASH */ |
308 | 308 | ||
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 5c412b33cd7c..493b74ca5648 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
@@ -128,29 +128,22 @@ cifs_read_super(struct super_block *sb, void *data, | |||
128 | } | 128 | } |
129 | cifs_sb->bdi.ra_pages = default_backing_dev_info.ra_pages; | 129 | cifs_sb->bdi.ra_pages = default_backing_dev_info.ra_pages; |
130 | 130 | ||
131 | #ifdef CONFIG_CIFS_DFS_UPCALL | 131 | /* |
132 | /* copy mount params to sb for use in submounts */ | 132 | * Copy mount params to sb for use in submounts. Better to do |
133 | /* BB: should we move this after the mount so we | 133 | * the copy here and deal with the error before cleanup gets |
134 | * do not have to do the copy on failed mounts? | 134 | * complicated post-mount. |
135 | * BB: May be it is better to do simple copy before | 135 | */ |
136 | * complex operation (mount), and in case of fail | ||
137 | * just exit instead of doing mount and attempting | ||
138 | * undo it if this copy fails?*/ | ||
139 | if (data) { | 136 | if (data) { |
140 | int len = strlen(data); | 137 | cifs_sb->mountdata = kstrndup(data, PAGE_SIZE, GFP_KERNEL); |
141 | cifs_sb->mountdata = kzalloc(len + 1, GFP_KERNEL); | ||
142 | if (cifs_sb->mountdata == NULL) { | 138 | if (cifs_sb->mountdata == NULL) { |
143 | bdi_destroy(&cifs_sb->bdi); | 139 | bdi_destroy(&cifs_sb->bdi); |
144 | kfree(sb->s_fs_info); | 140 | kfree(sb->s_fs_info); |
145 | sb->s_fs_info = NULL; | 141 | sb->s_fs_info = NULL; |
146 | return -ENOMEM; | 142 | return -ENOMEM; |
147 | } | 143 | } |
148 | strncpy(cifs_sb->mountdata, data, len + 1); | ||
149 | cifs_sb->mountdata[len] = '\0'; | ||
150 | } | 144 | } |
151 | #endif | ||
152 | 145 | ||
153 | rc = cifs_mount(sb, cifs_sb, data, devname); | 146 | rc = cifs_mount(sb, cifs_sb, devname); |
154 | 147 | ||
155 | if (rc) { | 148 | if (rc) { |
156 | if (!silent) | 149 | if (!silent) |
@@ -163,7 +156,7 @@ cifs_read_super(struct super_block *sb, void *data, | |||
163 | sb->s_bdi = &cifs_sb->bdi; | 156 | sb->s_bdi = &cifs_sb->bdi; |
164 | sb->s_blocksize = CIFS_MAX_MSGSIZE; | 157 | sb->s_blocksize = CIFS_MAX_MSGSIZE; |
165 | sb->s_blocksize_bits = 14; /* default 2**14 = CIFS_MAX_MSGSIZE */ | 158 | sb->s_blocksize_bits = 14; /* default 2**14 = CIFS_MAX_MSGSIZE */ |
166 | inode = cifs_root_iget(sb, ROOT_I); | 159 | inode = cifs_root_iget(sb); |
167 | 160 | ||
168 | if (IS_ERR(inode)) { | 161 | if (IS_ERR(inode)) { |
169 | rc = PTR_ERR(inode); | 162 | rc = PTR_ERR(inode); |
@@ -184,12 +177,12 @@ cifs_read_super(struct super_block *sb, void *data, | |||
184 | else | 177 | else |
185 | sb->s_d_op = &cifs_dentry_ops; | 178 | sb->s_d_op = &cifs_dentry_ops; |
186 | 179 | ||
187 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 180 | #ifdef CIFS_NFSD_EXPORT |
188 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { | 181 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { |
189 | cFYI(1, "export ops supported"); | 182 | cFYI(1, "export ops supported"); |
190 | sb->s_export_op = &cifs_export_ops; | 183 | sb->s_export_op = &cifs_export_ops; |
191 | } | 184 | } |
192 | #endif /* EXPERIMENTAL */ | 185 | #endif /* CIFS_NFSD_EXPORT */ |
193 | 186 | ||
194 | return 0; | 187 | return 0; |
195 | 188 | ||
@@ -202,12 +195,10 @@ out_no_root: | |||
202 | 195 | ||
203 | out_mount_failed: | 196 | out_mount_failed: |
204 | if (cifs_sb) { | 197 | if (cifs_sb) { |
205 | #ifdef CONFIG_CIFS_DFS_UPCALL | ||
206 | if (cifs_sb->mountdata) { | 198 | if (cifs_sb->mountdata) { |
207 | kfree(cifs_sb->mountdata); | 199 | kfree(cifs_sb->mountdata); |
208 | cifs_sb->mountdata = NULL; | 200 | cifs_sb->mountdata = NULL; |
209 | } | 201 | } |
210 | #endif | ||
211 | unload_nls(cifs_sb->local_nls); | 202 | unload_nls(cifs_sb->local_nls); |
212 | bdi_destroy(&cifs_sb->bdi); | 203 | bdi_destroy(&cifs_sb->bdi); |
213 | kfree(cifs_sb); | 204 | kfree(cifs_sb); |
@@ -231,12 +222,10 @@ cifs_put_super(struct super_block *sb) | |||
231 | rc = cifs_umount(sb, cifs_sb); | 222 | rc = cifs_umount(sb, cifs_sb); |
232 | if (rc) | 223 | if (rc) |
233 | cERROR(1, "cifs_umount failed with return code %d", rc); | 224 | cERROR(1, "cifs_umount failed with return code %d", rc); |
234 | #ifdef CONFIG_CIFS_DFS_UPCALL | ||
235 | if (cifs_sb->mountdata) { | 225 | if (cifs_sb->mountdata) { |
236 | kfree(cifs_sb->mountdata); | 226 | kfree(cifs_sb->mountdata); |
237 | cifs_sb->mountdata = NULL; | 227 | cifs_sb->mountdata = NULL; |
238 | } | 228 | } |
239 | #endif | ||
240 | 229 | ||
241 | unload_nls(cifs_sb->local_nls); | 230 | unload_nls(cifs_sb->local_nls); |
242 | bdi_destroy(&cifs_sb->bdi); | 231 | bdi_destroy(&cifs_sb->bdi); |
@@ -618,16 +607,31 @@ static loff_t cifs_llseek(struct file *file, loff_t offset, int origin) | |||
618 | { | 607 | { |
619 | /* origin == SEEK_END => we must revalidate the cached file length */ | 608 | /* origin == SEEK_END => we must revalidate the cached file length */ |
620 | if (origin == SEEK_END) { | 609 | if (origin == SEEK_END) { |
621 | int retval; | 610 | int rc; |
622 | 611 | struct inode *inode = file->f_path.dentry->d_inode; | |
623 | /* some applications poll for the file length in this strange | 612 | |
624 | way so we must seek to end on non-oplocked files by | 613 | /* |
625 | setting the revalidate time to zero */ | 614 | * We need to be sure that all dirty pages are written and the |
626 | CIFS_I(file->f_path.dentry->d_inode)->time = 0; | 615 | * server has the newest file length. |
627 | 616 | */ | |
628 | retval = cifs_revalidate_file(file); | 617 | if (!CIFS_I(inode)->clientCanCacheRead && inode->i_mapping && |
629 | if (retval < 0) | 618 | inode->i_mapping->nrpages != 0) { |
630 | return (loff_t)retval; | 619 | rc = filemap_fdatawait(inode->i_mapping); |
620 | if (rc) { | ||
621 | mapping_set_error(inode->i_mapping, rc); | ||
622 | return rc; | ||
623 | } | ||
624 | } | ||
625 | /* | ||
626 | * Some applications poll for the file length in this strange | ||
627 | * way so we must seek to end on non-oplocked files by | ||
628 | * setting the revalidate time to zero. | ||
629 | */ | ||
630 | CIFS_I(inode)->time = 0; | ||
631 | |||
632 | rc = cifs_revalidate_file_attr(file); | ||
633 | if (rc < 0) | ||
634 | return (loff_t)rc; | ||
631 | } | 635 | } |
632 | return generic_file_llseek_unlocked(file, offset, origin); | 636 | return generic_file_llseek_unlocked(file, offset, origin); |
633 | } | 637 | } |
@@ -760,10 +764,11 @@ const struct file_operations cifs_file_strict_ops = { | |||
760 | }; | 764 | }; |
761 | 765 | ||
762 | const struct file_operations cifs_file_direct_ops = { | 766 | const struct file_operations cifs_file_direct_ops = { |
763 | /* no aio, no readv - | 767 | /* BB reevaluate whether they can be done with directio, no cache */ |
764 | BB reevaluate whether they can be done with directio, no cache */ | 768 | .read = do_sync_read, |
765 | .read = cifs_user_read, | 769 | .write = do_sync_write, |
766 | .write = cifs_user_write, | 770 | .aio_read = cifs_user_readv, |
771 | .aio_write = cifs_user_writev, | ||
767 | .open = cifs_open, | 772 | .open = cifs_open, |
768 | .release = cifs_close, | 773 | .release = cifs_close, |
769 | .lock = cifs_lock, | 774 | .lock = cifs_lock, |
@@ -815,10 +820,11 @@ const struct file_operations cifs_file_strict_nobrl_ops = { | |||
815 | }; | 820 | }; |
816 | 821 | ||
817 | const struct file_operations cifs_file_direct_nobrl_ops = { | 822 | const struct file_operations cifs_file_direct_nobrl_ops = { |
818 | /* no mmap, no aio, no readv - | 823 | /* BB reevaluate whether they can be done with directio, no cache */ |
819 | BB reevaluate whether they can be done with directio, no cache */ | 824 | .read = do_sync_read, |
820 | .read = cifs_user_read, | 825 | .write = do_sync_write, |
821 | .write = cifs_user_write, | 826 | .aio_read = cifs_user_readv, |
827 | .aio_write = cifs_user_writev, | ||
822 | .open = cifs_open, | 828 | .open = cifs_open, |
823 | .release = cifs_close, | 829 | .release = cifs_close, |
824 | .fsync = cifs_fsync, | 830 | .fsync = cifs_fsync, |
@@ -981,10 +987,10 @@ init_cifs(void) | |||
981 | int rc = 0; | 987 | int rc = 0; |
982 | cifs_proc_init(); | 988 | cifs_proc_init(); |
983 | INIT_LIST_HEAD(&cifs_tcp_ses_list); | 989 | INIT_LIST_HEAD(&cifs_tcp_ses_list); |
984 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 990 | #ifdef CONFIG_CIFS_DNOTIFY_EXPERIMENTAL /* unused temporarily */ |
985 | INIT_LIST_HEAD(&GlobalDnotifyReqList); | 991 | INIT_LIST_HEAD(&GlobalDnotifyReqList); |
986 | INIT_LIST_HEAD(&GlobalDnotifyRsp_Q); | 992 | INIT_LIST_HEAD(&GlobalDnotifyRsp_Q); |
987 | #endif | 993 | #endif /* was needed for dnotify, and will be needed for inotify when VFS fix */ |
988 | /* | 994 | /* |
989 | * Initialize Global counters | 995 | * Initialize Global counters |
990 | */ | 996 | */ |
@@ -1033,22 +1039,33 @@ init_cifs(void) | |||
1033 | if (rc) | 1039 | if (rc) |
1034 | goto out_destroy_mids; | 1040 | goto out_destroy_mids; |
1035 | 1041 | ||
1036 | rc = register_filesystem(&cifs_fs_type); | ||
1037 | if (rc) | ||
1038 | goto out_destroy_request_bufs; | ||
1039 | #ifdef CONFIG_CIFS_UPCALL | 1042 | #ifdef CONFIG_CIFS_UPCALL |
1040 | rc = register_key_type(&cifs_spnego_key_type); | 1043 | rc = register_key_type(&cifs_spnego_key_type); |
1041 | if (rc) | 1044 | if (rc) |
1042 | goto out_unregister_filesystem; | 1045 | goto out_destroy_request_bufs; |
1043 | #endif | 1046 | #endif /* CONFIG_CIFS_UPCALL */ |
1047 | |||
1048 | #ifdef CONFIG_CIFS_ACL | ||
1049 | rc = init_cifs_idmap(); | ||
1050 | if (rc) | ||
1051 | goto out_register_key_type; | ||
1052 | #endif /* CONFIG_CIFS_ACL */ | ||
1053 | |||
1054 | rc = register_filesystem(&cifs_fs_type); | ||
1055 | if (rc) | ||
1056 | goto out_init_cifs_idmap; | ||
1044 | 1057 | ||
1045 | return 0; | 1058 | return 0; |
1046 | 1059 | ||
1047 | #ifdef CONFIG_CIFS_UPCALL | 1060 | out_init_cifs_idmap: |
1048 | out_unregister_filesystem: | 1061 | #ifdef CONFIG_CIFS_ACL |
1049 | unregister_filesystem(&cifs_fs_type); | 1062 | exit_cifs_idmap(); |
1063 | out_register_key_type: | ||
1050 | #endif | 1064 | #endif |
1065 | #ifdef CONFIG_CIFS_UPCALL | ||
1066 | unregister_key_type(&cifs_spnego_key_type); | ||
1051 | out_destroy_request_bufs: | 1067 | out_destroy_request_bufs: |
1068 | #endif | ||
1052 | cifs_destroy_request_bufs(); | 1069 | cifs_destroy_request_bufs(); |
1053 | out_destroy_mids: | 1070 | out_destroy_mids: |
1054 | cifs_destroy_mids(); | 1071 | cifs_destroy_mids(); |
@@ -1070,6 +1087,10 @@ exit_cifs(void) | |||
1070 | #ifdef CONFIG_CIFS_DFS_UPCALL | 1087 | #ifdef CONFIG_CIFS_DFS_UPCALL |
1071 | cifs_dfs_release_automount_timer(); | 1088 | cifs_dfs_release_automount_timer(); |
1072 | #endif | 1089 | #endif |
1090 | #ifdef CONFIG_CIFS_ACL | ||
1091 | cifs_destroy_idmaptrees(); | ||
1092 | exit_cifs_idmap(); | ||
1093 | #endif | ||
1073 | #ifdef CONFIG_CIFS_UPCALL | 1094 | #ifdef CONFIG_CIFS_UPCALL |
1074 | unregister_key_type(&cifs_spnego_key_type); | 1095 | unregister_key_type(&cifs_spnego_key_type); |
1075 | #endif | 1096 | #endif |
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index a9371b6578c0..64313f778ebf 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h | |||
@@ -47,7 +47,7 @@ extern void cifs_sb_deactive(struct super_block *sb); | |||
47 | 47 | ||
48 | /* Functions related to inodes */ | 48 | /* Functions related to inodes */ |
49 | extern const struct inode_operations cifs_dir_inode_ops; | 49 | extern const struct inode_operations cifs_dir_inode_ops; |
50 | extern struct inode *cifs_root_iget(struct super_block *, unsigned long); | 50 | extern struct inode *cifs_root_iget(struct super_block *); |
51 | extern int cifs_create(struct inode *, struct dentry *, int, | 51 | extern int cifs_create(struct inode *, struct dentry *, int, |
52 | struct nameidata *); | 52 | struct nameidata *); |
53 | extern struct dentry *cifs_lookup(struct inode *, struct dentry *, | 53 | extern struct dentry *cifs_lookup(struct inode *, struct dentry *, |
@@ -59,9 +59,11 @@ extern int cifs_mkdir(struct inode *, struct dentry *, int); | |||
59 | extern int cifs_rmdir(struct inode *, struct dentry *); | 59 | extern int cifs_rmdir(struct inode *, struct dentry *); |
60 | extern int cifs_rename(struct inode *, struct dentry *, struct inode *, | 60 | extern int cifs_rename(struct inode *, struct dentry *, struct inode *, |
61 | struct dentry *); | 61 | struct dentry *); |
62 | extern int cifs_revalidate_file_attr(struct file *filp); | ||
63 | extern int cifs_revalidate_dentry_attr(struct dentry *); | ||
62 | extern int cifs_revalidate_file(struct file *filp); | 64 | extern int cifs_revalidate_file(struct file *filp); |
63 | extern int cifs_revalidate_dentry(struct dentry *); | 65 | extern int cifs_revalidate_dentry(struct dentry *); |
64 | extern void cifs_invalidate_mapping(struct inode *inode); | 66 | extern int cifs_invalidate_mapping(struct inode *inode); |
65 | extern int cifs_getattr(struct vfsmount *, struct dentry *, struct kstat *); | 67 | extern int cifs_getattr(struct vfsmount *, struct dentry *, struct kstat *); |
66 | extern int cifs_setattr(struct dentry *, struct iattr *); | 68 | extern int cifs_setattr(struct dentry *, struct iattr *); |
67 | 69 | ||
@@ -80,12 +82,12 @@ extern const struct file_operations cifs_file_strict_nobrl_ops; | |||
80 | extern int cifs_open(struct inode *inode, struct file *file); | 82 | extern int cifs_open(struct inode *inode, struct file *file); |
81 | extern int cifs_close(struct inode *inode, struct file *file); | 83 | extern int cifs_close(struct inode *inode, struct file *file); |
82 | extern int cifs_closedir(struct inode *inode, struct file *file); | 84 | extern int cifs_closedir(struct inode *inode, struct file *file); |
83 | extern ssize_t cifs_user_read(struct file *file, char __user *read_data, | 85 | extern ssize_t cifs_user_readv(struct kiocb *iocb, const struct iovec *iov, |
84 | size_t read_size, loff_t *poffset); | 86 | unsigned long nr_segs, loff_t pos); |
85 | extern ssize_t cifs_strict_readv(struct kiocb *iocb, const struct iovec *iov, | 87 | extern ssize_t cifs_strict_readv(struct kiocb *iocb, const struct iovec *iov, |
86 | unsigned long nr_segs, loff_t pos); | 88 | unsigned long nr_segs, loff_t pos); |
87 | extern ssize_t cifs_user_write(struct file *file, const char __user *write_data, | 89 | extern ssize_t cifs_user_writev(struct kiocb *iocb, const struct iovec *iov, |
88 | size_t write_size, loff_t *poffset); | 90 | unsigned long nr_segs, loff_t pos); |
89 | extern ssize_t cifs_strict_writev(struct kiocb *iocb, const struct iovec *iov, | 91 | extern ssize_t cifs_strict_writev(struct kiocb *iocb, const struct iovec *iov, |
90 | unsigned long nr_segs, loff_t pos); | 92 | unsigned long nr_segs, loff_t pos); |
91 | extern int cifs_lock(struct file *, int, struct file_lock *); | 93 | extern int cifs_lock(struct file *, int, struct file_lock *); |
@@ -123,9 +125,9 @@ extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t); | |||
123 | extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); | 125 | extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); |
124 | extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg); | 126 | extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg); |
125 | 127 | ||
126 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 128 | #ifdef CIFS_NFSD_EXPORT |
127 | extern const struct export_operations cifs_export_ops; | 129 | extern const struct export_operations cifs_export_ops; |
128 | #endif /* EXPERIMENTAL */ | 130 | #endif /* CIFS_NFSD_EXPORT */ |
129 | 131 | ||
130 | #define CIFS_VERSION "1.71" | 132 | #define CIFS_VERSION "1.72" |
131 | #endif /* _CIFSFS_H */ | 133 | #endif /* _CIFSFS_H */ |
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index a5d1106fcbde..76b4517e74b0 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
@@ -274,7 +274,8 @@ struct cifsSesInfo { | |||
274 | int capabilities; | 274 | int capabilities; |
275 | char serverName[SERVER_NAME_LEN_WITH_NULL * 2]; /* BB make bigger for | 275 | char serverName[SERVER_NAME_LEN_WITH_NULL * 2]; /* BB make bigger for |
276 | TCP names - will ipv6 and sctp addresses fit? */ | 276 | TCP names - will ipv6 and sctp addresses fit? */ |
277 | char *user_name; | 277 | char *user_name; /* must not be null except during init of sess |
278 | and after mount option parsing we fill it */ | ||
278 | char *domainName; | 279 | char *domainName; |
279 | char *password; | 280 | char *password; |
280 | struct session_key auth_key; | 281 | struct session_key auth_key; |
@@ -780,10 +781,12 @@ GLOBAL_EXTERN spinlock_t cifs_tcp_ses_lock; | |||
780 | */ | 781 | */ |
781 | GLOBAL_EXTERN spinlock_t cifs_file_list_lock; | 782 | GLOBAL_EXTERN spinlock_t cifs_file_list_lock; |
782 | 783 | ||
784 | #ifdef CONFIG_CIFS_DNOTIFY_EXPERIMENTAL /* unused temporarily */ | ||
783 | /* Outstanding dir notify requests */ | 785 | /* Outstanding dir notify requests */ |
784 | GLOBAL_EXTERN struct list_head GlobalDnotifyReqList; | 786 | GLOBAL_EXTERN struct list_head GlobalDnotifyReqList; |
785 | /* DirNotify response queue */ | 787 | /* DirNotify response queue */ |
786 | GLOBAL_EXTERN struct list_head GlobalDnotifyRsp_Q; | 788 | GLOBAL_EXTERN struct list_head GlobalDnotifyRsp_Q; |
789 | #endif /* was needed for dnotify, and will be needed for inotify when VFS fix */ | ||
787 | 790 | ||
788 | /* | 791 | /* |
789 | * Global transaction id (XID) information | 792 | * Global transaction id (XID) information |
@@ -830,6 +833,11 @@ GLOBAL_EXTERN unsigned int cifs_max_pending; /* MAX requests at once to server*/ | |||
830 | /* reconnect after this many failed echo attempts */ | 833 | /* reconnect after this many failed echo attempts */ |
831 | GLOBAL_EXTERN unsigned short echo_retries; | 834 | GLOBAL_EXTERN unsigned short echo_retries; |
832 | 835 | ||
836 | GLOBAL_EXTERN struct rb_root uidtree; | ||
837 | GLOBAL_EXTERN struct rb_root gidtree; | ||
838 | GLOBAL_EXTERN spinlock_t siduidlock; | ||
839 | GLOBAL_EXTERN spinlock_t sidgidlock; | ||
840 | |||
833 | void cifs_oplock_break(struct work_struct *work); | 841 | void cifs_oplock_break(struct work_struct *work); |
834 | void cifs_oplock_break_get(struct cifsFileInfo *cfile); | 842 | void cifs_oplock_break_get(struct cifsFileInfo *cfile); |
835 | void cifs_oplock_break_put(struct cifsFileInfo *cfile); | 843 | void cifs_oplock_break_put(struct cifsFileInfo *cfile); |
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h index b5c8cc5d7a7f..de3aa285de03 100644 --- a/fs/cifs/cifspdu.h +++ b/fs/cifs/cifspdu.h | |||
@@ -397,9 +397,9 @@ | |||
397 | #define GETU32(var) (*((__u32 *)var)) /* BB check for endian issues */ | 397 | #define GETU32(var) (*((__u32 *)var)) /* BB check for endian issues */ |
398 | 398 | ||
399 | struct smb_hdr { | 399 | struct smb_hdr { |
400 | __u32 smb_buf_length; /* big endian on wire *//* BB length is only two | 400 | __be32 smb_buf_length; /* BB length is only two (rarely three) bytes, |
401 | or three bytes - with one or two byte type preceding it that are | 401 | with one or two byte "type" preceding it that will be |
402 | zero - we could mask the type byte off just in case BB */ | 402 | zero - we could mask the type byte off */ |
403 | __u8 Protocol[4]; | 403 | __u8 Protocol[4]; |
404 | __u8 Command; | 404 | __u8 Command; |
405 | union { | 405 | union { |
@@ -428,43 +428,28 @@ struct smb_hdr { | |||
428 | __u8 WordCount; | 428 | __u8 WordCount; |
429 | } __attribute__((packed)); | 429 | } __attribute__((packed)); |
430 | 430 | ||
431 | /* given a pointer to an smb_hdr retrieve a char pointer to the byte count */ | 431 | /* given a pointer to an smb_hdr, retrieve a void pointer to the ByteCount */ |
432 | #define BCC(smb_var) ((unsigned char *)(smb_var) + sizeof(struct smb_hdr) + \ | 432 | static inline void * |
433 | (2 * (smb_var)->WordCount)) | 433 | BCC(struct smb_hdr *smb) |
434 | { | ||
435 | return (void *)smb + sizeof(*smb) + 2 * smb->WordCount; | ||
436 | } | ||
434 | 437 | ||
435 | /* given a pointer to an smb_hdr retrieve the pointer to the byte area */ | 438 | /* given a pointer to an smb_hdr retrieve the pointer to the byte area */ |
436 | #define pByteArea(smb_var) (BCC(smb_var) + 2) | 439 | #define pByteArea(smb_var) (BCC(smb_var) + 2) |
437 | 440 | ||
438 | /* get the converted ByteCount for a SMB packet and return it */ | ||
439 | static inline __u16 | ||
440 | get_bcc(struct smb_hdr *hdr) | ||
441 | { | ||
442 | __u16 *bc_ptr = (__u16 *)BCC(hdr); | ||
443 | |||
444 | return get_unaligned(bc_ptr); | ||
445 | } | ||
446 | |||
447 | /* get the unconverted ByteCount for a SMB packet and return it */ | 441 | /* get the unconverted ByteCount for a SMB packet and return it */ |
448 | static inline __u16 | 442 | static inline __u16 |
449 | get_bcc_le(struct smb_hdr *hdr) | 443 | get_bcc(struct smb_hdr *hdr) |
450 | { | 444 | { |
451 | __le16 *bc_ptr = (__le16 *)BCC(hdr); | 445 | __le16 *bc_ptr = (__le16 *)BCC(hdr); |
452 | 446 | ||
453 | return get_unaligned_le16(bc_ptr); | 447 | return get_unaligned_le16(bc_ptr); |
454 | } | 448 | } |
455 | 449 | ||
456 | /* set the ByteCount for a SMB packet in host-byte order */ | ||
457 | static inline void | ||
458 | put_bcc(__u16 count, struct smb_hdr *hdr) | ||
459 | { | ||
460 | __u16 *bc_ptr = (__u16 *)BCC(hdr); | ||
461 | |||
462 | put_unaligned(count, bc_ptr); | ||
463 | } | ||
464 | |||
465 | /* set the ByteCount for a SMB packet in little-endian */ | 450 | /* set the ByteCount for a SMB packet in little-endian */ |
466 | static inline void | 451 | static inline void |
467 | put_bcc_le(__u16 count, struct smb_hdr *hdr) | 452 | put_bcc(__u16 count, struct smb_hdr *hdr) |
468 | { | 453 | { |
469 | __le16 *bc_ptr = (__le16 *)BCC(hdr); | 454 | __le16 *bc_ptr = (__le16 *)BCC(hdr); |
470 | 455 | ||
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 8096f27ad9a8..6e69e06a30b3 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
@@ -53,6 +53,9 @@ do { \ | |||
53 | cFYI(1, "CIFS VFS: leaving %s (xid = %d) rc = %d", \ | 53 | cFYI(1, "CIFS VFS: leaving %s (xid = %d) rc = %d", \ |
54 | __func__, curr_xid, (int)rc); \ | 54 | __func__, curr_xid, (int)rc); \ |
55 | } while (0) | 55 | } while (0) |
56 | extern int init_cifs_idmap(void); | ||
57 | extern void exit_cifs_idmap(void); | ||
58 | extern void cifs_destroy_idmaptrees(void); | ||
56 | extern char *build_path_from_dentry(struct dentry *); | 59 | extern char *build_path_from_dentry(struct dentry *); |
57 | extern char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb, | 60 | extern char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb, |
58 | struct cifsTconInfo *tcon); | 61 | struct cifsTconInfo *tcon); |
@@ -90,7 +93,6 @@ extern void cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset, | |||
90 | extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *, bool); | 93 | extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *, bool); |
91 | extern struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *, bool); | 94 | extern struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *, bool); |
92 | extern unsigned int smbCalcSize(struct smb_hdr *ptr); | 95 | extern unsigned int smbCalcSize(struct smb_hdr *ptr); |
93 | extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr); | ||
94 | extern int decode_negTokenInit(unsigned char *security_blob, int length, | 96 | extern int decode_negTokenInit(unsigned char *security_blob, int length, |
95 | struct TCP_Server_Info *server); | 97 | struct TCP_Server_Info *server); |
96 | extern int cifs_convert_address(struct sockaddr *dst, const char *src, int len); | 98 | extern int cifs_convert_address(struct sockaddr *dst, const char *src, int len); |
@@ -143,8 +145,10 @@ extern int cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, | |||
143 | extern int mode_to_cifs_acl(struct inode *inode, const char *path, __u64); | 145 | extern int mode_to_cifs_acl(struct inode *inode, const char *path, __u64); |
144 | extern struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *, struct inode *, | 146 | extern struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *, struct inode *, |
145 | const char *, u32 *); | 147 | const char *, u32 *); |
148 | extern int set_cifs_acl(struct cifs_ntsd *, __u32, struct inode *, | ||
149 | const char *); | ||
146 | 150 | ||
147 | extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *, | 151 | extern int cifs_mount(struct super_block *, struct cifs_sb_info *, |
148 | const char *); | 152 | const char *); |
149 | extern int cifs_umount(struct super_block *, struct cifs_sb_info *); | 153 | extern int cifs_umount(struct super_block *, struct cifs_sb_info *); |
150 | extern void cifs_dfs_release_automount_timer(void); | 154 | extern void cifs_dfs_release_automount_timer(void); |
@@ -304,12 +308,13 @@ extern int CIFSSMBUnixQuerySymLink(const int xid, | |||
304 | struct cifsTconInfo *tcon, | 308 | struct cifsTconInfo *tcon, |
305 | const unsigned char *searchName, char **syminfo, | 309 | const unsigned char *searchName, char **syminfo, |
306 | const struct nls_table *nls_codepage); | 310 | const struct nls_table *nls_codepage); |
311 | #ifdef CONFIG_CIFS_SYMLINK_EXPERIMENTAL | ||
307 | extern int CIFSSMBQueryReparseLinkInfo(const int xid, | 312 | extern int CIFSSMBQueryReparseLinkInfo(const int xid, |
308 | struct cifsTconInfo *tcon, | 313 | struct cifsTconInfo *tcon, |
309 | const unsigned char *searchName, | 314 | const unsigned char *searchName, |
310 | char *symlinkinfo, const int buflen, __u16 fid, | 315 | char *symlinkinfo, const int buflen, __u16 fid, |
311 | const struct nls_table *nls_codepage); | 316 | const struct nls_table *nls_codepage); |
312 | 317 | #endif /* temporarily unused until cifs_symlink fixed */ | |
313 | extern int CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon, | 318 | extern int CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon, |
314 | const char *fileName, const int disposition, | 319 | const char *fileName, const int disposition, |
315 | const int access_flags, const int omode, | 320 | const int access_flags, const int omode, |
@@ -348,8 +353,6 @@ extern int CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon, | |||
348 | const unsigned char *searchName, __u64 *inode_number, | 353 | const unsigned char *searchName, __u64 *inode_number, |
349 | const struct nls_table *nls_codepage, | 354 | const struct nls_table *nls_codepage, |
350 | int remap_special_chars); | 355 | int remap_special_chars); |
351 | extern int cifsConvertToUCS(__le16 *target, const char *source, int maxlen, | ||
352 | const struct nls_table *cp, int mapChars); | ||
353 | 356 | ||
354 | extern int CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, | 357 | extern int CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, |
355 | const __u16 netfid, const __u64 len, | 358 | const __u16 netfid, const __u64 len, |
@@ -383,9 +386,15 @@ extern void cifs_crypto_shash_release(struct TCP_Server_Info *); | |||
383 | extern int calc_seckey(struct cifsSesInfo *); | 386 | extern int calc_seckey(struct cifsSesInfo *); |
384 | 387 | ||
385 | #ifdef CONFIG_CIFS_WEAK_PW_HASH | 388 | #ifdef CONFIG_CIFS_WEAK_PW_HASH |
386 | extern void calc_lanman_hash(const char *password, const char *cryptkey, | 389 | extern int calc_lanman_hash(const char *password, const char *cryptkey, |
387 | bool encrypt, char *lnm_session_key); | 390 | bool encrypt, char *lnm_session_key); |
388 | #endif /* CIFS_WEAK_PW_HASH */ | 391 | #endif /* CIFS_WEAK_PW_HASH */ |
392 | #ifdef CONFIG_CIFS_DNOTIFY_EXPERIMENTAL /* unused temporarily */ | ||
393 | extern int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon, | ||
394 | const int notify_subdirs, const __u16 netfid, | ||
395 | __u32 filter, struct file *file, int multishot, | ||
396 | const struct nls_table *nls_codepage); | ||
397 | #endif /* was needed for dnotify, and will be needed for inotify when VFS fix */ | ||
389 | extern int CIFSSMBCopy(int xid, | 398 | extern int CIFSSMBCopy(int xid, |
390 | struct cifsTconInfo *source_tcon, | 399 | struct cifsTconInfo *source_tcon, |
391 | const char *fromName, | 400 | const char *fromName, |
@@ -393,10 +402,6 @@ extern int CIFSSMBCopy(int xid, | |||
393 | const char *toName, const int flags, | 402 | const char *toName, const int flags, |
394 | const struct nls_table *nls_codepage, | 403 | const struct nls_table *nls_codepage, |
395 | int remap_special_chars); | 404 | int remap_special_chars); |
396 | extern int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon, | ||
397 | const int notify_subdirs, const __u16 netfid, | ||
398 | __u32 filter, struct file *file, int multishot, | ||
399 | const struct nls_table *nls_codepage); | ||
400 | extern ssize_t CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon, | 405 | extern ssize_t CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon, |
401 | const unsigned char *searchName, | 406 | const unsigned char *searchName, |
402 | const unsigned char *ea_name, char *EAData, | 407 | const unsigned char *ea_name, char *EAData, |
@@ -427,9 +432,6 @@ extern int CIFSCheckMFSymlink(struct cifs_fattr *fattr, | |||
427 | struct cifs_sb_info *cifs_sb, int xid); | 432 | struct cifs_sb_info *cifs_sb, int xid); |
428 | extern int mdfour(unsigned char *, unsigned char *, int); | 433 | extern int mdfour(unsigned char *, unsigned char *, int); |
429 | extern int E_md4hash(const unsigned char *passwd, unsigned char *p16); | 434 | extern int E_md4hash(const unsigned char *passwd, unsigned char *p16); |
430 | extern void SMBencrypt(unsigned char *passwd, const unsigned char *c8, | 435 | extern int SMBencrypt(unsigned char *passwd, const unsigned char *c8, |
431 | unsigned char *p24); | ||
432 | extern void E_P16(unsigned char *p14, unsigned char *p16); | ||
433 | extern void E_P24(unsigned char *p21, const unsigned char *c8, | ||
434 | unsigned char *p24); | 436 | unsigned char *p24); |
435 | #endif /* _CIFSPROTO_H */ | 437 | #endif /* _CIFSPROTO_H */ |
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index df959bae6728..83df937b814e 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
@@ -339,12 +339,13 @@ static int validate_t2(struct smb_t2_rsp *pSMB) | |||
339 | get_unaligned_le16(&pSMB->t2_rsp.DataOffset) > 1024) | 339 | get_unaligned_le16(&pSMB->t2_rsp.DataOffset) > 1024) |
340 | goto vt2_err; | 340 | goto vt2_err; |
341 | 341 | ||
342 | /* check that bcc is at least as big as parms + data */ | ||
343 | /* check that bcc is less than negotiated smb buffer */ | ||
344 | total_size = get_unaligned_le16(&pSMB->t2_rsp.ParameterCount); | 342 | total_size = get_unaligned_le16(&pSMB->t2_rsp.ParameterCount); |
345 | if (total_size >= 512) | 343 | if (total_size >= 512) |
346 | goto vt2_err; | 344 | goto vt2_err; |
347 | 345 | ||
346 | /* check that bcc is at least as big as parms + data, and that it is | ||
347 | * less than negotiated smb buffer | ||
348 | */ | ||
348 | total_size += get_unaligned_le16(&pSMB->t2_rsp.DataCount); | 349 | total_size += get_unaligned_le16(&pSMB->t2_rsp.DataCount); |
349 | if (total_size > get_bcc(&pSMB->hdr) || | 350 | if (total_size > get_bcc(&pSMB->hdr) || |
350 | total_size >= CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) | 351 | total_size >= CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) |
@@ -357,6 +358,13 @@ vt2_err: | |||
357 | return -EINVAL; | 358 | return -EINVAL; |
358 | } | 359 | } |
359 | 360 | ||
361 | static inline void inc_rfc1001_len(void *pSMB, int count) | ||
362 | { | ||
363 | struct smb_hdr *hdr = (struct smb_hdr *)pSMB; | ||
364 | |||
365 | be32_add_cpu(&hdr->smb_buf_length, count); | ||
366 | } | ||
367 | |||
360 | int | 368 | int |
361 | CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) | 369 | CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) |
362 | { | 370 | { |
@@ -409,7 +417,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) | |||
409 | count += strlen(protocols[i].name) + 1; | 417 | count += strlen(protocols[i].name) + 1; |
410 | /* null at end of source and target buffers anyway */ | 418 | /* null at end of source and target buffers anyway */ |
411 | } | 419 | } |
412 | pSMB->hdr.smb_buf_length += count; | 420 | inc_rfc1001_len(pSMB, count); |
413 | pSMB->ByteCount = cpu_to_le16(count); | 421 | pSMB->ByteCount = cpu_to_le16(count); |
414 | 422 | ||
415 | rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB, | 423 | rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB, |
@@ -541,10 +549,6 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) | |||
541 | server->secType = RawNTLMSSP; | 549 | server->secType = RawNTLMSSP; |
542 | else if (secFlags & CIFSSEC_MAY_LANMAN) | 550 | else if (secFlags & CIFSSEC_MAY_LANMAN) |
543 | server->secType = LANMAN; | 551 | server->secType = LANMAN; |
544 | /* #ifdef CONFIG_CIFS_EXPERIMENTAL | ||
545 | else if (secFlags & CIFSSEC_MAY_PLNTXT) | ||
546 | server->secType = ?? | ||
547 | #endif */ | ||
548 | else { | 552 | else { |
549 | rc = -EOPNOTSUPP; | 553 | rc = -EOPNOTSUPP; |
550 | cERROR(1, "Invalid security type"); | 554 | cERROR(1, "Invalid security type"); |
@@ -578,7 +582,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) | |||
578 | 582 | ||
579 | if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) && | 583 | if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) && |
580 | (server->capabilities & CAP_EXTENDED_SECURITY)) { | 584 | (server->capabilities & CAP_EXTENDED_SECURITY)) { |
581 | count = pSMBr->ByteCount; | 585 | count = get_bcc(&pSMBr->hdr); |
582 | if (count < 16) { | 586 | if (count < 16) { |
583 | rc = -EIO; | 587 | rc = -EIO; |
584 | goto neg_err_exit; | 588 | goto neg_err_exit; |
@@ -732,9 +736,9 @@ CIFSSMBEcho(struct TCP_Server_Info *server) | |||
732 | smb->hdr.Tid = 0xffff; | 736 | smb->hdr.Tid = 0xffff; |
733 | smb->hdr.WordCount = 1; | 737 | smb->hdr.WordCount = 1; |
734 | put_unaligned_le16(1, &smb->EchoCount); | 738 | put_unaligned_le16(1, &smb->EchoCount); |
735 | put_bcc_le(1, &smb->hdr); | 739 | put_bcc(1, &smb->hdr); |
736 | smb->Data[0] = 'a'; | 740 | smb->Data[0] = 'a'; |
737 | smb->hdr.smb_buf_length += 3; | 741 | inc_rfc1001_len(smb, 3); |
738 | 742 | ||
739 | rc = cifs_call_async(server, (struct smb_hdr *)smb, | 743 | rc = cifs_call_async(server, (struct smb_hdr *)smb, |
740 | cifs_echo_callback, server); | 744 | cifs_echo_callback, server); |
@@ -852,7 +856,7 @@ PsxDelete: | |||
852 | pSMB->TotalParameterCount = pSMB->ParameterCount; | 856 | pSMB->TotalParameterCount = pSMB->ParameterCount; |
853 | pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK); | 857 | pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK); |
854 | pSMB->Reserved4 = 0; | 858 | pSMB->Reserved4 = 0; |
855 | pSMB->hdr.smb_buf_length += byte_count; | 859 | inc_rfc1001_len(pSMB, byte_count); |
856 | pSMB->ByteCount = cpu_to_le16(byte_count); | 860 | pSMB->ByteCount = cpu_to_le16(byte_count); |
857 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 861 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
858 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 862 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
@@ -898,7 +902,7 @@ DelFileRetry: | |||
898 | pSMB->SearchAttributes = | 902 | pSMB->SearchAttributes = |
899 | cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM); | 903 | cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM); |
900 | pSMB->BufferFormat = 0x04; | 904 | pSMB->BufferFormat = 0x04; |
901 | pSMB->hdr.smb_buf_length += name_len + 1; | 905 | inc_rfc1001_len(pSMB, name_len + 1); |
902 | pSMB->ByteCount = cpu_to_le16(name_len + 1); | 906 | pSMB->ByteCount = cpu_to_le16(name_len + 1); |
903 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 907 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
904 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 908 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
@@ -942,7 +946,7 @@ RmDirRetry: | |||
942 | } | 946 | } |
943 | 947 | ||
944 | pSMB->BufferFormat = 0x04; | 948 | pSMB->BufferFormat = 0x04; |
945 | pSMB->hdr.smb_buf_length += name_len + 1; | 949 | inc_rfc1001_len(pSMB, name_len + 1); |
946 | pSMB->ByteCount = cpu_to_le16(name_len + 1); | 950 | pSMB->ByteCount = cpu_to_le16(name_len + 1); |
947 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 951 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
948 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 952 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
@@ -985,7 +989,7 @@ MkDirRetry: | |||
985 | } | 989 | } |
986 | 990 | ||
987 | pSMB->BufferFormat = 0x04; | 991 | pSMB->BufferFormat = 0x04; |
988 | pSMB->hdr.smb_buf_length += name_len + 1; | 992 | inc_rfc1001_len(pSMB, name_len + 1); |
989 | pSMB->ByteCount = cpu_to_le16(name_len + 1); | 993 | pSMB->ByteCount = cpu_to_le16(name_len + 1); |
990 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 994 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
991 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 995 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
@@ -1063,7 +1067,7 @@ PsxCreat: | |||
1063 | pSMB->TotalParameterCount = pSMB->ParameterCount; | 1067 | pSMB->TotalParameterCount = pSMB->ParameterCount; |
1064 | pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN); | 1068 | pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN); |
1065 | pSMB->Reserved4 = 0; | 1069 | pSMB->Reserved4 = 0; |
1066 | pSMB->hdr.smb_buf_length += byte_count; | 1070 | inc_rfc1001_len(pSMB, byte_count); |
1067 | pSMB->ByteCount = cpu_to_le16(byte_count); | 1071 | pSMB->ByteCount = cpu_to_le16(byte_count); |
1068 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 1072 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
1069 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 1073 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
@@ -1075,7 +1079,7 @@ PsxCreat: | |||
1075 | cFYI(1, "copying inode info"); | 1079 | cFYI(1, "copying inode info"); |
1076 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 1080 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
1077 | 1081 | ||
1078 | if (rc || (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP))) { | 1082 | if (rc || get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP)) { |
1079 | rc = -EIO; /* bad smb */ | 1083 | rc = -EIO; /* bad smb */ |
1080 | goto psx_create_err; | 1084 | goto psx_create_err; |
1081 | } | 1085 | } |
@@ -1096,7 +1100,7 @@ PsxCreat: | |||
1096 | pRetData->Type = cpu_to_le32(-1); /* unknown */ | 1100 | pRetData->Type = cpu_to_le32(-1); /* unknown */ |
1097 | cFYI(DBG2, "unknown type"); | 1101 | cFYI(DBG2, "unknown type"); |
1098 | } else { | 1102 | } else { |
1099 | if (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP) | 1103 | if (get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP) |
1100 | + sizeof(FILE_UNIX_BASIC_INFO)) { | 1104 | + sizeof(FILE_UNIX_BASIC_INFO)) { |
1101 | cERROR(1, "Open response data too small"); | 1105 | cERROR(1, "Open response data too small"); |
1102 | pRetData->Type = cpu_to_le32(-1); | 1106 | pRetData->Type = cpu_to_le32(-1); |
@@ -1228,7 +1232,7 @@ OldOpenRetry: | |||
1228 | pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY); | 1232 | pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY); |
1229 | pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition)); | 1233 | pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition)); |
1230 | count += name_len; | 1234 | count += name_len; |
1231 | pSMB->hdr.smb_buf_length += count; | 1235 | inc_rfc1001_len(pSMB, count); |
1232 | 1236 | ||
1233 | pSMB->ByteCount = cpu_to_le16(count); | 1237 | pSMB->ByteCount = cpu_to_le16(count); |
1234 | /* long_op set to 1 to allow for oplock break timeouts */ | 1238 | /* long_op set to 1 to allow for oplock break timeouts */ |
@@ -1341,7 +1345,7 @@ openRetry: | |||
1341 | SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY; | 1345 | SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY; |
1342 | 1346 | ||
1343 | count += name_len; | 1347 | count += name_len; |
1344 | pSMB->hdr.smb_buf_length += count; | 1348 | inc_rfc1001_len(pSMB, count); |
1345 | 1349 | ||
1346 | pSMB->ByteCount = cpu_to_le16(count); | 1350 | pSMB->ByteCount = cpu_to_le16(count); |
1347 | /* long_op set to 1 to allow for oplock break timeouts */ | 1351 | /* long_op set to 1 to allow for oplock break timeouts */ |
@@ -1426,7 +1430,7 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid, | |||
1426 | } | 1430 | } |
1427 | 1431 | ||
1428 | iov[0].iov_base = (char *)pSMB; | 1432 | iov[0].iov_base = (char *)pSMB; |
1429 | iov[0].iov_len = pSMB->hdr.smb_buf_length + 4; | 1433 | iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4; |
1430 | rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */, | 1434 | rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */, |
1431 | &resp_buf_type, CIFS_LOG_ERROR); | 1435 | &resp_buf_type, CIFS_LOG_ERROR); |
1432 | cifs_stats_inc(&tcon->num_reads); | 1436 | cifs_stats_inc(&tcon->num_reads); |
@@ -1560,7 +1564,7 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon, | |||
1560 | 1564 | ||
1561 | pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF); | 1565 | pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF); |
1562 | pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16); | 1566 | pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16); |
1563 | pSMB->hdr.smb_buf_length += byte_count; | 1567 | inc_rfc1001_len(pSMB, byte_count); |
1564 | 1568 | ||
1565 | if (wct == 14) | 1569 | if (wct == 14) |
1566 | pSMB->ByteCount = cpu_to_le16(byte_count); | 1570 | pSMB->ByteCount = cpu_to_le16(byte_count); |
@@ -1644,11 +1648,12 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon, | |||
1644 | 1648 | ||
1645 | pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF); | 1649 | pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF); |
1646 | pSMB->DataLengthHigh = cpu_to_le16(count >> 16); | 1650 | pSMB->DataLengthHigh = cpu_to_le16(count >> 16); |
1647 | smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */ | 1651 | /* header + 1 byte pad */ |
1652 | smb_hdr_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 1; | ||
1648 | if (wct == 14) | 1653 | if (wct == 14) |
1649 | pSMB->hdr.smb_buf_length += count+1; | 1654 | inc_rfc1001_len(pSMB, count + 1); |
1650 | else /* wct == 12 */ | 1655 | else /* wct == 12 */ |
1651 | pSMB->hdr.smb_buf_length += count+5; /* smb data starts later */ | 1656 | inc_rfc1001_len(pSMB, count + 5); /* smb data starts later */ |
1652 | if (wct == 14) | 1657 | if (wct == 14) |
1653 | pSMB->ByteCount = cpu_to_le16(count + 1); | 1658 | pSMB->ByteCount = cpu_to_le16(count + 1); |
1654 | else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ { | 1659 | else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ { |
@@ -1748,7 +1753,7 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, | |||
1748 | /* oplock break */ | 1753 | /* oplock break */ |
1749 | count = 0; | 1754 | count = 0; |
1750 | } | 1755 | } |
1751 | pSMB->hdr.smb_buf_length += count; | 1756 | inc_rfc1001_len(pSMB, count); |
1752 | pSMB->ByteCount = cpu_to_le16(count); | 1757 | pSMB->ByteCount = cpu_to_le16(count); |
1753 | 1758 | ||
1754 | if (waitFlag) { | 1759 | if (waitFlag) { |
@@ -1839,14 +1844,14 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon, | |||
1839 | pSMB->Fid = smb_file_id; | 1844 | pSMB->Fid = smb_file_id; |
1840 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK); | 1845 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK); |
1841 | pSMB->Reserved4 = 0; | 1846 | pSMB->Reserved4 = 0; |
1842 | pSMB->hdr.smb_buf_length += byte_count; | 1847 | inc_rfc1001_len(pSMB, byte_count); |
1843 | pSMB->ByteCount = cpu_to_le16(byte_count); | 1848 | pSMB->ByteCount = cpu_to_le16(byte_count); |
1844 | if (waitFlag) { | 1849 | if (waitFlag) { |
1845 | rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB, | 1850 | rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB, |
1846 | (struct smb_hdr *) pSMBr, &bytes_returned); | 1851 | (struct smb_hdr *) pSMBr, &bytes_returned); |
1847 | } else { | 1852 | } else { |
1848 | iov[0].iov_base = (char *)pSMB; | 1853 | iov[0].iov_base = (char *)pSMB; |
1849 | iov[0].iov_len = pSMB->hdr.smb_buf_length + 4; | 1854 | iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4; |
1850 | rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */, | 1855 | rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */, |
1851 | &resp_buf_type, timeout); | 1856 | &resp_buf_type, timeout); |
1852 | pSMB = NULL; /* request buf already freed by SendReceive2. Do | 1857 | pSMB = NULL; /* request buf already freed by SendReceive2. Do |
@@ -1862,7 +1867,7 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon, | |||
1862 | __u16 data_count; | 1867 | __u16 data_count; |
1863 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 1868 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
1864 | 1869 | ||
1865 | if (rc || (pSMBr->ByteCount < sizeof(struct cifs_posix_lock))) { | 1870 | if (rc || get_bcc(&pSMBr->hdr) < sizeof(*parm_data)) { |
1866 | rc = -EIO; /* bad smb */ | 1871 | rc = -EIO; /* bad smb */ |
1867 | goto plk_err_exit; | 1872 | goto plk_err_exit; |
1868 | } | 1873 | } |
@@ -2012,7 +2017,7 @@ renameRetry: | |||
2012 | } | 2017 | } |
2013 | 2018 | ||
2014 | count = 1 /* 1st signature byte */ + name_len + name_len2; | 2019 | count = 1 /* 1st signature byte */ + name_len + name_len2; |
2015 | pSMB->hdr.smb_buf_length += count; | 2020 | inc_rfc1001_len(pSMB, count); |
2016 | pSMB->ByteCount = cpu_to_le16(count); | 2021 | pSMB->ByteCount = cpu_to_le16(count); |
2017 | 2022 | ||
2018 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 2023 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
@@ -2092,7 +2097,7 @@ int CIFSSMBRenameOpenFile(const int xid, struct cifsTconInfo *pTcon, | |||
2092 | pSMB->InformationLevel = | 2097 | pSMB->InformationLevel = |
2093 | cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION); | 2098 | cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION); |
2094 | pSMB->Reserved4 = 0; | 2099 | pSMB->Reserved4 = 0; |
2095 | pSMB->hdr.smb_buf_length += byte_count; | 2100 | inc_rfc1001_len(pSMB, byte_count); |
2096 | pSMB->ByteCount = cpu_to_le16(byte_count); | 2101 | pSMB->ByteCount = cpu_to_le16(byte_count); |
2097 | rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB, | 2102 | rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB, |
2098 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 2103 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
@@ -2159,7 +2164,7 @@ copyRetry: | |||
2159 | } | 2164 | } |
2160 | 2165 | ||
2161 | count = 1 /* 1st signature byte */ + name_len + name_len2; | 2166 | count = 1 /* 1st signature byte */ + name_len + name_len2; |
2162 | pSMB->hdr.smb_buf_length += count; | 2167 | inc_rfc1001_len(pSMB, count); |
2163 | pSMB->ByteCount = cpu_to_le16(count); | 2168 | pSMB->ByteCount = cpu_to_le16(count); |
2164 | 2169 | ||
2165 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 2170 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
@@ -2249,7 +2254,7 @@ createSymLinkRetry: | |||
2249 | pSMB->DataOffset = cpu_to_le16(offset); | 2254 | pSMB->DataOffset = cpu_to_le16(offset); |
2250 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK); | 2255 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK); |
2251 | pSMB->Reserved4 = 0; | 2256 | pSMB->Reserved4 = 0; |
2252 | pSMB->hdr.smb_buf_length += byte_count; | 2257 | inc_rfc1001_len(pSMB, byte_count); |
2253 | pSMB->ByteCount = cpu_to_le16(byte_count); | 2258 | pSMB->ByteCount = cpu_to_le16(byte_count); |
2254 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 2259 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
2255 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 2260 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
@@ -2335,7 +2340,7 @@ createHardLinkRetry: | |||
2335 | pSMB->DataOffset = cpu_to_le16(offset); | 2340 | pSMB->DataOffset = cpu_to_le16(offset); |
2336 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK); | 2341 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK); |
2337 | pSMB->Reserved4 = 0; | 2342 | pSMB->Reserved4 = 0; |
2338 | pSMB->hdr.smb_buf_length += byte_count; | 2343 | inc_rfc1001_len(pSMB, byte_count); |
2339 | pSMB->ByteCount = cpu_to_le16(byte_count); | 2344 | pSMB->ByteCount = cpu_to_le16(byte_count); |
2340 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 2345 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
2341 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 2346 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
@@ -2406,7 +2411,7 @@ winCreateHardLinkRetry: | |||
2406 | } | 2411 | } |
2407 | 2412 | ||
2408 | count = 1 /* string type byte */ + name_len + name_len2; | 2413 | count = 1 /* string type byte */ + name_len + name_len2; |
2409 | pSMB->hdr.smb_buf_length += count; | 2414 | inc_rfc1001_len(pSMB, count); |
2410 | pSMB->ByteCount = cpu_to_le16(count); | 2415 | pSMB->ByteCount = cpu_to_le16(count); |
2411 | 2416 | ||
2412 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 2417 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
@@ -2477,7 +2482,7 @@ querySymLinkRetry: | |||
2477 | pSMB->ParameterCount = pSMB->TotalParameterCount; | 2482 | pSMB->ParameterCount = pSMB->TotalParameterCount; |
2478 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK); | 2483 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK); |
2479 | pSMB->Reserved4 = 0; | 2484 | pSMB->Reserved4 = 0; |
2480 | pSMB->hdr.smb_buf_length += byte_count; | 2485 | inc_rfc1001_len(pSMB, byte_count); |
2481 | pSMB->ByteCount = cpu_to_le16(byte_count); | 2486 | pSMB->ByteCount = cpu_to_le16(byte_count); |
2482 | 2487 | ||
2483 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 2488 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
@@ -2489,7 +2494,7 @@ querySymLinkRetry: | |||
2489 | 2494 | ||
2490 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 2495 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
2491 | /* BB also check enough total bytes returned */ | 2496 | /* BB also check enough total bytes returned */ |
2492 | if (rc || (pSMBr->ByteCount < 2)) | 2497 | if (rc || get_bcc(&pSMBr->hdr) < 2) |
2493 | rc = -EIO; | 2498 | rc = -EIO; |
2494 | else { | 2499 | else { |
2495 | bool is_unicode; | 2500 | bool is_unicode; |
@@ -2516,7 +2521,17 @@ querySymLinkRetry: | |||
2516 | return rc; | 2521 | return rc; |
2517 | } | 2522 | } |
2518 | 2523 | ||
2519 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 2524 | #ifdef CONFIG_CIFS_SYMLINK_EXPERIMENTAL |
2525 | /* | ||
2526 | * Recent Windows versions now create symlinks more frequently | ||
2527 | * and they use the "reparse point" mechanism below. We can of course | ||
2528 | * do symlinks nicely to Samba and other servers which support the | ||
2529 | * CIFS Unix Extensions and we can also do SFU symlinks and "client only" | ||
2530 | * "MF" symlinks optionally, but for recent Windows we really need to | ||
2531 | * reenable the code below and fix the cifs_symlink callers to handle this. | ||
2532 | * In the interim this code has been moved to its own config option so | ||
2533 | * it is not compiled in by default until callers fixed up and more tested. | ||
2534 | */ | ||
2520 | int | 2535 | int |
2521 | CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon, | 2536 | CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon, |
2522 | const unsigned char *searchName, | 2537 | const unsigned char *searchName, |
@@ -2561,14 +2576,14 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon, | |||
2561 | } else { /* decode response */ | 2576 | } else { /* decode response */ |
2562 | __u32 data_offset = le32_to_cpu(pSMBr->DataOffset); | 2577 | __u32 data_offset = le32_to_cpu(pSMBr->DataOffset); |
2563 | __u32 data_count = le32_to_cpu(pSMBr->DataCount); | 2578 | __u32 data_count = le32_to_cpu(pSMBr->DataCount); |
2564 | if ((pSMBr->ByteCount < 2) || (data_offset > 512)) { | 2579 | if (get_bcc(&pSMBr->hdr) < 2 || data_offset > 512) { |
2565 | /* BB also check enough total bytes returned */ | 2580 | /* BB also check enough total bytes returned */ |
2566 | rc = -EIO; /* bad smb */ | 2581 | rc = -EIO; /* bad smb */ |
2567 | goto qreparse_out; | 2582 | goto qreparse_out; |
2568 | } | 2583 | } |
2569 | if (data_count && (data_count < 2048)) { | 2584 | if (data_count && (data_count < 2048)) { |
2570 | char *end_of_smb = 2 /* sizeof byte count */ + | 2585 | char *end_of_smb = 2 /* sizeof byte count */ + |
2571 | pSMBr->ByteCount + (char *)&pSMBr->ByteCount; | 2586 | get_bcc(&pSMBr->hdr) + (char *)&pSMBr->ByteCount; |
2572 | 2587 | ||
2573 | struct reparse_data *reparse_buf = | 2588 | struct reparse_data *reparse_buf = |
2574 | (struct reparse_data *) | 2589 | (struct reparse_data *) |
@@ -2618,7 +2633,7 @@ qreparse_out: | |||
2618 | 2633 | ||
2619 | return rc; | 2634 | return rc; |
2620 | } | 2635 | } |
2621 | #endif /* CIFS_EXPERIMENTAL */ | 2636 | #endif /* CIFS_SYMLINK_EXPERIMENTAL */ /* BB temporarily unused */ |
2622 | 2637 | ||
2623 | #ifdef CONFIG_CIFS_POSIX | 2638 | #ifdef CONFIG_CIFS_POSIX |
2624 | 2639 | ||
@@ -2814,7 +2829,7 @@ queryAclRetry: | |||
2814 | pSMB->ParameterCount = pSMB->TotalParameterCount; | 2829 | pSMB->ParameterCount = pSMB->TotalParameterCount; |
2815 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL); | 2830 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL); |
2816 | pSMB->Reserved4 = 0; | 2831 | pSMB->Reserved4 = 0; |
2817 | pSMB->hdr.smb_buf_length += byte_count; | 2832 | inc_rfc1001_len(pSMB, byte_count); |
2818 | pSMB->ByteCount = cpu_to_le16(byte_count); | 2833 | pSMB->ByteCount = cpu_to_le16(byte_count); |
2819 | 2834 | ||
2820 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 2835 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
@@ -2826,8 +2841,8 @@ queryAclRetry: | |||
2826 | /* decode response */ | 2841 | /* decode response */ |
2827 | 2842 | ||
2828 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 2843 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
2829 | if (rc || (pSMBr->ByteCount < 2)) | ||
2830 | /* BB also check enough total bytes returned */ | 2844 | /* BB also check enough total bytes returned */ |
2845 | if (rc || get_bcc(&pSMBr->hdr) < 2) | ||
2831 | rc = -EIO; /* bad smb */ | 2846 | rc = -EIO; /* bad smb */ |
2832 | else { | 2847 | else { |
2833 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); | 2848 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); |
@@ -2908,7 +2923,7 @@ setAclRetry: | |||
2908 | pSMB->ParameterCount = cpu_to_le16(params); | 2923 | pSMB->ParameterCount = cpu_to_le16(params); |
2909 | pSMB->TotalParameterCount = pSMB->ParameterCount; | 2924 | pSMB->TotalParameterCount = pSMB->ParameterCount; |
2910 | pSMB->Reserved4 = 0; | 2925 | pSMB->Reserved4 = 0; |
2911 | pSMB->hdr.smb_buf_length += byte_count; | 2926 | inc_rfc1001_len(pSMB, byte_count); |
2912 | pSMB->ByteCount = cpu_to_le16(byte_count); | 2927 | pSMB->ByteCount = cpu_to_le16(byte_count); |
2913 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 2928 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
2914 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 2929 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
@@ -2966,7 +2981,7 @@ GetExtAttrRetry: | |||
2966 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS); | 2981 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS); |
2967 | pSMB->Pad = 0; | 2982 | pSMB->Pad = 0; |
2968 | pSMB->Fid = netfid; | 2983 | pSMB->Fid = netfid; |
2969 | pSMB->hdr.smb_buf_length += byte_count; | 2984 | inc_rfc1001_len(pSMB, byte_count); |
2970 | pSMB->t2.ByteCount = cpu_to_le16(byte_count); | 2985 | pSMB->t2.ByteCount = cpu_to_le16(byte_count); |
2971 | 2986 | ||
2972 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 2987 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
@@ -2976,8 +2991,8 @@ GetExtAttrRetry: | |||
2976 | } else { | 2991 | } else { |
2977 | /* decode response */ | 2992 | /* decode response */ |
2978 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 2993 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
2979 | if (rc || (pSMBr->ByteCount < 2)) | ||
2980 | /* BB also check enough total bytes returned */ | 2994 | /* BB also check enough total bytes returned */ |
2995 | if (rc || get_bcc(&pSMBr->hdr) < 2) | ||
2981 | /* If rc should we check for EOPNOSUPP and | 2996 | /* If rc should we check for EOPNOSUPP and |
2982 | disable the srvino flag? or in caller? */ | 2997 | disable the srvino flag? or in caller? */ |
2983 | rc = -EIO; /* bad smb */ | 2998 | rc = -EIO; /* bad smb */ |
@@ -3052,6 +3067,7 @@ validate_ntransact(char *buf, char **ppparm, char **ppdata, | |||
3052 | char *end_of_smb; | 3067 | char *end_of_smb; |
3053 | __u32 data_count, data_offset, parm_count, parm_offset; | 3068 | __u32 data_count, data_offset, parm_count, parm_offset; |
3054 | struct smb_com_ntransact_rsp *pSMBr; | 3069 | struct smb_com_ntransact_rsp *pSMBr; |
3070 | u16 bcc; | ||
3055 | 3071 | ||
3056 | *pdatalen = 0; | 3072 | *pdatalen = 0; |
3057 | *pparmlen = 0; | 3073 | *pparmlen = 0; |
@@ -3061,8 +3077,8 @@ validate_ntransact(char *buf, char **ppparm, char **ppdata, | |||
3061 | 3077 | ||
3062 | pSMBr = (struct smb_com_ntransact_rsp *)buf; | 3078 | pSMBr = (struct smb_com_ntransact_rsp *)buf; |
3063 | 3079 | ||
3064 | /* ByteCount was converted from little endian in SendReceive */ | 3080 | bcc = get_bcc(&pSMBr->hdr); |
3065 | end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount + | 3081 | end_of_smb = 2 /* sizeof byte count */ + bcc + |
3066 | (char *)&pSMBr->ByteCount; | 3082 | (char *)&pSMBr->ByteCount; |
3067 | 3083 | ||
3068 | data_offset = le32_to_cpu(pSMBr->DataOffset); | 3084 | data_offset = le32_to_cpu(pSMBr->DataOffset); |
@@ -3088,7 +3104,7 @@ validate_ntransact(char *buf, char **ppparm, char **ppdata, | |||
3088 | *ppdata, data_count, (data_count + *ppdata), | 3104 | *ppdata, data_count, (data_count + *ppdata), |
3089 | end_of_smb, pSMBr); | 3105 | end_of_smb, pSMBr); |
3090 | return -EINVAL; | 3106 | return -EINVAL; |
3091 | } else if (parm_count + data_count > pSMBr->ByteCount) { | 3107 | } else if (parm_count + data_count > bcc) { |
3092 | cFYI(1, "parm count and data count larger than SMB"); | 3108 | cFYI(1, "parm count and data count larger than SMB"); |
3093 | return -EINVAL; | 3109 | return -EINVAL; |
3094 | } | 3110 | } |
@@ -3124,9 +3140,9 @@ CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid, | |||
3124 | pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP | | 3140 | pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP | |
3125 | CIFS_ACL_DACL); | 3141 | CIFS_ACL_DACL); |
3126 | pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */ | 3142 | pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */ |
3127 | pSMB->hdr.smb_buf_length += 11; | 3143 | inc_rfc1001_len(pSMB, 11); |
3128 | iov[0].iov_base = (char *)pSMB; | 3144 | iov[0].iov_base = (char *)pSMB; |
3129 | iov[0].iov_len = pSMB->hdr.smb_buf_length + 4; | 3145 | iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4; |
3130 | 3146 | ||
3131 | rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type, | 3147 | rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type, |
3132 | 0); | 3148 | 0); |
@@ -3235,10 +3251,9 @@ setCifsAclRetry: | |||
3235 | memcpy((char *) &pSMBr->hdr.Protocol + data_offset, | 3251 | memcpy((char *) &pSMBr->hdr.Protocol + data_offset, |
3236 | (char *) pntsd, | 3252 | (char *) pntsd, |
3237 | acllen); | 3253 | acllen); |
3238 | pSMB->hdr.smb_buf_length += (byte_count + data_count); | 3254 | inc_rfc1001_len(pSMB, byte_count + data_count); |
3239 | |||
3240 | } else | 3255 | } else |
3241 | pSMB->hdr.smb_buf_length += byte_count; | 3256 | inc_rfc1001_len(pSMB, byte_count); |
3242 | 3257 | ||
3243 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 3258 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
3244 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 3259 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
@@ -3289,7 +3304,7 @@ QInfRetry: | |||
3289 | } | 3304 | } |
3290 | pSMB->BufferFormat = 0x04; | 3305 | pSMB->BufferFormat = 0x04; |
3291 | name_len++; /* account for buffer type byte */ | 3306 | name_len++; /* account for buffer type byte */ |
3292 | pSMB->hdr.smb_buf_length += (__u16) name_len; | 3307 | inc_rfc1001_len(pSMB, (__u16)name_len); |
3293 | pSMB->ByteCount = cpu_to_le16(name_len); | 3308 | pSMB->ByteCount = cpu_to_le16(name_len); |
3294 | 3309 | ||
3295 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 3310 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
@@ -3364,7 +3379,7 @@ QFileInfoRetry: | |||
3364 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO); | 3379 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO); |
3365 | pSMB->Pad = 0; | 3380 | pSMB->Pad = 0; |
3366 | pSMB->Fid = netfid; | 3381 | pSMB->Fid = netfid; |
3367 | pSMB->hdr.smb_buf_length += byte_count; | 3382 | inc_rfc1001_len(pSMB, byte_count); |
3368 | 3383 | ||
3369 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 3384 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
3370 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 3385 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
@@ -3375,7 +3390,7 @@ QFileInfoRetry: | |||
3375 | 3390 | ||
3376 | if (rc) /* BB add auto retry on EOPNOTSUPP? */ | 3391 | if (rc) /* BB add auto retry on EOPNOTSUPP? */ |
3377 | rc = -EIO; | 3392 | rc = -EIO; |
3378 | else if (pSMBr->ByteCount < 40) | 3393 | else if (get_bcc(&pSMBr->hdr) < 40) |
3379 | rc = -EIO; /* bad smb */ | 3394 | rc = -EIO; /* bad smb */ |
3380 | else if (pFindData) { | 3395 | else if (pFindData) { |
3381 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); | 3396 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); |
@@ -3451,7 +3466,7 @@ QPathInfoRetry: | |||
3451 | else | 3466 | else |
3452 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO); | 3467 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO); |
3453 | pSMB->Reserved4 = 0; | 3468 | pSMB->Reserved4 = 0; |
3454 | pSMB->hdr.smb_buf_length += byte_count; | 3469 | inc_rfc1001_len(pSMB, byte_count); |
3455 | pSMB->ByteCount = cpu_to_le16(byte_count); | 3470 | pSMB->ByteCount = cpu_to_le16(byte_count); |
3456 | 3471 | ||
3457 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 3472 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
@@ -3463,9 +3478,9 @@ QPathInfoRetry: | |||
3463 | 3478 | ||
3464 | if (rc) /* BB add auto retry on EOPNOTSUPP? */ | 3479 | if (rc) /* BB add auto retry on EOPNOTSUPP? */ |
3465 | rc = -EIO; | 3480 | rc = -EIO; |
3466 | else if (!legacy && (pSMBr->ByteCount < 40)) | 3481 | else if (!legacy && get_bcc(&pSMBr->hdr) < 40) |
3467 | rc = -EIO; /* bad smb */ | 3482 | rc = -EIO; /* bad smb */ |
3468 | else if (legacy && (pSMBr->ByteCount < 24)) | 3483 | else if (legacy && get_bcc(&pSMBr->hdr) < 24) |
3469 | rc = -EIO; /* 24 or 26 expected but we do not read | 3484 | rc = -EIO; /* 24 or 26 expected but we do not read |
3470 | last field */ | 3485 | last field */ |
3471 | else if (pFindData) { | 3486 | else if (pFindData) { |
@@ -3532,7 +3547,7 @@ UnixQFileInfoRetry: | |||
3532 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC); | 3547 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC); |
3533 | pSMB->Pad = 0; | 3548 | pSMB->Pad = 0; |
3534 | pSMB->Fid = netfid; | 3549 | pSMB->Fid = netfid; |
3535 | pSMB->hdr.smb_buf_length += byte_count; | 3550 | inc_rfc1001_len(pSMB, byte_count); |
3536 | 3551 | ||
3537 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 3552 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
3538 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 3553 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
@@ -3541,7 +3556,7 @@ UnixQFileInfoRetry: | |||
3541 | } else { /* decode response */ | 3556 | } else { /* decode response */ |
3542 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 3557 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
3543 | 3558 | ||
3544 | if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) { | 3559 | if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) { |
3545 | cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response.\n" | 3560 | cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response.\n" |
3546 | "Unix Extensions can be disabled on mount " | 3561 | "Unix Extensions can be disabled on mount " |
3547 | "by specifying the nosfu mount option."); | 3562 | "by specifying the nosfu mount option."); |
@@ -3617,7 +3632,7 @@ UnixQPathInfoRetry: | |||
3617 | pSMB->ParameterCount = pSMB->TotalParameterCount; | 3632 | pSMB->ParameterCount = pSMB->TotalParameterCount; |
3618 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC); | 3633 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC); |
3619 | pSMB->Reserved4 = 0; | 3634 | pSMB->Reserved4 = 0; |
3620 | pSMB->hdr.smb_buf_length += byte_count; | 3635 | inc_rfc1001_len(pSMB, byte_count); |
3621 | pSMB->ByteCount = cpu_to_le16(byte_count); | 3636 | pSMB->ByteCount = cpu_to_le16(byte_count); |
3622 | 3637 | ||
3623 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 3638 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
@@ -3627,7 +3642,7 @@ UnixQPathInfoRetry: | |||
3627 | } else { /* decode response */ | 3642 | } else { /* decode response */ |
3628 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 3643 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
3629 | 3644 | ||
3630 | if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) { | 3645 | if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) { |
3631 | cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response.\n" | 3646 | cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response.\n" |
3632 | "Unix Extensions can be disabled on mount " | 3647 | "Unix Extensions can be disabled on mount " |
3633 | "by specifying the nosfu mount option."); | 3648 | "by specifying the nosfu mount option."); |
@@ -3731,7 +3746,7 @@ findFirstRetry: | |||
3731 | 3746 | ||
3732 | /* BB what should we set StorageType to? Does it matter? BB */ | 3747 | /* BB what should we set StorageType to? Does it matter? BB */ |
3733 | pSMB->SearchStorageType = 0; | 3748 | pSMB->SearchStorageType = 0; |
3734 | pSMB->hdr.smb_buf_length += byte_count; | 3749 | inc_rfc1001_len(pSMB, byte_count); |
3735 | pSMB->ByteCount = cpu_to_le16(byte_count); | 3750 | pSMB->ByteCount = cpu_to_le16(byte_count); |
3736 | 3751 | ||
3737 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 3752 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
@@ -3860,7 +3875,7 @@ int CIFSFindNext(const int xid, struct cifsTconInfo *tcon, | |||
3860 | byte_count = params + 1 /* pad */ ; | 3875 | byte_count = params + 1 /* pad */ ; |
3861 | pSMB->TotalParameterCount = cpu_to_le16(params); | 3876 | pSMB->TotalParameterCount = cpu_to_le16(params); |
3862 | pSMB->ParameterCount = pSMB->TotalParameterCount; | 3877 | pSMB->ParameterCount = pSMB->TotalParameterCount; |
3863 | pSMB->hdr.smb_buf_length += byte_count; | 3878 | inc_rfc1001_len(pSMB, byte_count); |
3864 | pSMB->ByteCount = cpu_to_le16(byte_count); | 3879 | pSMB->ByteCount = cpu_to_le16(byte_count); |
3865 | 3880 | ||
3866 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 3881 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
@@ -4022,7 +4037,7 @@ GetInodeNumberRetry: | |||
4022 | pSMB->ParameterCount = pSMB->TotalParameterCount; | 4037 | pSMB->ParameterCount = pSMB->TotalParameterCount; |
4023 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO); | 4038 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO); |
4024 | pSMB->Reserved4 = 0; | 4039 | pSMB->Reserved4 = 0; |
4025 | pSMB->hdr.smb_buf_length += byte_count; | 4040 | inc_rfc1001_len(pSMB, byte_count); |
4026 | pSMB->ByteCount = cpu_to_le16(byte_count); | 4041 | pSMB->ByteCount = cpu_to_le16(byte_count); |
4027 | 4042 | ||
4028 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 4043 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
@@ -4032,8 +4047,8 @@ GetInodeNumberRetry: | |||
4032 | } else { | 4047 | } else { |
4033 | /* decode response */ | 4048 | /* decode response */ |
4034 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 4049 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
4035 | if (rc || (pSMBr->ByteCount < 2)) | ||
4036 | /* BB also check enough total bytes returned */ | 4050 | /* BB also check enough total bytes returned */ |
4051 | if (rc || get_bcc(&pSMBr->hdr) < 2) | ||
4037 | /* If rc should we check for EOPNOSUPP and | 4052 | /* If rc should we check for EOPNOSUPP and |
4038 | disable the srvino flag? or in caller? */ | 4053 | disable the srvino flag? or in caller? */ |
4039 | rc = -EIO; /* bad smb */ | 4054 | rc = -EIO; /* bad smb */ |
@@ -4246,7 +4261,7 @@ getDFSRetry: | |||
4246 | pSMB->ParameterCount = cpu_to_le16(params); | 4261 | pSMB->ParameterCount = cpu_to_le16(params); |
4247 | pSMB->TotalParameterCount = pSMB->ParameterCount; | 4262 | pSMB->TotalParameterCount = pSMB->ParameterCount; |
4248 | pSMB->MaxReferralLevel = cpu_to_le16(3); | 4263 | pSMB->MaxReferralLevel = cpu_to_le16(3); |
4249 | pSMB->hdr.smb_buf_length += byte_count; | 4264 | inc_rfc1001_len(pSMB, byte_count); |
4250 | pSMB->ByteCount = cpu_to_le16(byte_count); | 4265 | pSMB->ByteCount = cpu_to_le16(byte_count); |
4251 | 4266 | ||
4252 | rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB, | 4267 | rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB, |
@@ -4258,13 +4273,13 @@ getDFSRetry: | |||
4258 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 4273 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
4259 | 4274 | ||
4260 | /* BB Also check if enough total bytes returned? */ | 4275 | /* BB Also check if enough total bytes returned? */ |
4261 | if (rc || (pSMBr->ByteCount < 17)) { | 4276 | if (rc || get_bcc(&pSMBr->hdr) < 17) { |
4262 | rc = -EIO; /* bad smb */ | 4277 | rc = -EIO; /* bad smb */ |
4263 | goto GetDFSRefExit; | 4278 | goto GetDFSRefExit; |
4264 | } | 4279 | } |
4265 | 4280 | ||
4266 | cFYI(1, "Decoding GetDFSRefer response BCC: %d Offset %d", | 4281 | cFYI(1, "Decoding GetDFSRefer response BCC: %d Offset %d", |
4267 | pSMBr->ByteCount, | 4282 | get_bcc(&pSMBr->hdr), |
4268 | le16_to_cpu(pSMBr->t2.DataOffset)); | 4283 | le16_to_cpu(pSMBr->t2.DataOffset)); |
4269 | 4284 | ||
4270 | /* parse returned result into more usable form */ | 4285 | /* parse returned result into more usable form */ |
@@ -4320,7 +4335,7 @@ oldQFSInfoRetry: | |||
4320 | pSMB->Reserved3 = 0; | 4335 | pSMB->Reserved3 = 0; |
4321 | pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION); | 4336 | pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION); |
4322 | pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION); | 4337 | pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION); |
4323 | pSMB->hdr.smb_buf_length += byte_count; | 4338 | inc_rfc1001_len(pSMB, byte_count); |
4324 | pSMB->ByteCount = cpu_to_le16(byte_count); | 4339 | pSMB->ByteCount = cpu_to_le16(byte_count); |
4325 | 4340 | ||
4326 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 4341 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
@@ -4330,12 +4345,12 @@ oldQFSInfoRetry: | |||
4330 | } else { /* decode response */ | 4345 | } else { /* decode response */ |
4331 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 4346 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
4332 | 4347 | ||
4333 | if (rc || (pSMBr->ByteCount < 18)) | 4348 | if (rc || get_bcc(&pSMBr->hdr) < 18) |
4334 | rc = -EIO; /* bad smb */ | 4349 | rc = -EIO; /* bad smb */ |
4335 | else { | 4350 | else { |
4336 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); | 4351 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); |
4337 | cFYI(1, "qfsinf resp BCC: %d Offset %d", | 4352 | cFYI(1, "qfsinf resp BCC: %d Offset %d", |
4338 | pSMBr->ByteCount, data_offset); | 4353 | get_bcc(&pSMBr->hdr), data_offset); |
4339 | 4354 | ||
4340 | response_data = (FILE_SYSTEM_ALLOC_INFO *) | 4355 | response_data = (FILE_SYSTEM_ALLOC_INFO *) |
4341 | (((char *) &pSMBr->hdr.Protocol) + data_offset); | 4356 | (((char *) &pSMBr->hdr.Protocol) + data_offset); |
@@ -4399,7 +4414,7 @@ QFSInfoRetry: | |||
4399 | pSMB->Reserved3 = 0; | 4414 | pSMB->Reserved3 = 0; |
4400 | pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION); | 4415 | pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION); |
4401 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO); | 4416 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO); |
4402 | pSMB->hdr.smb_buf_length += byte_count; | 4417 | inc_rfc1001_len(pSMB, byte_count); |
4403 | pSMB->ByteCount = cpu_to_le16(byte_count); | 4418 | pSMB->ByteCount = cpu_to_le16(byte_count); |
4404 | 4419 | ||
4405 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 4420 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
@@ -4409,7 +4424,7 @@ QFSInfoRetry: | |||
4409 | } else { /* decode response */ | 4424 | } else { /* decode response */ |
4410 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 4425 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
4411 | 4426 | ||
4412 | if (rc || (pSMBr->ByteCount < 24)) | 4427 | if (rc || get_bcc(&pSMBr->hdr) < 24) |
4413 | rc = -EIO; /* bad smb */ | 4428 | rc = -EIO; /* bad smb */ |
4414 | else { | 4429 | else { |
4415 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); | 4430 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); |
@@ -4479,7 +4494,7 @@ QFSAttributeRetry: | |||
4479 | pSMB->Reserved3 = 0; | 4494 | pSMB->Reserved3 = 0; |
4480 | pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION); | 4495 | pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION); |
4481 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO); | 4496 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO); |
4482 | pSMB->hdr.smb_buf_length += byte_count; | 4497 | inc_rfc1001_len(pSMB, byte_count); |
4483 | pSMB->ByteCount = cpu_to_le16(byte_count); | 4498 | pSMB->ByteCount = cpu_to_le16(byte_count); |
4484 | 4499 | ||
4485 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 4500 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
@@ -4489,7 +4504,7 @@ QFSAttributeRetry: | |||
4489 | } else { /* decode response */ | 4504 | } else { /* decode response */ |
4490 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 4505 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
4491 | 4506 | ||
4492 | if (rc || (pSMBr->ByteCount < 13)) { | 4507 | if (rc || get_bcc(&pSMBr->hdr) < 13) { |
4493 | /* BB also check if enough bytes returned */ | 4508 | /* BB also check if enough bytes returned */ |
4494 | rc = -EIO; /* bad smb */ | 4509 | rc = -EIO; /* bad smb */ |
4495 | } else { | 4510 | } else { |
@@ -4550,7 +4565,7 @@ QFSDeviceRetry: | |||
4550 | pSMB->Reserved3 = 0; | 4565 | pSMB->Reserved3 = 0; |
4551 | pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION); | 4566 | pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION); |
4552 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO); | 4567 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO); |
4553 | pSMB->hdr.smb_buf_length += byte_count; | 4568 | inc_rfc1001_len(pSMB, byte_count); |
4554 | pSMB->ByteCount = cpu_to_le16(byte_count); | 4569 | pSMB->ByteCount = cpu_to_le16(byte_count); |
4555 | 4570 | ||
4556 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 4571 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
@@ -4560,7 +4575,8 @@ QFSDeviceRetry: | |||
4560 | } else { /* decode response */ | 4575 | } else { /* decode response */ |
4561 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 4576 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
4562 | 4577 | ||
4563 | if (rc || (pSMBr->ByteCount < sizeof(FILE_SYSTEM_DEVICE_INFO))) | 4578 | if (rc || get_bcc(&pSMBr->hdr) < |
4579 | sizeof(FILE_SYSTEM_DEVICE_INFO)) | ||
4564 | rc = -EIO; /* bad smb */ | 4580 | rc = -EIO; /* bad smb */ |
4565 | else { | 4581 | else { |
4566 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); | 4582 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); |
@@ -4619,7 +4635,7 @@ QFSUnixRetry: | |||
4619 | pSMB->Reserved3 = 0; | 4635 | pSMB->Reserved3 = 0; |
4620 | pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION); | 4636 | pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION); |
4621 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO); | 4637 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO); |
4622 | pSMB->hdr.smb_buf_length += byte_count; | 4638 | inc_rfc1001_len(pSMB, byte_count); |
4623 | pSMB->ByteCount = cpu_to_le16(byte_count); | 4639 | pSMB->ByteCount = cpu_to_le16(byte_count); |
4624 | 4640 | ||
4625 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 4641 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
@@ -4629,7 +4645,7 @@ QFSUnixRetry: | |||
4629 | } else { /* decode response */ | 4645 | } else { /* decode response */ |
4630 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 4646 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
4631 | 4647 | ||
4632 | if (rc || (pSMBr->ByteCount < 13)) { | 4648 | if (rc || get_bcc(&pSMBr->hdr) < 13) { |
4633 | rc = -EIO; /* bad smb */ | 4649 | rc = -EIO; /* bad smb */ |
4634 | } else { | 4650 | } else { |
4635 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); | 4651 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); |
@@ -4702,7 +4718,7 @@ SETFSUnixRetry: | |||
4702 | pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION); | 4718 | pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION); |
4703 | pSMB->ClientUnixCap = cpu_to_le64(cap); | 4719 | pSMB->ClientUnixCap = cpu_to_le64(cap); |
4704 | 4720 | ||
4705 | pSMB->hdr.smb_buf_length += byte_count; | 4721 | inc_rfc1001_len(pSMB, byte_count); |
4706 | pSMB->ByteCount = cpu_to_le16(byte_count); | 4722 | pSMB->ByteCount = cpu_to_le16(byte_count); |
4707 | 4723 | ||
4708 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 4724 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
@@ -4764,7 +4780,7 @@ QFSPosixRetry: | |||
4764 | pSMB->Reserved3 = 0; | 4780 | pSMB->Reserved3 = 0; |
4765 | pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION); | 4781 | pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION); |
4766 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO); | 4782 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO); |
4767 | pSMB->hdr.smb_buf_length += byte_count; | 4783 | inc_rfc1001_len(pSMB, byte_count); |
4768 | pSMB->ByteCount = cpu_to_le16(byte_count); | 4784 | pSMB->ByteCount = cpu_to_le16(byte_count); |
4769 | 4785 | ||
4770 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 4786 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
@@ -4774,7 +4790,7 @@ QFSPosixRetry: | |||
4774 | } else { /* decode response */ | 4790 | } else { /* decode response */ |
4775 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 4791 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
4776 | 4792 | ||
4777 | if (rc || (pSMBr->ByteCount < 13)) { | 4793 | if (rc || get_bcc(&pSMBr->hdr) < 13) { |
4778 | rc = -EIO; /* bad smb */ | 4794 | rc = -EIO; /* bad smb */ |
4779 | } else { | 4795 | } else { |
4780 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); | 4796 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); |
@@ -4890,7 +4906,7 @@ SetEOFRetry: | |||
4890 | pSMB->ParameterCount = cpu_to_le16(params); | 4906 | pSMB->ParameterCount = cpu_to_le16(params); |
4891 | pSMB->TotalParameterCount = pSMB->ParameterCount; | 4907 | pSMB->TotalParameterCount = pSMB->ParameterCount; |
4892 | pSMB->Reserved4 = 0; | 4908 | pSMB->Reserved4 = 0; |
4893 | pSMB->hdr.smb_buf_length += byte_count; | 4909 | inc_rfc1001_len(pSMB, byte_count); |
4894 | parm_data->FileSize = cpu_to_le64(size); | 4910 | parm_data->FileSize = cpu_to_le64(size); |
4895 | pSMB->ByteCount = cpu_to_le16(byte_count); | 4911 | pSMB->ByteCount = cpu_to_le16(byte_count); |
4896 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 4912 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
@@ -4969,7 +4985,7 @@ CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size, | |||
4969 | cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO); | 4985 | cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO); |
4970 | } | 4986 | } |
4971 | pSMB->Reserved4 = 0; | 4987 | pSMB->Reserved4 = 0; |
4972 | pSMB->hdr.smb_buf_length += byte_count; | 4988 | inc_rfc1001_len(pSMB, byte_count); |
4973 | pSMB->ByteCount = cpu_to_le16(byte_count); | 4989 | pSMB->ByteCount = cpu_to_le16(byte_count); |
4974 | rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); | 4990 | rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); |
4975 | if (rc) { | 4991 | if (rc) { |
@@ -5037,7 +5053,7 @@ CIFSSMBSetFileInfo(const int xid, struct cifsTconInfo *tcon, | |||
5037 | else | 5053 | else |
5038 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO); | 5054 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO); |
5039 | pSMB->Reserved4 = 0; | 5055 | pSMB->Reserved4 = 0; |
5040 | pSMB->hdr.smb_buf_length += byte_count; | 5056 | inc_rfc1001_len(pSMB, byte_count); |
5041 | pSMB->ByteCount = cpu_to_le16(byte_count); | 5057 | pSMB->ByteCount = cpu_to_le16(byte_count); |
5042 | memcpy(data_offset, data, sizeof(FILE_BASIC_INFO)); | 5058 | memcpy(data_offset, data, sizeof(FILE_BASIC_INFO)); |
5043 | rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); | 5059 | rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); |
@@ -5096,7 +5112,7 @@ CIFSSMBSetFileDisposition(const int xid, struct cifsTconInfo *tcon, | |||
5096 | pSMB->Fid = fid; | 5112 | pSMB->Fid = fid; |
5097 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO); | 5113 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO); |
5098 | pSMB->Reserved4 = 0; | 5114 | pSMB->Reserved4 = 0; |
5099 | pSMB->hdr.smb_buf_length += byte_count; | 5115 | inc_rfc1001_len(pSMB, byte_count); |
5100 | pSMB->ByteCount = cpu_to_le16(byte_count); | 5116 | pSMB->ByteCount = cpu_to_le16(byte_count); |
5101 | *data_offset = delete_file ? 1 : 0; | 5117 | *data_offset = delete_file ? 1 : 0; |
5102 | rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); | 5118 | rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); |
@@ -5169,7 +5185,7 @@ SetTimesRetry: | |||
5169 | else | 5185 | else |
5170 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO); | 5186 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO); |
5171 | pSMB->Reserved4 = 0; | 5187 | pSMB->Reserved4 = 0; |
5172 | pSMB->hdr.smb_buf_length += byte_count; | 5188 | inc_rfc1001_len(pSMB, byte_count); |
5173 | memcpy(data_offset, data, sizeof(FILE_BASIC_INFO)); | 5189 | memcpy(data_offset, data, sizeof(FILE_BASIC_INFO)); |
5174 | pSMB->ByteCount = cpu_to_le16(byte_count); | 5190 | pSMB->ByteCount = cpu_to_le16(byte_count); |
5175 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 5191 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
@@ -5221,7 +5237,7 @@ SetAttrLgcyRetry: | |||
5221 | } | 5237 | } |
5222 | pSMB->attr = cpu_to_le16(dos_attrs); | 5238 | pSMB->attr = cpu_to_le16(dos_attrs); |
5223 | pSMB->BufferFormat = 0x04; | 5239 | pSMB->BufferFormat = 0x04; |
5224 | pSMB->hdr.smb_buf_length += name_len + 1; | 5240 | inc_rfc1001_len(pSMB, name_len + 1); |
5225 | pSMB->ByteCount = cpu_to_le16(name_len + 1); | 5241 | pSMB->ByteCount = cpu_to_le16(name_len + 1); |
5226 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 5242 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
5227 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 5243 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
@@ -5326,7 +5342,7 @@ CIFSSMBUnixSetFileInfo(const int xid, struct cifsTconInfo *tcon, | |||
5326 | pSMB->Fid = fid; | 5342 | pSMB->Fid = fid; |
5327 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC); | 5343 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC); |
5328 | pSMB->Reserved4 = 0; | 5344 | pSMB->Reserved4 = 0; |
5329 | pSMB->hdr.smb_buf_length += byte_count; | 5345 | inc_rfc1001_len(pSMB, byte_count); |
5330 | pSMB->ByteCount = cpu_to_le16(byte_count); | 5346 | pSMB->ByteCount = cpu_to_le16(byte_count); |
5331 | 5347 | ||
5332 | cifs_fill_unix_set_info(data_offset, args); | 5348 | cifs_fill_unix_set_info(data_offset, args); |
@@ -5402,7 +5418,7 @@ setPermsRetry: | |||
5402 | pSMB->TotalDataCount = pSMB->DataCount; | 5418 | pSMB->TotalDataCount = pSMB->DataCount; |
5403 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC); | 5419 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC); |
5404 | pSMB->Reserved4 = 0; | 5420 | pSMB->Reserved4 = 0; |
5405 | pSMB->hdr.smb_buf_length += byte_count; | 5421 | inc_rfc1001_len(pSMB, byte_count); |
5406 | 5422 | ||
5407 | cifs_fill_unix_set_info(data_offset, args); | 5423 | cifs_fill_unix_set_info(data_offset, args); |
5408 | 5424 | ||
@@ -5418,79 +5434,6 @@ setPermsRetry: | |||
5418 | return rc; | 5434 | return rc; |
5419 | } | 5435 | } |
5420 | 5436 | ||
5421 | int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon, | ||
5422 | const int notify_subdirs, const __u16 netfid, | ||
5423 | __u32 filter, struct file *pfile, int multishot, | ||
5424 | const struct nls_table *nls_codepage) | ||
5425 | { | ||
5426 | int rc = 0; | ||
5427 | struct smb_com_transaction_change_notify_req *pSMB = NULL; | ||
5428 | struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL; | ||
5429 | struct dir_notify_req *dnotify_req; | ||
5430 | int bytes_returned; | ||
5431 | |||
5432 | cFYI(1, "In CIFSSMBNotify for file handle %d", (int)netfid); | ||
5433 | rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB, | ||
5434 | (void **) &pSMBr); | ||
5435 | if (rc) | ||
5436 | return rc; | ||
5437 | |||
5438 | pSMB->TotalParameterCount = 0 ; | ||
5439 | pSMB->TotalDataCount = 0; | ||
5440 | pSMB->MaxParameterCount = cpu_to_le32(2); | ||
5441 | /* BB find exact data count max from sess structure BB */ | ||
5442 | pSMB->MaxDataCount = 0; /* same in little endian or be */ | ||
5443 | /* BB VERIFY verify which is correct for above BB */ | ||
5444 | pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf - | ||
5445 | MAX_CIFS_HDR_SIZE) & 0xFFFFFF00); | ||
5446 | |||
5447 | pSMB->MaxSetupCount = 4; | ||
5448 | pSMB->Reserved = 0; | ||
5449 | pSMB->ParameterOffset = 0; | ||
5450 | pSMB->DataCount = 0; | ||
5451 | pSMB->DataOffset = 0; | ||
5452 | pSMB->SetupCount = 4; /* single byte does not need le conversion */ | ||
5453 | pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE); | ||
5454 | pSMB->ParameterCount = pSMB->TotalParameterCount; | ||
5455 | if (notify_subdirs) | ||
5456 | pSMB->WatchTree = 1; /* one byte - no le conversion needed */ | ||
5457 | pSMB->Reserved2 = 0; | ||
5458 | pSMB->CompletionFilter = cpu_to_le32(filter); | ||
5459 | pSMB->Fid = netfid; /* file handle always le */ | ||
5460 | pSMB->ByteCount = 0; | ||
5461 | |||
5462 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | ||
5463 | (struct smb_hdr *)pSMBr, &bytes_returned, | ||
5464 | CIFS_ASYNC_OP); | ||
5465 | if (rc) { | ||
5466 | cFYI(1, "Error in Notify = %d", rc); | ||
5467 | } else { | ||
5468 | /* Add file to outstanding requests */ | ||
5469 | /* BB change to kmem cache alloc */ | ||
5470 | dnotify_req = kmalloc( | ||
5471 | sizeof(struct dir_notify_req), | ||
5472 | GFP_KERNEL); | ||
5473 | if (dnotify_req) { | ||
5474 | dnotify_req->Pid = pSMB->hdr.Pid; | ||
5475 | dnotify_req->PidHigh = pSMB->hdr.PidHigh; | ||
5476 | dnotify_req->Mid = pSMB->hdr.Mid; | ||
5477 | dnotify_req->Tid = pSMB->hdr.Tid; | ||
5478 | dnotify_req->Uid = pSMB->hdr.Uid; | ||
5479 | dnotify_req->netfid = netfid; | ||
5480 | dnotify_req->pfile = pfile; | ||
5481 | dnotify_req->filter = filter; | ||
5482 | dnotify_req->multishot = multishot; | ||
5483 | spin_lock(&GlobalMid_Lock); | ||
5484 | list_add_tail(&dnotify_req->lhead, | ||
5485 | &GlobalDnotifyReqList); | ||
5486 | spin_unlock(&GlobalMid_Lock); | ||
5487 | } else | ||
5488 | rc = -ENOMEM; | ||
5489 | } | ||
5490 | cifs_buf_release(pSMB); | ||
5491 | return rc; | ||
5492 | } | ||
5493 | |||
5494 | #ifdef CONFIG_CIFS_XATTR | 5437 | #ifdef CONFIG_CIFS_XATTR |
5495 | /* | 5438 | /* |
5496 | * Do a path-based QUERY_ALL_EAS call and parse the result. This is a common | 5439 | * Do a path-based QUERY_ALL_EAS call and parse the result. This is a common |
@@ -5560,7 +5503,7 @@ QAllEAsRetry: | |||
5560 | pSMB->ParameterCount = pSMB->TotalParameterCount; | 5503 | pSMB->ParameterCount = pSMB->TotalParameterCount; |
5561 | pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS); | 5504 | pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS); |
5562 | pSMB->Reserved4 = 0; | 5505 | pSMB->Reserved4 = 0; |
5563 | pSMB->hdr.smb_buf_length += byte_count; | 5506 | inc_rfc1001_len(pSMB, byte_count); |
5564 | pSMB->ByteCount = cpu_to_le16(byte_count); | 5507 | pSMB->ByteCount = cpu_to_le16(byte_count); |
5565 | 5508 | ||
5566 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 5509 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
@@ -5576,7 +5519,7 @@ QAllEAsRetry: | |||
5576 | of these trans2 responses */ | 5519 | of these trans2 responses */ |
5577 | 5520 | ||
5578 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 5521 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
5579 | if (rc || (pSMBr->ByteCount < 4)) { | 5522 | if (rc || get_bcc(&pSMBr->hdr) < 4) { |
5580 | rc = -EIO; /* bad smb */ | 5523 | rc = -EIO; /* bad smb */ |
5581 | goto QAllEAsOut; | 5524 | goto QAllEAsOut; |
5582 | } | 5525 | } |
@@ -5773,7 +5716,7 @@ SetEARetry: | |||
5773 | pSMB->ParameterCount = cpu_to_le16(params); | 5716 | pSMB->ParameterCount = cpu_to_le16(params); |
5774 | pSMB->TotalParameterCount = pSMB->ParameterCount; | 5717 | pSMB->TotalParameterCount = pSMB->ParameterCount; |
5775 | pSMB->Reserved4 = 0; | 5718 | pSMB->Reserved4 = 0; |
5776 | pSMB->hdr.smb_buf_length += byte_count; | 5719 | inc_rfc1001_len(pSMB, byte_count); |
5777 | pSMB->ByteCount = cpu_to_le16(byte_count); | 5720 | pSMB->ByteCount = cpu_to_le16(byte_count); |
5778 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 5721 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
5779 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 5722 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
@@ -5787,5 +5730,99 @@ SetEARetry: | |||
5787 | 5730 | ||
5788 | return rc; | 5731 | return rc; |
5789 | } | 5732 | } |
5790 | |||
5791 | #endif | 5733 | #endif |
5734 | |||
5735 | #ifdef CONFIG_CIFS_DNOTIFY_EXPERIMENTAL /* BB unused temporarily */ | ||
5736 | /* | ||
5737 | * Years ago the kernel added a "dnotify" function for Samba server, | ||
5738 | * to allow network clients (such as Windows) to display updated | ||
5739 | * lists of files in directory listings automatically when | ||
5740 | * files are added by one user when another user has the | ||
5741 | * same directory open on their desktop. The Linux cifs kernel | ||
5742 | * client hooked into the kernel side of this interface for | ||
5743 | * the same reason, but ironically when the VFS moved from | ||
5744 | * "dnotify" to "inotify" it became harder to plug in Linux | ||
5745 | * network file system clients (the most obvious use case | ||
5746 | * for notify interfaces is when multiple users can update | ||
5747 | * the contents of the same directory - exactly what network | ||
5748 | * file systems can do) although the server (Samba) could | ||
5749 | * still use it. For the short term we leave the worker | ||
5750 | * function ifdeffed out (below) until inotify is fixed | ||
5751 | * in the VFS to make it easier to plug in network file | ||
5752 | * system clients. If inotify turns out to be permanently | ||
5753 | * incompatible for network fs clients, we could instead simply | ||
5754 | * expose this config flag by adding a future cifs (and smb2) notify ioctl. | ||
5755 | */ | ||
5756 | int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon, | ||
5757 | const int notify_subdirs, const __u16 netfid, | ||
5758 | __u32 filter, struct file *pfile, int multishot, | ||
5759 | const struct nls_table *nls_codepage) | ||
5760 | { | ||
5761 | int rc = 0; | ||
5762 | struct smb_com_transaction_change_notify_req *pSMB = NULL; | ||
5763 | struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL; | ||
5764 | struct dir_notify_req *dnotify_req; | ||
5765 | int bytes_returned; | ||
5766 | |||
5767 | cFYI(1, "In CIFSSMBNotify for file handle %d", (int)netfid); | ||
5768 | rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB, | ||
5769 | (void **) &pSMBr); | ||
5770 | if (rc) | ||
5771 | return rc; | ||
5772 | |||
5773 | pSMB->TotalParameterCount = 0 ; | ||
5774 | pSMB->TotalDataCount = 0; | ||
5775 | pSMB->MaxParameterCount = cpu_to_le32(2); | ||
5776 | /* BB find exact data count max from sess structure BB */ | ||
5777 | pSMB->MaxDataCount = 0; /* same in little endian or be */ | ||
5778 | /* BB VERIFY verify which is correct for above BB */ | ||
5779 | pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf - | ||
5780 | MAX_CIFS_HDR_SIZE) & 0xFFFFFF00); | ||
5781 | |||
5782 | pSMB->MaxSetupCount = 4; | ||
5783 | pSMB->Reserved = 0; | ||
5784 | pSMB->ParameterOffset = 0; | ||
5785 | pSMB->DataCount = 0; | ||
5786 | pSMB->DataOffset = 0; | ||
5787 | pSMB->SetupCount = 4; /* single byte does not need le conversion */ | ||
5788 | pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE); | ||
5789 | pSMB->ParameterCount = pSMB->TotalParameterCount; | ||
5790 | if (notify_subdirs) | ||
5791 | pSMB->WatchTree = 1; /* one byte - no le conversion needed */ | ||
5792 | pSMB->Reserved2 = 0; | ||
5793 | pSMB->CompletionFilter = cpu_to_le32(filter); | ||
5794 | pSMB->Fid = netfid; /* file handle always le */ | ||
5795 | pSMB->ByteCount = 0; | ||
5796 | |||
5797 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | ||
5798 | (struct smb_hdr *)pSMBr, &bytes_returned, | ||
5799 | CIFS_ASYNC_OP); | ||
5800 | if (rc) { | ||
5801 | cFYI(1, "Error in Notify = %d", rc); | ||
5802 | } else { | ||
5803 | /* Add file to outstanding requests */ | ||
5804 | /* BB change to kmem cache alloc */ | ||
5805 | dnotify_req = kmalloc( | ||
5806 | sizeof(struct dir_notify_req), | ||
5807 | GFP_KERNEL); | ||
5808 | if (dnotify_req) { | ||
5809 | dnotify_req->Pid = pSMB->hdr.Pid; | ||
5810 | dnotify_req->PidHigh = pSMB->hdr.PidHigh; | ||
5811 | dnotify_req->Mid = pSMB->hdr.Mid; | ||
5812 | dnotify_req->Tid = pSMB->hdr.Tid; | ||
5813 | dnotify_req->Uid = pSMB->hdr.Uid; | ||
5814 | dnotify_req->netfid = netfid; | ||
5815 | dnotify_req->pfile = pfile; | ||
5816 | dnotify_req->filter = filter; | ||
5817 | dnotify_req->multishot = multishot; | ||
5818 | spin_lock(&GlobalMid_Lock); | ||
5819 | list_add_tail(&dnotify_req->lhead, | ||
5820 | &GlobalDnotifyReqList); | ||
5821 | spin_unlock(&GlobalMid_Lock); | ||
5822 | } else | ||
5823 | rc = -ENOMEM; | ||
5824 | } | ||
5825 | cifs_buf_release(pSMB); | ||
5826 | return rc; | ||
5827 | } | ||
5828 | #endif /* was needed for dnotify, and will be needed for inotify when VFS fix */ | ||
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 277262a8e82f..da284e3cb653 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -102,6 +102,7 @@ struct smb_vol { | |||
102 | bool fsc:1; /* enable fscache */ | 102 | bool fsc:1; /* enable fscache */ |
103 | bool mfsymlinks:1; /* use Minshall+French Symlinks */ | 103 | bool mfsymlinks:1; /* use Minshall+French Symlinks */ |
104 | bool multiuser:1; | 104 | bool multiuser:1; |
105 | bool use_smb2:1; /* force smb2 use on mount instead of cifs */ | ||
105 | unsigned int rsize; | 106 | unsigned int rsize; |
106 | unsigned int wsize; | 107 | unsigned int wsize; |
107 | bool sockopt_tcp_nodelay:1; | 108 | bool sockopt_tcp_nodelay:1; |
@@ -316,19 +317,19 @@ static int coalesce_t2(struct smb_hdr *psecond, struct smb_hdr *pTargetSMB) | |||
316 | put_unaligned_le16(total_in_buf, &pSMBt->t2_rsp.DataCount); | 317 | put_unaligned_le16(total_in_buf, &pSMBt->t2_rsp.DataCount); |
317 | 318 | ||
318 | /* fix up the BCC */ | 319 | /* fix up the BCC */ |
319 | byte_count = get_bcc_le(pTargetSMB); | 320 | byte_count = get_bcc(pTargetSMB); |
320 | byte_count += total_in_buf2; | 321 | byte_count += total_in_buf2; |
321 | /* is the result too big for the field? */ | 322 | /* is the result too big for the field? */ |
322 | if (byte_count > USHRT_MAX) | 323 | if (byte_count > USHRT_MAX) |
323 | return -EPROTO; | 324 | return -EPROTO; |
324 | put_bcc_le(byte_count, pTargetSMB); | 325 | put_bcc(byte_count, pTargetSMB); |
325 | 326 | ||
326 | byte_count = pTargetSMB->smb_buf_length; | 327 | byte_count = be32_to_cpu(pTargetSMB->smb_buf_length); |
327 | byte_count += total_in_buf2; | 328 | byte_count += total_in_buf2; |
328 | /* don't allow buffer to overflow */ | 329 | /* don't allow buffer to overflow */ |
329 | if (byte_count > CIFSMaxBufSize) | 330 | if (byte_count > CIFSMaxBufSize) |
330 | return -ENOBUFS; | 331 | return -ENOBUFS; |
331 | pTargetSMB->smb_buf_length = byte_count; | 332 | pTargetSMB->smb_buf_length = cpu_to_be32(byte_count); |
332 | 333 | ||
333 | memcpy(data_area_of_target, data_area_of_buf2, total_in_buf2); | 334 | memcpy(data_area_of_target, data_area_of_buf2, total_in_buf2); |
334 | 335 | ||
@@ -495,8 +496,7 @@ incomplete_rcv: | |||
495 | /* Note that FC 1001 length is big endian on the wire, | 496 | /* Note that FC 1001 length is big endian on the wire, |
496 | but we convert it here so it is always manipulated | 497 | but we convert it here so it is always manipulated |
497 | as host byte order */ | 498 | as host byte order */ |
498 | pdu_length = be32_to_cpu((__force __be32)smb_buffer->smb_buf_length); | 499 | pdu_length = be32_to_cpu(smb_buffer->smb_buf_length); |
499 | smb_buffer->smb_buf_length = pdu_length; | ||
500 | 500 | ||
501 | cFYI(1, "rfc1002 length 0x%x", pdu_length+4); | 501 | cFYI(1, "rfc1002 length 0x%x", pdu_length+4); |
502 | 502 | ||
@@ -735,7 +735,7 @@ multi_t2_fnd: | |||
735 | sock_release(csocket); | 735 | sock_release(csocket); |
736 | server->ssocket = NULL; | 736 | server->ssocket = NULL; |
737 | } | 737 | } |
738 | /* buffer usuallly freed in free_mid - need to free it here on exit */ | 738 | /* buffer usually freed in free_mid - need to free it here on exit */ |
739 | cifs_buf_release(bigbuf); | 739 | cifs_buf_release(bigbuf); |
740 | if (smallbuf) /* no sense logging a debug message if NULL */ | 740 | if (smallbuf) /* no sense logging a debug message if NULL */ |
741 | cifs_small_buf_release(smallbuf); | 741 | cifs_small_buf_release(smallbuf); |
@@ -818,10 +818,11 @@ extract_hostname(const char *unc) | |||
818 | } | 818 | } |
819 | 819 | ||
820 | static int | 820 | static int |
821 | cifs_parse_mount_options(char *options, const char *devname, | 821 | cifs_parse_mount_options(const char *mountdata, const char *devname, |
822 | struct smb_vol *vol) | 822 | struct smb_vol *vol) |
823 | { | 823 | { |
824 | char *value, *data, *end; | 824 | char *value, *data, *end; |
825 | char *mountdata_copy, *options; | ||
825 | unsigned int temp_len, i, j; | 826 | unsigned int temp_len, i, j; |
826 | char separator[2]; | 827 | char separator[2]; |
827 | short int override_uid = -1; | 828 | short int override_uid = -1; |
@@ -861,9 +862,14 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
861 | 862 | ||
862 | vol->actimeo = CIFS_DEF_ACTIMEO; | 863 | vol->actimeo = CIFS_DEF_ACTIMEO; |
863 | 864 | ||
864 | if (!options) | 865 | if (!mountdata) |
865 | return 1; | 866 | goto cifs_parse_mount_err; |
867 | |||
868 | mountdata_copy = kstrndup(mountdata, PAGE_SIZE, GFP_KERNEL); | ||
869 | if (!mountdata_copy) | ||
870 | goto cifs_parse_mount_err; | ||
866 | 871 | ||
872 | options = mountdata_copy; | ||
867 | end = options + strlen(options); | 873 | end = options + strlen(options); |
868 | if (strncmp(options, "sep=", 4) == 0) { | 874 | if (strncmp(options, "sep=", 4) == 0) { |
869 | if (options[4] != 0) { | 875 | if (options[4] != 0) { |
@@ -889,17 +895,22 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
889 | if (!value) { | 895 | if (!value) { |
890 | printk(KERN_WARNING | 896 | printk(KERN_WARNING |
891 | "CIFS: invalid or missing username\n"); | 897 | "CIFS: invalid or missing username\n"); |
892 | return 1; /* needs_arg; */ | 898 | goto cifs_parse_mount_err; |
893 | } else if (!*value) { | 899 | } else if (!*value) { |
894 | /* null user, ie anonymous, authentication */ | 900 | /* null user, ie anonymous, authentication */ |
895 | vol->nullauth = 1; | 901 | vol->nullauth = 1; |
896 | } | 902 | } |
897 | if (strnlen(value, MAX_USERNAME_SIZE) < | 903 | if (strnlen(value, MAX_USERNAME_SIZE) < |
898 | MAX_USERNAME_SIZE) { | 904 | MAX_USERNAME_SIZE) { |
899 | vol->username = value; | 905 | vol->username = kstrdup(value, GFP_KERNEL); |
906 | if (!vol->username) { | ||
907 | printk(KERN_WARNING "CIFS: no memory " | ||
908 | "for username\n"); | ||
909 | goto cifs_parse_mount_err; | ||
910 | } | ||
900 | } else { | 911 | } else { |
901 | printk(KERN_WARNING "CIFS: username too long\n"); | 912 | printk(KERN_WARNING "CIFS: username too long\n"); |
902 | return 1; | 913 | goto cifs_parse_mount_err; |
903 | } | 914 | } |
904 | } else if (strnicmp(data, "pass", 4) == 0) { | 915 | } else if (strnicmp(data, "pass", 4) == 0) { |
905 | if (!value) { | 916 | if (!value) { |
@@ -963,7 +974,7 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
963 | if (vol->password == NULL) { | 974 | if (vol->password == NULL) { |
964 | printk(KERN_WARNING "CIFS: no memory " | 975 | printk(KERN_WARNING "CIFS: no memory " |
965 | "for password\n"); | 976 | "for password\n"); |
966 | return 1; | 977 | goto cifs_parse_mount_err; |
967 | } | 978 | } |
968 | for (i = 0, j = 0; i < temp_len; i++, j++) { | 979 | for (i = 0, j = 0; i < temp_len; i++, j++) { |
969 | vol->password[j] = value[i]; | 980 | vol->password[j] = value[i]; |
@@ -979,7 +990,7 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
979 | if (vol->password == NULL) { | 990 | if (vol->password == NULL) { |
980 | printk(KERN_WARNING "CIFS: no memory " | 991 | printk(KERN_WARNING "CIFS: no memory " |
981 | "for password\n"); | 992 | "for password\n"); |
982 | return 1; | 993 | goto cifs_parse_mount_err; |
983 | } | 994 | } |
984 | strcpy(vol->password, value); | 995 | strcpy(vol->password, value); |
985 | } | 996 | } |
@@ -989,11 +1000,16 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
989 | vol->UNCip = NULL; | 1000 | vol->UNCip = NULL; |
990 | } else if (strnlen(value, INET6_ADDRSTRLEN) < | 1001 | } else if (strnlen(value, INET6_ADDRSTRLEN) < |
991 | INET6_ADDRSTRLEN) { | 1002 | INET6_ADDRSTRLEN) { |
992 | vol->UNCip = value; | 1003 | vol->UNCip = kstrdup(value, GFP_KERNEL); |
1004 | if (!vol->UNCip) { | ||
1005 | printk(KERN_WARNING "CIFS: no memory " | ||
1006 | "for UNC IP\n"); | ||
1007 | goto cifs_parse_mount_err; | ||
1008 | } | ||
993 | } else { | 1009 | } else { |
994 | printk(KERN_WARNING "CIFS: ip address " | 1010 | printk(KERN_WARNING "CIFS: ip address " |
995 | "too long\n"); | 1011 | "too long\n"); |
996 | return 1; | 1012 | goto cifs_parse_mount_err; |
997 | } | 1013 | } |
998 | } else if (strnicmp(data, "sec", 3) == 0) { | 1014 | } else if (strnicmp(data, "sec", 3) == 0) { |
999 | if (!value || !*value) { | 1015 | if (!value || !*value) { |
@@ -1006,7 +1022,7 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
1006 | /* vol->secFlg |= CIFSSEC_MUST_SEAL | | 1022 | /* vol->secFlg |= CIFSSEC_MUST_SEAL | |
1007 | CIFSSEC_MAY_KRB5; */ | 1023 | CIFSSEC_MAY_KRB5; */ |
1008 | cERROR(1, "Krb5 cifs privacy not supported"); | 1024 | cERROR(1, "Krb5 cifs privacy not supported"); |
1009 | return 1; | 1025 | goto cifs_parse_mount_err; |
1010 | } else if (strnicmp(value, "krb5", 4) == 0) { | 1026 | } else if (strnicmp(value, "krb5", 4) == 0) { |
1011 | vol->secFlg |= CIFSSEC_MAY_KRB5; | 1027 | vol->secFlg |= CIFSSEC_MAY_KRB5; |
1012 | } else if (strnicmp(value, "ntlmsspi", 8) == 0) { | 1028 | } else if (strnicmp(value, "ntlmsspi", 8) == 0) { |
@@ -1036,7 +1052,23 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
1036 | vol->nullauth = 1; | 1052 | vol->nullauth = 1; |
1037 | } else { | 1053 | } else { |
1038 | cERROR(1, "bad security option: %s", value); | 1054 | cERROR(1, "bad security option: %s", value); |
1039 | return 1; | 1055 | goto cifs_parse_mount_err; |
1056 | } | ||
1057 | } else if (strnicmp(data, "vers", 3) == 0) { | ||
1058 | if (!value || !*value) { | ||
1059 | cERROR(1, "no protocol version specified" | ||
1060 | " after vers= mount option"); | ||
1061 | } else if ((strnicmp(value, "cifs", 4) == 0) || | ||
1062 | (strnicmp(value, "1", 1) == 0)) { | ||
1063 | /* this is the default */ | ||
1064 | continue; | ||
1065 | } else if ((strnicmp(value, "smb2", 4) == 0) || | ||
1066 | (strnicmp(value, "2", 1) == 0)) { | ||
1067 | #ifdef CONFIG_CIFS_SMB2 | ||
1068 | vol->use_smb2 = true; | ||
1069 | #else | ||
1070 | cERROR(1, "smb2 support not enabled"); | ||
1071 | #endif /* CONFIG_CIFS_SMB2 */ | ||
1040 | } | 1072 | } |
1041 | } else if ((strnicmp(data, "unc", 3) == 0) | 1073 | } else if ((strnicmp(data, "unc", 3) == 0) |
1042 | || (strnicmp(data, "target", 6) == 0) | 1074 | || (strnicmp(data, "target", 6) == 0) |
@@ -1044,12 +1076,12 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
1044 | if (!value || !*value) { | 1076 | if (!value || !*value) { |
1045 | printk(KERN_WARNING "CIFS: invalid path to " | 1077 | printk(KERN_WARNING "CIFS: invalid path to " |
1046 | "network resource\n"); | 1078 | "network resource\n"); |
1047 | return 1; /* needs_arg; */ | 1079 | goto cifs_parse_mount_err; |
1048 | } | 1080 | } |
1049 | if ((temp_len = strnlen(value, 300)) < 300) { | 1081 | if ((temp_len = strnlen(value, 300)) < 300) { |
1050 | vol->UNC = kmalloc(temp_len+1, GFP_KERNEL); | 1082 | vol->UNC = kmalloc(temp_len+1, GFP_KERNEL); |
1051 | if (vol->UNC == NULL) | 1083 | if (vol->UNC == NULL) |
1052 | return 1; | 1084 | goto cifs_parse_mount_err; |
1053 | strcpy(vol->UNC, value); | 1085 | strcpy(vol->UNC, value); |
1054 | if (strncmp(vol->UNC, "//", 2) == 0) { | 1086 | if (strncmp(vol->UNC, "//", 2) == 0) { |
1055 | vol->UNC[0] = '\\'; | 1087 | vol->UNC[0] = '\\'; |
@@ -1058,27 +1090,32 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
1058 | printk(KERN_WARNING | 1090 | printk(KERN_WARNING |
1059 | "CIFS: UNC Path does not begin " | 1091 | "CIFS: UNC Path does not begin " |
1060 | "with // or \\\\ \n"); | 1092 | "with // or \\\\ \n"); |
1061 | return 1; | 1093 | goto cifs_parse_mount_err; |
1062 | } | 1094 | } |
1063 | } else { | 1095 | } else { |
1064 | printk(KERN_WARNING "CIFS: UNC name too long\n"); | 1096 | printk(KERN_WARNING "CIFS: UNC name too long\n"); |
1065 | return 1; | 1097 | goto cifs_parse_mount_err; |
1066 | } | 1098 | } |
1067 | } else if ((strnicmp(data, "domain", 3) == 0) | 1099 | } else if ((strnicmp(data, "domain", 3) == 0) |
1068 | || (strnicmp(data, "workgroup", 5) == 0)) { | 1100 | || (strnicmp(data, "workgroup", 5) == 0)) { |
1069 | if (!value || !*value) { | 1101 | if (!value || !*value) { |
1070 | printk(KERN_WARNING "CIFS: invalid domain name\n"); | 1102 | printk(KERN_WARNING "CIFS: invalid domain name\n"); |
1071 | return 1; /* needs_arg; */ | 1103 | goto cifs_parse_mount_err; |
1072 | } | 1104 | } |
1073 | /* BB are there cases in which a comma can be valid in | 1105 | /* BB are there cases in which a comma can be valid in |
1074 | a domain name and need special handling? */ | 1106 | a domain name and need special handling? */ |
1075 | if (strnlen(value, 256) < 256) { | 1107 | if (strnlen(value, 256) < 256) { |
1076 | vol->domainname = value; | 1108 | vol->domainname = kstrdup(value, GFP_KERNEL); |
1109 | if (!vol->domainname) { | ||
1110 | printk(KERN_WARNING "CIFS: no memory " | ||
1111 | "for domainname\n"); | ||
1112 | goto cifs_parse_mount_err; | ||
1113 | } | ||
1077 | cFYI(1, "Domain name set"); | 1114 | cFYI(1, "Domain name set"); |
1078 | } else { | 1115 | } else { |
1079 | printk(KERN_WARNING "CIFS: domain name too " | 1116 | printk(KERN_WARNING "CIFS: domain name too " |
1080 | "long\n"); | 1117 | "long\n"); |
1081 | return 1; | 1118 | goto cifs_parse_mount_err; |
1082 | } | 1119 | } |
1083 | } else if (strnicmp(data, "srcaddr", 7) == 0) { | 1120 | } else if (strnicmp(data, "srcaddr", 7) == 0) { |
1084 | vol->srcaddr.ss_family = AF_UNSPEC; | 1121 | vol->srcaddr.ss_family = AF_UNSPEC; |
@@ -1086,7 +1123,7 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
1086 | if (!value || !*value) { | 1123 | if (!value || !*value) { |
1087 | printk(KERN_WARNING "CIFS: srcaddr value" | 1124 | printk(KERN_WARNING "CIFS: srcaddr value" |
1088 | " not specified.\n"); | 1125 | " not specified.\n"); |
1089 | return 1; /* needs_arg; */ | 1126 | goto cifs_parse_mount_err; |
1090 | } | 1127 | } |
1091 | i = cifs_convert_address((struct sockaddr *)&vol->srcaddr, | 1128 | i = cifs_convert_address((struct sockaddr *)&vol->srcaddr, |
1092 | value, strlen(value)); | 1129 | value, strlen(value)); |
@@ -1094,20 +1131,20 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
1094 | printk(KERN_WARNING "CIFS: Could not parse" | 1131 | printk(KERN_WARNING "CIFS: Could not parse" |
1095 | " srcaddr: %s\n", | 1132 | " srcaddr: %s\n", |
1096 | value); | 1133 | value); |
1097 | return 1; | 1134 | goto cifs_parse_mount_err; |
1098 | } | 1135 | } |
1099 | } else if (strnicmp(data, "prefixpath", 10) == 0) { | 1136 | } else if (strnicmp(data, "prefixpath", 10) == 0) { |
1100 | if (!value || !*value) { | 1137 | if (!value || !*value) { |
1101 | printk(KERN_WARNING | 1138 | printk(KERN_WARNING |
1102 | "CIFS: invalid path prefix\n"); | 1139 | "CIFS: invalid path prefix\n"); |
1103 | return 1; /* needs_argument */ | 1140 | goto cifs_parse_mount_err; |
1104 | } | 1141 | } |
1105 | if ((temp_len = strnlen(value, 1024)) < 1024) { | 1142 | if ((temp_len = strnlen(value, 1024)) < 1024) { |
1106 | if (value[0] != '/') | 1143 | if (value[0] != '/') |
1107 | temp_len++; /* missing leading slash */ | 1144 | temp_len++; /* missing leading slash */ |
1108 | vol->prepath = kmalloc(temp_len+1, GFP_KERNEL); | 1145 | vol->prepath = kmalloc(temp_len+1, GFP_KERNEL); |
1109 | if (vol->prepath == NULL) | 1146 | if (vol->prepath == NULL) |
1110 | return 1; | 1147 | goto cifs_parse_mount_err; |
1111 | if (value[0] != '/') { | 1148 | if (value[0] != '/') { |
1112 | vol->prepath[0] = '/'; | 1149 | vol->prepath[0] = '/'; |
1113 | strcpy(vol->prepath+1, value); | 1150 | strcpy(vol->prepath+1, value); |
@@ -1116,24 +1153,33 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
1116 | cFYI(1, "prefix path %s", vol->prepath); | 1153 | cFYI(1, "prefix path %s", vol->prepath); |
1117 | } else { | 1154 | } else { |
1118 | printk(KERN_WARNING "CIFS: prefix too long\n"); | 1155 | printk(KERN_WARNING "CIFS: prefix too long\n"); |
1119 | return 1; | 1156 | goto cifs_parse_mount_err; |
1120 | } | 1157 | } |
1121 | } else if (strnicmp(data, "iocharset", 9) == 0) { | 1158 | } else if (strnicmp(data, "iocharset", 9) == 0) { |
1122 | if (!value || !*value) { | 1159 | if (!value || !*value) { |
1123 | printk(KERN_WARNING "CIFS: invalid iocharset " | 1160 | printk(KERN_WARNING "CIFS: invalid iocharset " |
1124 | "specified\n"); | 1161 | "specified\n"); |
1125 | return 1; /* needs_arg; */ | 1162 | goto cifs_parse_mount_err; |
1126 | } | 1163 | } |
1127 | if (strnlen(value, 65) < 65) { | 1164 | if (strnlen(value, 65) < 65) { |
1128 | if (strnicmp(value, "default", 7)) | 1165 | if (strnicmp(value, "default", 7)) { |
1129 | vol->iocharset = value; | 1166 | vol->iocharset = kstrdup(value, |
1167 | GFP_KERNEL); | ||
1168 | |||
1169 | if (!vol->iocharset) { | ||
1170 | printk(KERN_WARNING "CIFS: no " | ||
1171 | "memory for" | ||
1172 | "charset\n"); | ||
1173 | goto cifs_parse_mount_err; | ||
1174 | } | ||
1175 | } | ||
1130 | /* if iocharset not set then load_nls_default | 1176 | /* if iocharset not set then load_nls_default |
1131 | is used by caller */ | 1177 | is used by caller */ |
1132 | cFYI(1, "iocharset set to %s", value); | 1178 | cFYI(1, "iocharset set to %s", value); |
1133 | } else { | 1179 | } else { |
1134 | printk(KERN_WARNING "CIFS: iocharset name " | 1180 | printk(KERN_WARNING "CIFS: iocharset name " |
1135 | "too long.\n"); | 1181 | "too long.\n"); |
1136 | return 1; | 1182 | goto cifs_parse_mount_err; |
1137 | } | 1183 | } |
1138 | } else if (!strnicmp(data, "uid", 3) && value && *value) { | 1184 | } else if (!strnicmp(data, "uid", 3) && value && *value) { |
1139 | vol->linux_uid = simple_strtoul(value, &value, 0); | 1185 | vol->linux_uid = simple_strtoul(value, &value, 0); |
@@ -1246,7 +1292,7 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
1246 | if (vol->actimeo > CIFS_MAX_ACTIMEO) { | 1292 | if (vol->actimeo > CIFS_MAX_ACTIMEO) { |
1247 | cERROR(1, "CIFS: attribute cache" | 1293 | cERROR(1, "CIFS: attribute cache" |
1248 | "timeout too large"); | 1294 | "timeout too large"); |
1249 | return 1; | 1295 | goto cifs_parse_mount_err; |
1250 | } | 1296 | } |
1251 | } | 1297 | } |
1252 | } else if (strnicmp(data, "credentials", 4) == 0) { | 1298 | } else if (strnicmp(data, "credentials", 4) == 0) { |
@@ -1390,7 +1436,7 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
1390 | #ifndef CONFIG_CIFS_FSCACHE | 1436 | #ifndef CONFIG_CIFS_FSCACHE |
1391 | cERROR(1, "FS-Cache support needs CONFIG_CIFS_FSCACHE" | 1437 | cERROR(1, "FS-Cache support needs CONFIG_CIFS_FSCACHE" |
1392 | "kernel config option set"); | 1438 | "kernel config option set"); |
1393 | return 1; | 1439 | goto cifs_parse_mount_err; |
1394 | #endif | 1440 | #endif |
1395 | vol->fsc = true; | 1441 | vol->fsc = true; |
1396 | } else if (strnicmp(data, "mfsymlinks", 10) == 0) { | 1442 | } else if (strnicmp(data, "mfsymlinks", 10) == 0) { |
@@ -1405,12 +1451,12 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
1405 | if (devname == NULL) { | 1451 | if (devname == NULL) { |
1406 | printk(KERN_WARNING "CIFS: Missing UNC name for mount " | 1452 | printk(KERN_WARNING "CIFS: Missing UNC name for mount " |
1407 | "target\n"); | 1453 | "target\n"); |
1408 | return 1; | 1454 | goto cifs_parse_mount_err; |
1409 | } | 1455 | } |
1410 | if ((temp_len = strnlen(devname, 300)) < 300) { | 1456 | if ((temp_len = strnlen(devname, 300)) < 300) { |
1411 | vol->UNC = kmalloc(temp_len+1, GFP_KERNEL); | 1457 | vol->UNC = kmalloc(temp_len+1, GFP_KERNEL); |
1412 | if (vol->UNC == NULL) | 1458 | if (vol->UNC == NULL) |
1413 | return 1; | 1459 | goto cifs_parse_mount_err; |
1414 | strcpy(vol->UNC, devname); | 1460 | strcpy(vol->UNC, devname); |
1415 | if (strncmp(vol->UNC, "//", 2) == 0) { | 1461 | if (strncmp(vol->UNC, "//", 2) == 0) { |
1416 | vol->UNC[0] = '\\'; | 1462 | vol->UNC[0] = '\\'; |
@@ -1418,21 +1464,21 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
1418 | } else if (strncmp(vol->UNC, "\\\\", 2) != 0) { | 1464 | } else if (strncmp(vol->UNC, "\\\\", 2) != 0) { |
1419 | printk(KERN_WARNING "CIFS: UNC Path does not " | 1465 | printk(KERN_WARNING "CIFS: UNC Path does not " |
1420 | "begin with // or \\\\ \n"); | 1466 | "begin with // or \\\\ \n"); |
1421 | return 1; | 1467 | goto cifs_parse_mount_err; |
1422 | } | 1468 | } |
1423 | value = strpbrk(vol->UNC+2, "/\\"); | 1469 | value = strpbrk(vol->UNC+2, "/\\"); |
1424 | if (value) | 1470 | if (value) |
1425 | *value = '\\'; | 1471 | *value = '\\'; |
1426 | } else { | 1472 | } else { |
1427 | printk(KERN_WARNING "CIFS: UNC name too long\n"); | 1473 | printk(KERN_WARNING "CIFS: UNC name too long\n"); |
1428 | return 1; | 1474 | goto cifs_parse_mount_err; |
1429 | } | 1475 | } |
1430 | } | 1476 | } |
1431 | 1477 | ||
1432 | if (vol->multiuser && !(vol->secFlg & CIFSSEC_MAY_KRB5)) { | 1478 | if (vol->multiuser && !(vol->secFlg & CIFSSEC_MAY_KRB5)) { |
1433 | cERROR(1, "Multiuser mounts currently require krb5 " | 1479 | cERROR(1, "Multiuser mounts currently require krb5 " |
1434 | "authentication!"); | 1480 | "authentication!"); |
1435 | return 1; | 1481 | goto cifs_parse_mount_err; |
1436 | } | 1482 | } |
1437 | 1483 | ||
1438 | if (vol->UNCip == NULL) | 1484 | if (vol->UNCip == NULL) |
@@ -1450,7 +1496,12 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
1450 | printk(KERN_NOTICE "CIFS: ignoring forcegid mount option " | 1496 | printk(KERN_NOTICE "CIFS: ignoring forcegid mount option " |
1451 | "specified with no gid= option.\n"); | 1497 | "specified with no gid= option.\n"); |
1452 | 1498 | ||
1499 | kfree(mountdata_copy); | ||
1453 | return 0; | 1500 | return 0; |
1501 | |||
1502 | cifs_parse_mount_err: | ||
1503 | kfree(mountdata_copy); | ||
1504 | return 1; | ||
1454 | } | 1505 | } |
1455 | 1506 | ||
1456 | /** Returns true if srcaddr isn't specified and rhs isn't | 1507 | /** Returns true if srcaddr isn't specified and rhs isn't |
@@ -2280,7 +2331,7 @@ ip_rfc1001_connect(struct TCP_Server_Info *server) | |||
2280 | smb_buf = (struct smb_hdr *)ses_init_buf; | 2331 | smb_buf = (struct smb_hdr *)ses_init_buf; |
2281 | 2332 | ||
2282 | /* sizeof RFC1002_SESSION_REQUEST with no scope */ | 2333 | /* sizeof RFC1002_SESSION_REQUEST with no scope */ |
2283 | smb_buf->smb_buf_length = 0x81000044; | 2334 | smb_buf->smb_buf_length = cpu_to_be32(0x81000044); |
2284 | rc = smb_send(server, smb_buf, 0x44); | 2335 | rc = smb_send(server, smb_buf, 0x44); |
2285 | kfree(ses_init_buf); | 2336 | kfree(ses_init_buf); |
2286 | /* | 2337 | /* |
@@ -2691,8 +2742,12 @@ cleanup_volume_info(struct smb_vol **pvolume_info) | |||
2691 | return; | 2742 | return; |
2692 | 2743 | ||
2693 | volume_info = *pvolume_info; | 2744 | volume_info = *pvolume_info; |
2745 | kfree(volume_info->username); | ||
2694 | kzfree(volume_info->password); | 2746 | kzfree(volume_info->password); |
2695 | kfree(volume_info->UNC); | 2747 | kfree(volume_info->UNC); |
2748 | kfree(volume_info->UNCip); | ||
2749 | kfree(volume_info->domainname); | ||
2750 | kfree(volume_info->iocharset); | ||
2696 | kfree(volume_info->prepath); | 2751 | kfree(volume_info->prepath); |
2697 | kfree(volume_info); | 2752 | kfree(volume_info); |
2698 | *pvolume_info = NULL; | 2753 | *pvolume_info = NULL; |
@@ -2729,11 +2784,65 @@ build_unc_path_to_root(const struct smb_vol *volume_info, | |||
2729 | full_path[unc_len + cifs_sb->prepathlen] = 0; /* add trailing null */ | 2784 | full_path[unc_len + cifs_sb->prepathlen] = 0; /* add trailing null */ |
2730 | return full_path; | 2785 | return full_path; |
2731 | } | 2786 | } |
2787 | |||
2788 | /* | ||
2789 | * Perform a dfs referral query for a share and (optionally) prefix | ||
2790 | * | ||
2791 | * If a referral is found, cifs_sb->mountdata will be (re-)allocated | ||
2792 | * to a string containing updated options for the submount. Otherwise it | ||
2793 | * will be left untouched. | ||
2794 | * | ||
2795 | * Returns the rc from get_dfs_path to the caller, which can be used to | ||
2796 | * determine whether there were referrals. | ||
2797 | */ | ||
2798 | static int | ||
2799 | expand_dfs_referral(int xid, struct cifsSesInfo *pSesInfo, | ||
2800 | struct smb_vol *volume_info, struct cifs_sb_info *cifs_sb, | ||
2801 | int check_prefix) | ||
2802 | { | ||
2803 | int rc; | ||
2804 | unsigned int num_referrals = 0; | ||
2805 | struct dfs_info3_param *referrals = NULL; | ||
2806 | char *full_path = NULL, *ref_path = NULL, *mdata = NULL; | ||
2807 | |||
2808 | full_path = build_unc_path_to_root(volume_info, cifs_sb); | ||
2809 | if (IS_ERR(full_path)) | ||
2810 | return PTR_ERR(full_path); | ||
2811 | |||
2812 | /* For DFS paths, skip the first '\' of the UNC */ | ||
2813 | ref_path = check_prefix ? full_path + 1 : volume_info->UNC + 1; | ||
2814 | |||
2815 | rc = get_dfs_path(xid, pSesInfo , ref_path, cifs_sb->local_nls, | ||
2816 | &num_referrals, &referrals, | ||
2817 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
2818 | |||
2819 | if (!rc && num_referrals > 0) { | ||
2820 | char *fake_devname = NULL; | ||
2821 | |||
2822 | mdata = cifs_compose_mount_options(cifs_sb->mountdata, | ||
2823 | full_path + 1, referrals, | ||
2824 | &fake_devname); | ||
2825 | |||
2826 | free_dfs_info_array(referrals, num_referrals); | ||
2827 | kfree(fake_devname); | ||
2828 | |||
2829 | if (cifs_sb->mountdata != NULL) | ||
2830 | kfree(cifs_sb->mountdata); | ||
2831 | |||
2832 | if (IS_ERR(mdata)) { | ||
2833 | rc = PTR_ERR(mdata); | ||
2834 | mdata = NULL; | ||
2835 | } | ||
2836 | cifs_sb->mountdata = mdata; | ||
2837 | } | ||
2838 | kfree(full_path); | ||
2839 | return rc; | ||
2840 | } | ||
2732 | #endif | 2841 | #endif |
2733 | 2842 | ||
2734 | int | 2843 | int |
2735 | cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | 2844 | cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, |
2736 | char *mount_data_global, const char *devname) | 2845 | const char *devname) |
2737 | { | 2846 | { |
2738 | int rc; | 2847 | int rc; |
2739 | int xid; | 2848 | int xid; |
@@ -2742,13 +2851,20 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
2742 | struct cifsTconInfo *tcon; | 2851 | struct cifsTconInfo *tcon; |
2743 | struct TCP_Server_Info *srvTcp; | 2852 | struct TCP_Server_Info *srvTcp; |
2744 | char *full_path; | 2853 | char *full_path; |
2745 | char *mount_data = mount_data_global; | ||
2746 | struct tcon_link *tlink; | 2854 | struct tcon_link *tlink; |
2747 | #ifdef CONFIG_CIFS_DFS_UPCALL | 2855 | #ifdef CONFIG_CIFS_DFS_UPCALL |
2748 | struct dfs_info3_param *referrals = NULL; | ||
2749 | unsigned int num_referrals = 0; | ||
2750 | int referral_walks_count = 0; | 2856 | int referral_walks_count = 0; |
2751 | try_mount_again: | 2857 | try_mount_again: |
2858 | /* cleanup activities if we're chasing a referral */ | ||
2859 | if (referral_walks_count) { | ||
2860 | if (tcon) | ||
2861 | cifs_put_tcon(tcon); | ||
2862 | else if (pSesInfo) | ||
2863 | cifs_put_smb_ses(pSesInfo); | ||
2864 | |||
2865 | cleanup_volume_info(&volume_info); | ||
2866 | FreeXid(xid); | ||
2867 | } | ||
2752 | #endif | 2868 | #endif |
2753 | rc = 0; | 2869 | rc = 0; |
2754 | tcon = NULL; | 2870 | tcon = NULL; |
@@ -2765,7 +2881,8 @@ try_mount_again: | |||
2765 | goto out; | 2881 | goto out; |
2766 | } | 2882 | } |
2767 | 2883 | ||
2768 | if (cifs_parse_mount_options(mount_data, devname, volume_info)) { | 2884 | if (cifs_parse_mount_options(cifs_sb->mountdata, devname, |
2885 | volume_info)) { | ||
2769 | rc = -EINVAL; | 2886 | rc = -EINVAL; |
2770 | goto out; | 2887 | goto out; |
2771 | } | 2888 | } |
@@ -2861,6 +2978,24 @@ try_mount_again: | |||
2861 | (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)); | 2978 | (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)); |
2862 | 2979 | ||
2863 | remote_path_check: | 2980 | remote_path_check: |
2981 | #ifdef CONFIG_CIFS_DFS_UPCALL | ||
2982 | /* | ||
2983 | * Perform an unconditional check for whether there are DFS | ||
2984 | * referrals for this path without prefix, to provide support | ||
2985 | * for DFS referrals from w2k8 servers which don't seem to respond | ||
2986 | * with PATH_NOT_COVERED to requests that include the prefix. | ||
2987 | * Chase the referral if found, otherwise continue normally. | ||
2988 | */ | ||
2989 | if (referral_walks_count == 0) { | ||
2990 | int refrc = expand_dfs_referral(xid, pSesInfo, volume_info, | ||
2991 | cifs_sb, false); | ||
2992 | if (!refrc) { | ||
2993 | referral_walks_count++; | ||
2994 | goto try_mount_again; | ||
2995 | } | ||
2996 | } | ||
2997 | #endif | ||
2998 | |||
2864 | /* check if a whole path (including prepath) is not remote */ | 2999 | /* check if a whole path (including prepath) is not remote */ |
2865 | if (!rc && tcon) { | 3000 | if (!rc && tcon) { |
2866 | /* build_path_to_root works only when we have a valid tcon */ | 3001 | /* build_path_to_root works only when we have a valid tcon */ |
@@ -2894,46 +3029,15 @@ remote_path_check: | |||
2894 | if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) == 0) | 3029 | if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) == 0) |
2895 | convert_delimiter(cifs_sb->prepath, | 3030 | convert_delimiter(cifs_sb->prepath, |
2896 | CIFS_DIR_SEP(cifs_sb)); | 3031 | CIFS_DIR_SEP(cifs_sb)); |
2897 | full_path = build_unc_path_to_root(volume_info, cifs_sb); | ||
2898 | if (IS_ERR(full_path)) { | ||
2899 | rc = PTR_ERR(full_path); | ||
2900 | goto mount_fail_check; | ||
2901 | } | ||
2902 | |||
2903 | cFYI(1, "Getting referral for: %s", full_path); | ||
2904 | rc = get_dfs_path(xid, pSesInfo , full_path + 1, | ||
2905 | cifs_sb->local_nls, &num_referrals, &referrals, | ||
2906 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
2907 | if (!rc && num_referrals > 0) { | ||
2908 | char *fake_devname = NULL; | ||
2909 | |||
2910 | if (mount_data != mount_data_global) | ||
2911 | kfree(mount_data); | ||
2912 | 3032 | ||
2913 | mount_data = cifs_compose_mount_options( | 3033 | rc = expand_dfs_referral(xid, pSesInfo, volume_info, cifs_sb, |
2914 | cifs_sb->mountdata, full_path + 1, | 3034 | true); |
2915 | referrals, &fake_devname); | ||
2916 | 3035 | ||
2917 | free_dfs_info_array(referrals, num_referrals); | 3036 | if (!rc) { |
2918 | kfree(fake_devname); | ||
2919 | kfree(full_path); | ||
2920 | |||
2921 | if (IS_ERR(mount_data)) { | ||
2922 | rc = PTR_ERR(mount_data); | ||
2923 | mount_data = NULL; | ||
2924 | goto mount_fail_check; | ||
2925 | } | ||
2926 | |||
2927 | if (tcon) | ||
2928 | cifs_put_tcon(tcon); | ||
2929 | else if (pSesInfo) | ||
2930 | cifs_put_smb_ses(pSesInfo); | ||
2931 | |||
2932 | cleanup_volume_info(&volume_info); | ||
2933 | referral_walks_count++; | 3037 | referral_walks_count++; |
2934 | FreeXid(xid); | ||
2935 | goto try_mount_again; | 3038 | goto try_mount_again; |
2936 | } | 3039 | } |
3040 | goto mount_fail_check; | ||
2937 | #else /* No DFS support, return error on mount */ | 3041 | #else /* No DFS support, return error on mount */ |
2938 | rc = -EOPNOTSUPP; | 3042 | rc = -EOPNOTSUPP; |
2939 | #endif | 3043 | #endif |
@@ -2966,8 +3070,6 @@ remote_path_check: | |||
2966 | mount_fail_check: | 3070 | mount_fail_check: |
2967 | /* on error free sesinfo and tcon struct if needed */ | 3071 | /* on error free sesinfo and tcon struct if needed */ |
2968 | if (rc) { | 3072 | if (rc) { |
2969 | if (mount_data != mount_data_global) | ||
2970 | kfree(mount_data); | ||
2971 | /* If find_unc succeeded then rc == 0 so we can not end */ | 3073 | /* If find_unc succeeded then rc == 0 so we can not end */ |
2972 | /* up accidentally freeing someone elses tcon struct */ | 3074 | /* up accidentally freeing someone elses tcon struct */ |
2973 | if (tcon) | 3075 | if (tcon) |
@@ -3083,7 +3185,8 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, | |||
3083 | bcc_ptr += strlen("?????"); | 3185 | bcc_ptr += strlen("?????"); |
3084 | bcc_ptr += 1; | 3186 | bcc_ptr += 1; |
3085 | count = bcc_ptr - &pSMB->Password[0]; | 3187 | count = bcc_ptr - &pSMB->Password[0]; |
3086 | pSMB->hdr.smb_buf_length += count; | 3188 | pSMB->hdr.smb_buf_length = cpu_to_be32(be32_to_cpu( |
3189 | pSMB->hdr.smb_buf_length) + count); | ||
3087 | pSMB->ByteCount = cpu_to_le16(count); | 3190 | pSMB->ByteCount = cpu_to_le16(count); |
3088 | 3191 | ||
3089 | rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, | 3192 | rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, |
@@ -3258,7 +3361,9 @@ cifs_construct_tcon(struct cifs_sb_info *cifs_sb, uid_t fsuid) | |||
3258 | struct cifsSesInfo *ses; | 3361 | struct cifsSesInfo *ses; |
3259 | struct cifsTconInfo *tcon = NULL; | 3362 | struct cifsTconInfo *tcon = NULL; |
3260 | struct smb_vol *vol_info; | 3363 | struct smb_vol *vol_info; |
3261 | char username[MAX_USERNAME_SIZE + 1]; | 3364 | char username[28]; /* big enough for "krb50x" + hex of ULONG_MAX 6+16 */ |
3365 | /* We used to have this as MAX_USERNAME which is */ | ||
3366 | /* way too big now (256 instead of 32) */ | ||
3262 | 3367 | ||
3263 | vol_info = kzalloc(sizeof(*vol_info), GFP_KERNEL); | 3368 | vol_info = kzalloc(sizeof(*vol_info), GFP_KERNEL); |
3264 | if (vol_info == NULL) { | 3369 | if (vol_info == NULL) { |
diff --git a/fs/cifs/export.c b/fs/cifs/export.c index 993f82045bf6..55d87ac52000 100644 --- a/fs/cifs/export.c +++ b/fs/cifs/export.c | |||
@@ -45,7 +45,7 @@ | |||
45 | #include "cifs_debug.h" | 45 | #include "cifs_debug.h" |
46 | #include "cifsfs.h" | 46 | #include "cifsfs.h" |
47 | 47 | ||
48 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 48 | #ifdef CIFS_NFSD_EXPORT |
49 | static struct dentry *cifs_get_parent(struct dentry *dentry) | 49 | static struct dentry *cifs_get_parent(struct dentry *dentry) |
50 | { | 50 | { |
51 | /* BB need to add code here eventually to enable export via NFSD */ | 51 | /* BB need to add code here eventually to enable export via NFSD */ |
@@ -63,5 +63,5 @@ const struct export_operations cifs_export_ops = { | |||
63 | .encode_fs = */ | 63 | .encode_fs = */ |
64 | }; | 64 | }; |
65 | 65 | ||
66 | #endif /* EXPERIMENTAL */ | 66 | #endif /* CIFS_NFSD_EXPORT */ |
67 | 67 | ||
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index faf59529e847..c672afef0c09 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -857,95 +857,6 @@ cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset, | |||
857 | cifsi->server_eof = end_of_write; | 857 | cifsi->server_eof = end_of_write; |
858 | } | 858 | } |
859 | 859 | ||
860 | ssize_t cifs_user_write(struct file *file, const char __user *write_data, | ||
861 | size_t write_size, loff_t *poffset) | ||
862 | { | ||
863 | struct inode *inode = file->f_path.dentry->d_inode; | ||
864 | int rc = 0; | ||
865 | unsigned int bytes_written = 0; | ||
866 | unsigned int total_written; | ||
867 | struct cifs_sb_info *cifs_sb; | ||
868 | struct cifsTconInfo *pTcon; | ||
869 | int xid; | ||
870 | struct cifsFileInfo *open_file; | ||
871 | struct cifsInodeInfo *cifsi = CIFS_I(inode); | ||
872 | |||
873 | cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); | ||
874 | |||
875 | /* cFYI(1, " write %d bytes to offset %lld of %s", write_size, | ||
876 | *poffset, file->f_path.dentry->d_name.name); */ | ||
877 | |||
878 | if (file->private_data == NULL) | ||
879 | return -EBADF; | ||
880 | |||
881 | open_file = file->private_data; | ||
882 | pTcon = tlink_tcon(open_file->tlink); | ||
883 | |||
884 | rc = generic_write_checks(file, poffset, &write_size, 0); | ||
885 | if (rc) | ||
886 | return rc; | ||
887 | |||
888 | xid = GetXid(); | ||
889 | |||
890 | for (total_written = 0; write_size > total_written; | ||
891 | total_written += bytes_written) { | ||
892 | rc = -EAGAIN; | ||
893 | while (rc == -EAGAIN) { | ||
894 | if (file->private_data == NULL) { | ||
895 | /* file has been closed on us */ | ||
896 | FreeXid(xid); | ||
897 | /* if we have gotten here we have written some data | ||
898 | and blocked, and the file has been freed on us while | ||
899 | we blocked so return what we managed to write */ | ||
900 | return total_written; | ||
901 | } | ||
902 | if (open_file->invalidHandle) { | ||
903 | /* we could deadlock if we called | ||
904 | filemap_fdatawait from here so tell | ||
905 | reopen_file not to flush data to server | ||
906 | now */ | ||
907 | rc = cifs_reopen_file(open_file, false); | ||
908 | if (rc != 0) | ||
909 | break; | ||
910 | } | ||
911 | |||
912 | rc = CIFSSMBWrite(xid, pTcon, | ||
913 | open_file->netfid, | ||
914 | min_t(const int, cifs_sb->wsize, | ||
915 | write_size - total_written), | ||
916 | *poffset, &bytes_written, | ||
917 | NULL, write_data + total_written, 0); | ||
918 | } | ||
919 | if (rc || (bytes_written == 0)) { | ||
920 | if (total_written) | ||
921 | break; | ||
922 | else { | ||
923 | FreeXid(xid); | ||
924 | return rc; | ||
925 | } | ||
926 | } else { | ||
927 | cifs_update_eof(cifsi, *poffset, bytes_written); | ||
928 | *poffset += bytes_written; | ||
929 | } | ||
930 | } | ||
931 | |||
932 | cifs_stats_bytes_written(pTcon, total_written); | ||
933 | |||
934 | /* Do not update local mtime - server will set its actual value on write | ||
935 | * inode->i_ctime = inode->i_mtime = | ||
936 | * current_fs_time(inode->i_sb);*/ | ||
937 | if (total_written > 0) { | ||
938 | spin_lock(&inode->i_lock); | ||
939 | if (*poffset > inode->i_size) | ||
940 | i_size_write(inode, *poffset); | ||
941 | spin_unlock(&inode->i_lock); | ||
942 | } | ||
943 | mark_inode_dirty_sync(inode); | ||
944 | |||
945 | FreeXid(xid); | ||
946 | return total_written; | ||
947 | } | ||
948 | |||
949 | static ssize_t cifs_write(struct cifsFileInfo *open_file, | 860 | static ssize_t cifs_write(struct cifsFileInfo *open_file, |
950 | const char *write_data, size_t write_size, | 861 | const char *write_data, size_t write_size, |
951 | loff_t *poffset) | 862 | loff_t *poffset) |
@@ -1420,9 +1331,10 @@ retry_write: | |||
1420 | return rc; | 1331 | return rc; |
1421 | } | 1332 | } |
1422 | 1333 | ||
1423 | static int cifs_writepage(struct page *page, struct writeback_control *wbc) | 1334 | static int |
1335 | cifs_writepage_locked(struct page *page, struct writeback_control *wbc) | ||
1424 | { | 1336 | { |
1425 | int rc = -EFAULT; | 1337 | int rc; |
1426 | int xid; | 1338 | int xid; |
1427 | 1339 | ||
1428 | xid = GetXid(); | 1340 | xid = GetXid(); |
@@ -1442,15 +1354,29 @@ static int cifs_writepage(struct page *page, struct writeback_control *wbc) | |||
1442 | * to fail to update with the state of the page correctly. | 1354 | * to fail to update with the state of the page correctly. |
1443 | */ | 1355 | */ |
1444 | set_page_writeback(page); | 1356 | set_page_writeback(page); |
1357 | retry_write: | ||
1445 | rc = cifs_partialpagewrite(page, 0, PAGE_CACHE_SIZE); | 1358 | rc = cifs_partialpagewrite(page, 0, PAGE_CACHE_SIZE); |
1446 | SetPageUptodate(page); /* BB add check for error and Clearuptodate? */ | 1359 | if (rc == -EAGAIN && wbc->sync_mode == WB_SYNC_ALL) |
1447 | unlock_page(page); | 1360 | goto retry_write; |
1361 | else if (rc == -EAGAIN) | ||
1362 | redirty_page_for_writepage(wbc, page); | ||
1363 | else if (rc != 0) | ||
1364 | SetPageError(page); | ||
1365 | else | ||
1366 | SetPageUptodate(page); | ||
1448 | end_page_writeback(page); | 1367 | end_page_writeback(page); |
1449 | page_cache_release(page); | 1368 | page_cache_release(page); |
1450 | FreeXid(xid); | 1369 | FreeXid(xid); |
1451 | return rc; | 1370 | return rc; |
1452 | } | 1371 | } |
1453 | 1372 | ||
1373 | static int cifs_writepage(struct page *page, struct writeback_control *wbc) | ||
1374 | { | ||
1375 | int rc = cifs_writepage_locked(page, wbc); | ||
1376 | unlock_page(page); | ||
1377 | return rc; | ||
1378 | } | ||
1379 | |||
1454 | static int cifs_write_end(struct file *file, struct address_space *mapping, | 1380 | static int cifs_write_end(struct file *file, struct address_space *mapping, |
1455 | loff_t pos, unsigned len, unsigned copied, | 1381 | loff_t pos, unsigned len, unsigned copied, |
1456 | struct page *page, void *fsdata) | 1382 | struct page *page, void *fsdata) |
@@ -1519,8 +1445,13 @@ int cifs_strict_fsync(struct file *file, int datasync) | |||
1519 | cFYI(1, "Sync file - name: %s datasync: 0x%x", | 1445 | cFYI(1, "Sync file - name: %s datasync: 0x%x", |
1520 | file->f_path.dentry->d_name.name, datasync); | 1446 | file->f_path.dentry->d_name.name, datasync); |
1521 | 1447 | ||
1522 | if (!CIFS_I(inode)->clientCanCacheRead) | 1448 | if (!CIFS_I(inode)->clientCanCacheRead) { |
1523 | cifs_invalidate_mapping(inode); | 1449 | rc = cifs_invalidate_mapping(inode); |
1450 | if (rc) { | ||
1451 | cFYI(1, "rc: %d during invalidate phase", rc); | ||
1452 | rc = 0; /* don't care about it in fsync */ | ||
1453 | } | ||
1454 | } | ||
1524 | 1455 | ||
1525 | tcon = tlink_tcon(smbfile->tlink); | 1456 | tcon = tlink_tcon(smbfile->tlink); |
1526 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) | 1457 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) |
@@ -1726,7 +1657,7 @@ cifs_iovec_write(struct file *file, const struct iovec *iov, | |||
1726 | return total_written; | 1657 | return total_written; |
1727 | } | 1658 | } |
1728 | 1659 | ||
1729 | static ssize_t cifs_user_writev(struct kiocb *iocb, const struct iovec *iov, | 1660 | ssize_t cifs_user_writev(struct kiocb *iocb, const struct iovec *iov, |
1730 | unsigned long nr_segs, loff_t pos) | 1661 | unsigned long nr_segs, loff_t pos) |
1731 | { | 1662 | { |
1732 | ssize_t written; | 1663 | ssize_t written; |
@@ -1849,17 +1780,7 @@ cifs_iovec_read(struct file *file, const struct iovec *iov, | |||
1849 | return total_read; | 1780 | return total_read; |
1850 | } | 1781 | } |
1851 | 1782 | ||
1852 | ssize_t cifs_user_read(struct file *file, char __user *read_data, | 1783 | ssize_t cifs_user_readv(struct kiocb *iocb, const struct iovec *iov, |
1853 | size_t read_size, loff_t *poffset) | ||
1854 | { | ||
1855 | struct iovec iov; | ||
1856 | iov.iov_base = read_data; | ||
1857 | iov.iov_len = read_size; | ||
1858 | |||
1859 | return cifs_iovec_read(file, &iov, 1, poffset); | ||
1860 | } | ||
1861 | |||
1862 | static ssize_t cifs_user_readv(struct kiocb *iocb, const struct iovec *iov, | ||
1863 | unsigned long nr_segs, loff_t pos) | 1784 | unsigned long nr_segs, loff_t pos) |
1864 | { | 1785 | { |
1865 | ssize_t read; | 1786 | ssize_t read; |
@@ -1987,8 +1908,11 @@ int cifs_file_strict_mmap(struct file *file, struct vm_area_struct *vma) | |||
1987 | 1908 | ||
1988 | xid = GetXid(); | 1909 | xid = GetXid(); |
1989 | 1910 | ||
1990 | if (!CIFS_I(inode)->clientCanCacheRead) | 1911 | if (!CIFS_I(inode)->clientCanCacheRead) { |
1991 | cifs_invalidate_mapping(inode); | 1912 | rc = cifs_invalidate_mapping(inode); |
1913 | if (rc) | ||
1914 | return rc; | ||
1915 | } | ||
1992 | 1916 | ||
1993 | rc = generic_file_mmap(file, vma); | 1917 | rc = generic_file_mmap(file, vma); |
1994 | if (rc == 0) | 1918 | if (rc == 0) |
@@ -2415,6 +2339,27 @@ static void cifs_invalidate_page(struct page *page, unsigned long offset) | |||
2415 | cifs_fscache_invalidate_page(page, &cifsi->vfs_inode); | 2339 | cifs_fscache_invalidate_page(page, &cifsi->vfs_inode); |
2416 | } | 2340 | } |
2417 | 2341 | ||
2342 | static int cifs_launder_page(struct page *page) | ||
2343 | { | ||
2344 | int rc = 0; | ||
2345 | loff_t range_start = page_offset(page); | ||
2346 | loff_t range_end = range_start + (loff_t)(PAGE_CACHE_SIZE - 1); | ||
2347 | struct writeback_control wbc = { | ||
2348 | .sync_mode = WB_SYNC_ALL, | ||
2349 | .nr_to_write = 0, | ||
2350 | .range_start = range_start, | ||
2351 | .range_end = range_end, | ||
2352 | }; | ||
2353 | |||
2354 | cFYI(1, "Launder page: %p", page); | ||
2355 | |||
2356 | if (clear_page_dirty_for_io(page)) | ||
2357 | rc = cifs_writepage_locked(page, &wbc); | ||
2358 | |||
2359 | cifs_fscache_invalidate_page(page, page->mapping->host); | ||
2360 | return rc; | ||
2361 | } | ||
2362 | |||
2418 | void cifs_oplock_break(struct work_struct *work) | 2363 | void cifs_oplock_break(struct work_struct *work) |
2419 | { | 2364 | { |
2420 | struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo, | 2365 | struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo, |
@@ -2486,7 +2431,7 @@ const struct address_space_operations cifs_addr_ops = { | |||
2486 | .set_page_dirty = __set_page_dirty_nobuffers, | 2431 | .set_page_dirty = __set_page_dirty_nobuffers, |
2487 | .releasepage = cifs_release_page, | 2432 | .releasepage = cifs_release_page, |
2488 | .invalidatepage = cifs_invalidate_page, | 2433 | .invalidatepage = cifs_invalidate_page, |
2489 | /* .direct_IO = */ | 2434 | .launder_page = cifs_launder_page, |
2490 | }; | 2435 | }; |
2491 | 2436 | ||
2492 | /* | 2437 | /* |
@@ -2503,5 +2448,5 @@ const struct address_space_operations cifs_addr_ops_smallbuf = { | |||
2503 | .set_page_dirty = __set_page_dirty_nobuffers, | 2448 | .set_page_dirty = __set_page_dirty_nobuffers, |
2504 | .releasepage = cifs_release_page, | 2449 | .releasepage = cifs_release_page, |
2505 | .invalidatepage = cifs_invalidate_page, | 2450 | .invalidatepage = cifs_invalidate_page, |
2506 | /* .direct_IO = */ | 2451 | .launder_page = cifs_launder_page, |
2507 | }; | 2452 | }; |
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 8852470b4fbb..de02ed5e25c2 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -878,7 +878,7 @@ retry_iget5_locked: | |||
878 | } | 878 | } |
879 | 879 | ||
880 | /* gets root inode */ | 880 | /* gets root inode */ |
881 | struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino) | 881 | struct inode *cifs_root_iget(struct super_block *sb) |
882 | { | 882 | { |
883 | int xid; | 883 | int xid; |
884 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); | 884 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); |
@@ -1683,71 +1683,70 @@ cifs_inode_needs_reval(struct inode *inode) | |||
1683 | /* | 1683 | /* |
1684 | * Zap the cache. Called when invalid_mapping flag is set. | 1684 | * Zap the cache. Called when invalid_mapping flag is set. |
1685 | */ | 1685 | */ |
1686 | void | 1686 | int |
1687 | cifs_invalidate_mapping(struct inode *inode) | 1687 | cifs_invalidate_mapping(struct inode *inode) |
1688 | { | 1688 | { |
1689 | int rc; | 1689 | int rc = 0; |
1690 | struct cifsInodeInfo *cifs_i = CIFS_I(inode); | 1690 | struct cifsInodeInfo *cifs_i = CIFS_I(inode); |
1691 | 1691 | ||
1692 | cifs_i->invalid_mapping = false; | 1692 | cifs_i->invalid_mapping = false; |
1693 | 1693 | ||
1694 | /* write back any cached data */ | ||
1695 | if (inode->i_mapping && inode->i_mapping->nrpages != 0) { | 1694 | if (inode->i_mapping && inode->i_mapping->nrpages != 0) { |
1696 | rc = filemap_write_and_wait(inode->i_mapping); | 1695 | rc = invalidate_inode_pages2(inode->i_mapping); |
1697 | mapping_set_error(inode->i_mapping, rc); | 1696 | if (rc) { |
1697 | cERROR(1, "%s: could not invalidate inode %p", __func__, | ||
1698 | inode); | ||
1699 | cifs_i->invalid_mapping = true; | ||
1700 | } | ||
1698 | } | 1701 | } |
1699 | invalidate_remote_inode(inode); | 1702 | |
1700 | cifs_fscache_reset_inode_cookie(inode); | 1703 | cifs_fscache_reset_inode_cookie(inode); |
1704 | return rc; | ||
1701 | } | 1705 | } |
1702 | 1706 | ||
1703 | int cifs_revalidate_file(struct file *filp) | 1707 | int cifs_revalidate_file_attr(struct file *filp) |
1704 | { | 1708 | { |
1705 | int rc = 0; | 1709 | int rc = 0; |
1706 | struct inode *inode = filp->f_path.dentry->d_inode; | 1710 | struct inode *inode = filp->f_path.dentry->d_inode; |
1707 | struct cifsFileInfo *cfile = (struct cifsFileInfo *) filp->private_data; | 1711 | struct cifsFileInfo *cfile = (struct cifsFileInfo *) filp->private_data; |
1708 | 1712 | ||
1709 | if (!cifs_inode_needs_reval(inode)) | 1713 | if (!cifs_inode_needs_reval(inode)) |
1710 | goto check_inval; | 1714 | return rc; |
1711 | 1715 | ||
1712 | if (tlink_tcon(cfile->tlink)->unix_ext) | 1716 | if (tlink_tcon(cfile->tlink)->unix_ext) |
1713 | rc = cifs_get_file_info_unix(filp); | 1717 | rc = cifs_get_file_info_unix(filp); |
1714 | else | 1718 | else |
1715 | rc = cifs_get_file_info(filp); | 1719 | rc = cifs_get_file_info(filp); |
1716 | 1720 | ||
1717 | check_inval: | ||
1718 | if (CIFS_I(inode)->invalid_mapping) | ||
1719 | cifs_invalidate_mapping(inode); | ||
1720 | |||
1721 | return rc; | 1721 | return rc; |
1722 | } | 1722 | } |
1723 | 1723 | ||
1724 | /* revalidate a dentry's inode attributes */ | 1724 | int cifs_revalidate_dentry_attr(struct dentry *dentry) |
1725 | int cifs_revalidate_dentry(struct dentry *dentry) | ||
1726 | { | 1725 | { |
1727 | int xid; | 1726 | int xid; |
1728 | int rc = 0; | 1727 | int rc = 0; |
1729 | char *full_path = NULL; | ||
1730 | struct inode *inode = dentry->d_inode; | 1728 | struct inode *inode = dentry->d_inode; |
1731 | struct super_block *sb = dentry->d_sb; | 1729 | struct super_block *sb = dentry->d_sb; |
1730 | char *full_path = NULL; | ||
1732 | 1731 | ||
1733 | if (inode == NULL) | 1732 | if (inode == NULL) |
1734 | return -ENOENT; | 1733 | return -ENOENT; |
1735 | 1734 | ||
1736 | xid = GetXid(); | ||
1737 | |||
1738 | if (!cifs_inode_needs_reval(inode)) | 1735 | if (!cifs_inode_needs_reval(inode)) |
1739 | goto check_inval; | 1736 | return rc; |
1737 | |||
1738 | xid = GetXid(); | ||
1740 | 1739 | ||
1741 | /* can not safely grab the rename sem here if rename calls revalidate | 1740 | /* can not safely grab the rename sem here if rename calls revalidate |
1742 | since that would deadlock */ | 1741 | since that would deadlock */ |
1743 | full_path = build_path_from_dentry(dentry); | 1742 | full_path = build_path_from_dentry(dentry); |
1744 | if (full_path == NULL) { | 1743 | if (full_path == NULL) { |
1745 | rc = -ENOMEM; | 1744 | rc = -ENOMEM; |
1746 | goto check_inval; | 1745 | goto out; |
1747 | } | 1746 | } |
1748 | 1747 | ||
1749 | cFYI(1, "Revalidate: %s inode 0x%p count %d dentry: 0x%p d_time %ld " | 1748 | cFYI(1, "Update attributes: %s inode 0x%p count %d dentry: 0x%p d_time " |
1750 | "jiffies %ld", full_path, inode, inode->i_count.counter, | 1749 | "%ld jiffies %ld", full_path, inode, inode->i_count.counter, |
1751 | dentry, dentry->d_time, jiffies); | 1750 | dentry, dentry->d_time, jiffies); |
1752 | 1751 | ||
1753 | if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext) | 1752 | if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext) |
@@ -1756,41 +1755,83 @@ int cifs_revalidate_dentry(struct dentry *dentry) | |||
1756 | rc = cifs_get_inode_info(&inode, full_path, NULL, sb, | 1755 | rc = cifs_get_inode_info(&inode, full_path, NULL, sb, |
1757 | xid, NULL); | 1756 | xid, NULL); |
1758 | 1757 | ||
1759 | check_inval: | 1758 | out: |
1760 | if (CIFS_I(inode)->invalid_mapping) | ||
1761 | cifs_invalidate_mapping(inode); | ||
1762 | |||
1763 | kfree(full_path); | 1759 | kfree(full_path); |
1764 | FreeXid(xid); | 1760 | FreeXid(xid); |
1765 | return rc; | 1761 | return rc; |
1766 | } | 1762 | } |
1767 | 1763 | ||
1764 | int cifs_revalidate_file(struct file *filp) | ||
1765 | { | ||
1766 | int rc; | ||
1767 | struct inode *inode = filp->f_path.dentry->d_inode; | ||
1768 | |||
1769 | rc = cifs_revalidate_file_attr(filp); | ||
1770 | if (rc) | ||
1771 | return rc; | ||
1772 | |||
1773 | if (CIFS_I(inode)->invalid_mapping) | ||
1774 | rc = cifs_invalidate_mapping(inode); | ||
1775 | return rc; | ||
1776 | } | ||
1777 | |||
1778 | /* revalidate a dentry's inode attributes */ | ||
1779 | int cifs_revalidate_dentry(struct dentry *dentry) | ||
1780 | { | ||
1781 | int rc; | ||
1782 | struct inode *inode = dentry->d_inode; | ||
1783 | |||
1784 | rc = cifs_revalidate_dentry_attr(dentry); | ||
1785 | if (rc) | ||
1786 | return rc; | ||
1787 | |||
1788 | if (CIFS_I(inode)->invalid_mapping) | ||
1789 | rc = cifs_invalidate_mapping(inode); | ||
1790 | return rc; | ||
1791 | } | ||
1792 | |||
1768 | int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry, | 1793 | int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry, |
1769 | struct kstat *stat) | 1794 | struct kstat *stat) |
1770 | { | 1795 | { |
1771 | struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb); | 1796 | struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb); |
1772 | struct cifsTconInfo *tcon = cifs_sb_master_tcon(cifs_sb); | 1797 | struct cifsTconInfo *tcon = cifs_sb_master_tcon(cifs_sb); |
1773 | int err = cifs_revalidate_dentry(dentry); | 1798 | struct inode *inode = dentry->d_inode; |
1774 | 1799 | int rc; | |
1775 | if (!err) { | ||
1776 | generic_fillattr(dentry->d_inode, stat); | ||
1777 | stat->blksize = CIFS_MAX_MSGSIZE; | ||
1778 | stat->ino = CIFS_I(dentry->d_inode)->uniqueid; | ||
1779 | 1800 | ||
1780 | /* | 1801 | /* |
1781 | * If on a multiuser mount without unix extensions, and the | 1802 | * We need to be sure that all dirty pages are written and the server |
1782 | * admin hasn't overridden them, set the ownership to the | 1803 | * has actual ctime, mtime and file length. |
1783 | * fsuid/fsgid of the current process. | 1804 | */ |
1784 | */ | 1805 | if (!CIFS_I(inode)->clientCanCacheRead && inode->i_mapping && |
1785 | if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER) && | 1806 | inode->i_mapping->nrpages != 0) { |
1786 | !tcon->unix_ext) { | 1807 | rc = filemap_fdatawait(inode->i_mapping); |
1787 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)) | 1808 | if (rc) { |
1788 | stat->uid = current_fsuid(); | 1809 | mapping_set_error(inode->i_mapping, rc); |
1789 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)) | 1810 | return rc; |
1790 | stat->gid = current_fsgid(); | ||
1791 | } | 1811 | } |
1792 | } | 1812 | } |
1793 | return err; | 1813 | |
1814 | rc = cifs_revalidate_dentry_attr(dentry); | ||
1815 | if (rc) | ||
1816 | return rc; | ||
1817 | |||
1818 | generic_fillattr(inode, stat); | ||
1819 | stat->blksize = CIFS_MAX_MSGSIZE; | ||
1820 | stat->ino = CIFS_I(inode)->uniqueid; | ||
1821 | |||
1822 | /* | ||
1823 | * If on a multiuser mount without unix extensions, and the admin hasn't | ||
1824 | * overridden them, set the ownership to the fsuid/fsgid of the current | ||
1825 | * process. | ||
1826 | */ | ||
1827 | if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER) && | ||
1828 | !tcon->unix_ext) { | ||
1829 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)) | ||
1830 | stat->uid = current_fsuid(); | ||
1831 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)) | ||
1832 | stat->gid = current_fsgid(); | ||
1833 | } | ||
1834 | return rc; | ||
1794 | } | 1835 | } |
1795 | 1836 | ||
1796 | static int cifs_truncate_page(struct address_space *mapping, loff_t from) | 1837 | static int cifs_truncate_page(struct address_space *mapping, loff_t from) |
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index 0c684ae4c071..907531ac5888 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c | |||
@@ -304,12 +304,10 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ , | |||
304 | 304 | ||
305 | memset(temp, 0, 256); /* bigger than MAX_CIFS_HDR_SIZE */ | 305 | memset(temp, 0, 256); /* bigger than MAX_CIFS_HDR_SIZE */ |
306 | 306 | ||
307 | buffer->smb_buf_length = | 307 | buffer->smb_buf_length = cpu_to_be32( |
308 | (2 * word_count) + sizeof(struct smb_hdr) - | 308 | (2 * word_count) + sizeof(struct smb_hdr) - |
309 | 4 /* RFC 1001 length field does not count */ + | 309 | 4 /* RFC 1001 length field does not count */ + |
310 | 2 /* for bcc field itself */ ; | 310 | 2 /* for bcc field itself */) ; |
311 | /* Note that this is the only network field that has to be converted | ||
312 | to big endian and it is done just before we send it */ | ||
313 | 311 | ||
314 | buffer->Protocol[0] = 0xFF; | 312 | buffer->Protocol[0] = 0xFF; |
315 | buffer->Protocol[1] = 'S'; | 313 | buffer->Protocol[1] = 'S'; |
@@ -424,7 +422,7 @@ check_smb_hdr(struct smb_hdr *smb, __u16 mid) | |||
424 | int | 422 | int |
425 | checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length) | 423 | checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length) |
426 | { | 424 | { |
427 | __u32 len = smb->smb_buf_length; | 425 | __u32 len = be32_to_cpu(smb->smb_buf_length); |
428 | __u32 clc_len; /* calculated length */ | 426 | __u32 clc_len; /* calculated length */ |
429 | cFYI(0, "checkSMB Length: 0x%x, smb_buf_length: 0x%x", length, len); | 427 | cFYI(0, "checkSMB Length: 0x%x, smb_buf_length: 0x%x", length, len); |
430 | 428 | ||
@@ -464,7 +462,7 @@ checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length) | |||
464 | 462 | ||
465 | if (check_smb_hdr(smb, mid)) | 463 | if (check_smb_hdr(smb, mid)) |
466 | return 1; | 464 | return 1; |
467 | clc_len = smbCalcSize_LE(smb); | 465 | clc_len = smbCalcSize(smb); |
468 | 466 | ||
469 | if (4 + len != length) { | 467 | if (4 + len != length) { |
470 | cERROR(1, "Length read does not match RFC1001 length %d", | 468 | cERROR(1, "Length read does not match RFC1001 length %d", |
@@ -521,7 +519,7 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv) | |||
521 | (struct smb_com_transaction_change_notify_rsp *)buf; | 519 | (struct smb_com_transaction_change_notify_rsp *)buf; |
522 | struct file_notify_information *pnotify; | 520 | struct file_notify_information *pnotify; |
523 | __u32 data_offset = 0; | 521 | __u32 data_offset = 0; |
524 | if (get_bcc_le(buf) > sizeof(struct file_notify_information)) { | 522 | if (get_bcc(buf) > sizeof(struct file_notify_information)) { |
525 | data_offset = le32_to_cpu(pSMBr->DataOffset); | 523 | data_offset = le32_to_cpu(pSMBr->DataOffset); |
526 | 524 | ||
527 | pnotify = (struct file_notify_information *) | 525 | pnotify = (struct file_notify_information *) |
diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c index 79f641eeda30..79b71c2c7c9d 100644 --- a/fs/cifs/netmisc.c +++ b/fs/cifs/netmisc.c | |||
@@ -919,13 +919,6 @@ smbCalcSize(struct smb_hdr *ptr) | |||
919 | 2 /* size of the bcc field */ + get_bcc(ptr)); | 919 | 2 /* size of the bcc field */ + get_bcc(ptr)); |
920 | } | 920 | } |
921 | 921 | ||
922 | unsigned int | ||
923 | smbCalcSize_LE(struct smb_hdr *ptr) | ||
924 | { | ||
925 | return (sizeof(struct smb_hdr) + (2 * ptr->WordCount) + | ||
926 | 2 /* size of the bcc field */ + get_bcc_le(ptr)); | ||
927 | } | ||
928 | |||
929 | /* The following are taken from fs/ntfs/util.c */ | 922 | /* The following are taken from fs/ntfs/util.c */ |
930 | 923 | ||
931 | #define NTFS_TIME_OFFSET ((u64)(369*365 + 89) * 24 * 3600 * 10000000) | 924 | #define NTFS_TIME_OFFSET ((u64)(369*365 + 89) * 24 * 3600 * 10000000) |
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c index 645114ad0a10..7dd462100378 100644 --- a/fs/cifs/sess.c +++ b/fs/cifs/sess.c | |||
@@ -621,7 +621,7 @@ ssetup_ntlmssp_authenticate: | |||
621 | and rest of bcc area. This allows us to avoid | 621 | and rest of bcc area. This allows us to avoid |
622 | a large buffer 17K allocation */ | 622 | a large buffer 17K allocation */ |
623 | iov[0].iov_base = (char *)pSMB; | 623 | iov[0].iov_base = (char *)pSMB; |
624 | iov[0].iov_len = smb_buf->smb_buf_length + 4; | 624 | iov[0].iov_len = be32_to_cpu(smb_buf->smb_buf_length) + 4; |
625 | 625 | ||
626 | /* setting this here allows the code at the end of the function | 626 | /* setting this here allows the code at the end of the function |
627 | to free the request buffer if there's an error */ | 627 | to free the request buffer if there's an error */ |
@@ -656,7 +656,7 @@ ssetup_ntlmssp_authenticate: | |||
656 | * to use challenge/response method (i.e. Password bit is 1). | 656 | * to use challenge/response method (i.e. Password bit is 1). |
657 | */ | 657 | */ |
658 | 658 | ||
659 | calc_lanman_hash(ses->password, ses->server->cryptkey, | 659 | rc = calc_lanman_hash(ses->password, ses->server->cryptkey, |
660 | ses->server->secMode & SECMODE_PW_ENCRYPT ? | 660 | ses->server->secMode & SECMODE_PW_ENCRYPT ? |
661 | true : false, lnm_session_key); | 661 | true : false, lnm_session_key); |
662 | 662 | ||
@@ -859,9 +859,10 @@ ssetup_ntlmssp_authenticate: | |||
859 | iov[2].iov_len = (long) bcc_ptr - (long) str_area; | 859 | iov[2].iov_len = (long) bcc_ptr - (long) str_area; |
860 | 860 | ||
861 | count = iov[1].iov_len + iov[2].iov_len; | 861 | count = iov[1].iov_len + iov[2].iov_len; |
862 | smb_buf->smb_buf_length += count; | 862 | smb_buf->smb_buf_length = |
863 | cpu_to_be32(be32_to_cpu(smb_buf->smb_buf_length) + count); | ||
863 | 864 | ||
864 | put_bcc_le(count, smb_buf); | 865 | put_bcc(count, smb_buf); |
865 | 866 | ||
866 | rc = SendReceive2(xid, ses, iov, 3 /* num_iovecs */, &resp_buf_type, | 867 | rc = SendReceive2(xid, ses, iov, 3 /* num_iovecs */, &resp_buf_type, |
867 | CIFS_LOG_ERROR); | 868 | CIFS_LOG_ERROR); |
diff --git a/fs/cifs/smbdes.c b/fs/cifs/smbdes.c deleted file mode 100644 index 04721485925d..000000000000 --- a/fs/cifs/smbdes.c +++ /dev/null | |||
@@ -1,418 +0,0 @@ | |||
1 | /* | ||
2 | Unix SMB/Netbios implementation. | ||
3 | Version 1.9. | ||
4 | |||
5 | a partial implementation of DES designed for use in the | ||
6 | SMB authentication protocol | ||
7 | |||
8 | Copyright (C) Andrew Tridgell 1998 | ||
9 | Modified by Steve French (sfrench@us.ibm.com) 2002,2004 | ||
10 | |||
11 | This program is free software; you can redistribute it and/or modify | ||
12 | it under the terms of the GNU General Public License as published by | ||
13 | the Free Software Foundation; either version 2 of the License, or | ||
14 | (at your option) any later version. | ||
15 | |||
16 | This program is distributed in the hope that it will be useful, | ||
17 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
19 | GNU General Public License for more details. | ||
20 | |||
21 | You should have received a copy of the GNU General Public License | ||
22 | along with this program; if not, write to the Free Software | ||
23 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
24 | */ | ||
25 | |||
26 | /* NOTES: | ||
27 | |||
28 | This code makes no attempt to be fast! In fact, it is a very | ||
29 | slow implementation | ||
30 | |||
31 | This code is NOT a complete DES implementation. It implements only | ||
32 | the minimum necessary for SMB authentication, as used by all SMB | ||
33 | products (including every copy of Microsoft Windows95 ever sold) | ||
34 | |||
35 | In particular, it can only do a unchained forward DES pass. This | ||
36 | means it is not possible to use this code for encryption/decryption | ||
37 | of data, instead it is only useful as a "hash" algorithm. | ||
38 | |||
39 | There is no entry point into this code that allows normal DES operation. | ||
40 | |||
41 | I believe this means that this code does not come under ITAR | ||
42 | regulations but this is NOT a legal opinion. If you are concerned | ||
43 | about the applicability of ITAR regulations to this code then you | ||
44 | should confirm it for yourself (and maybe let me know if you come | ||
45 | up with a different answer to the one above) | ||
46 | */ | ||
47 | #include <linux/slab.h> | ||
48 | #define uchar unsigned char | ||
49 | |||
50 | static uchar perm1[56] = { 57, 49, 41, 33, 25, 17, 9, | ||
51 | 1, 58, 50, 42, 34, 26, 18, | ||
52 | 10, 2, 59, 51, 43, 35, 27, | ||
53 | 19, 11, 3, 60, 52, 44, 36, | ||
54 | 63, 55, 47, 39, 31, 23, 15, | ||
55 | 7, 62, 54, 46, 38, 30, 22, | ||
56 | 14, 6, 61, 53, 45, 37, 29, | ||
57 | 21, 13, 5, 28, 20, 12, 4 | ||
58 | }; | ||
59 | |||
60 | static uchar perm2[48] = { 14, 17, 11, 24, 1, 5, | ||
61 | 3, 28, 15, 6, 21, 10, | ||
62 | 23, 19, 12, 4, 26, 8, | ||
63 | 16, 7, 27, 20, 13, 2, | ||
64 | 41, 52, 31, 37, 47, 55, | ||
65 | 30, 40, 51, 45, 33, 48, | ||
66 | 44, 49, 39, 56, 34, 53, | ||
67 | 46, 42, 50, 36, 29, 32 | ||
68 | }; | ||
69 | |||
70 | static uchar perm3[64] = { 58, 50, 42, 34, 26, 18, 10, 2, | ||
71 | 60, 52, 44, 36, 28, 20, 12, 4, | ||
72 | 62, 54, 46, 38, 30, 22, 14, 6, | ||
73 | 64, 56, 48, 40, 32, 24, 16, 8, | ||
74 | 57, 49, 41, 33, 25, 17, 9, 1, | ||
75 | 59, 51, 43, 35, 27, 19, 11, 3, | ||
76 | 61, 53, 45, 37, 29, 21, 13, 5, | ||
77 | 63, 55, 47, 39, 31, 23, 15, 7 | ||
78 | }; | ||
79 | |||
80 | static uchar perm4[48] = { 32, 1, 2, 3, 4, 5, | ||
81 | 4, 5, 6, 7, 8, 9, | ||
82 | 8, 9, 10, 11, 12, 13, | ||
83 | 12, 13, 14, 15, 16, 17, | ||
84 | 16, 17, 18, 19, 20, 21, | ||
85 | 20, 21, 22, 23, 24, 25, | ||
86 | 24, 25, 26, 27, 28, 29, | ||
87 | 28, 29, 30, 31, 32, 1 | ||
88 | }; | ||
89 | |||
90 | static uchar perm5[32] = { 16, 7, 20, 21, | ||
91 | 29, 12, 28, 17, | ||
92 | 1, 15, 23, 26, | ||
93 | 5, 18, 31, 10, | ||
94 | 2, 8, 24, 14, | ||
95 | 32, 27, 3, 9, | ||
96 | 19, 13, 30, 6, | ||
97 | 22, 11, 4, 25 | ||
98 | }; | ||
99 | |||
100 | static uchar perm6[64] = { 40, 8, 48, 16, 56, 24, 64, 32, | ||
101 | 39, 7, 47, 15, 55, 23, 63, 31, | ||
102 | 38, 6, 46, 14, 54, 22, 62, 30, | ||
103 | 37, 5, 45, 13, 53, 21, 61, 29, | ||
104 | 36, 4, 44, 12, 52, 20, 60, 28, | ||
105 | 35, 3, 43, 11, 51, 19, 59, 27, | ||
106 | 34, 2, 42, 10, 50, 18, 58, 26, | ||
107 | 33, 1, 41, 9, 49, 17, 57, 25 | ||
108 | }; | ||
109 | |||
110 | static uchar sc[16] = { 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 }; | ||
111 | |||
112 | static uchar sbox[8][4][16] = { | ||
113 | {{14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7}, | ||
114 | {0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8}, | ||
115 | {4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0}, | ||
116 | {15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13} }, | ||
117 | |||
118 | {{15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10}, | ||
119 | {3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5}, | ||
120 | {0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15}, | ||
121 | {13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9} }, | ||
122 | |||
123 | {{10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8}, | ||
124 | {13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1}, | ||
125 | {13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7}, | ||
126 | {1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12} }, | ||
127 | |||
128 | {{7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15}, | ||
129 | {13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9}, | ||
130 | {10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4}, | ||
131 | {3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14} }, | ||
132 | |||
133 | {{2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9}, | ||
134 | {14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6}, | ||
135 | {4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14}, | ||
136 | {11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3} }, | ||
137 | |||
138 | {{12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11}, | ||
139 | {10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8}, | ||
140 | {9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6}, | ||
141 | {4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13} }, | ||
142 | |||
143 | {{4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1}, | ||
144 | {13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6}, | ||
145 | {1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2}, | ||
146 | {6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12} }, | ||
147 | |||
148 | {{13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7}, | ||
149 | {1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2}, | ||
150 | {7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8}, | ||
151 | {2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11} } | ||
152 | }; | ||
153 | |||
154 | static void | ||
155 | permute(char *out, char *in, uchar *p, int n) | ||
156 | { | ||
157 | int i; | ||
158 | for (i = 0; i < n; i++) | ||
159 | out[i] = in[p[i] - 1]; | ||
160 | } | ||
161 | |||
162 | static void | ||
163 | lshift(char *d, int count, int n) | ||
164 | { | ||
165 | char out[64]; | ||
166 | int i; | ||
167 | for (i = 0; i < n; i++) | ||
168 | out[i] = d[(i + count) % n]; | ||
169 | for (i = 0; i < n; i++) | ||
170 | d[i] = out[i]; | ||
171 | } | ||
172 | |||
173 | static void | ||
174 | concat(char *out, char *in1, char *in2, int l1, int l2) | ||
175 | { | ||
176 | while (l1--) | ||
177 | *out++ = *in1++; | ||
178 | while (l2--) | ||
179 | *out++ = *in2++; | ||
180 | } | ||
181 | |||
182 | static void | ||
183 | xor(char *out, char *in1, char *in2, int n) | ||
184 | { | ||
185 | int i; | ||
186 | for (i = 0; i < n; i++) | ||
187 | out[i] = in1[i] ^ in2[i]; | ||
188 | } | ||
189 | |||
190 | static void | ||
191 | dohash(char *out, char *in, char *key, int forw) | ||
192 | { | ||
193 | int i, j, k; | ||
194 | char *pk1; | ||
195 | char c[28]; | ||
196 | char d[28]; | ||
197 | char *cd; | ||
198 | char (*ki)[48]; | ||
199 | char *pd1; | ||
200 | char l[32], r[32]; | ||
201 | char *rl; | ||
202 | |||
203 | /* Have to reduce stack usage */ | ||
204 | pk1 = kmalloc(56+56+64+64, GFP_KERNEL); | ||
205 | if (pk1 == NULL) | ||
206 | return; | ||
207 | |||
208 | ki = kmalloc(16*48, GFP_KERNEL); | ||
209 | if (ki == NULL) { | ||
210 | kfree(pk1); | ||
211 | return; | ||
212 | } | ||
213 | |||
214 | cd = pk1 + 56; | ||
215 | pd1 = cd + 56; | ||
216 | rl = pd1 + 64; | ||
217 | |||
218 | permute(pk1, key, perm1, 56); | ||
219 | |||
220 | for (i = 0; i < 28; i++) | ||
221 | c[i] = pk1[i]; | ||
222 | for (i = 0; i < 28; i++) | ||
223 | d[i] = pk1[i + 28]; | ||
224 | |||
225 | for (i = 0; i < 16; i++) { | ||
226 | lshift(c, sc[i], 28); | ||
227 | lshift(d, sc[i], 28); | ||
228 | |||
229 | concat(cd, c, d, 28, 28); | ||
230 | permute(ki[i], cd, perm2, 48); | ||
231 | } | ||
232 | |||
233 | permute(pd1, in, perm3, 64); | ||
234 | |||
235 | for (j = 0; j < 32; j++) { | ||
236 | l[j] = pd1[j]; | ||
237 | r[j] = pd1[j + 32]; | ||
238 | } | ||
239 | |||
240 | for (i = 0; i < 16; i++) { | ||
241 | char *er; /* er[48] */ | ||
242 | char *erk; /* erk[48] */ | ||
243 | char b[8][6]; | ||
244 | char *cb; /* cb[32] */ | ||
245 | char *pcb; /* pcb[32] */ | ||
246 | char *r2; /* r2[32] */ | ||
247 | |||
248 | er = kmalloc(48+48+32+32+32, GFP_KERNEL); | ||
249 | if (er == NULL) { | ||
250 | kfree(pk1); | ||
251 | kfree(ki); | ||
252 | return; | ||
253 | } | ||
254 | erk = er+48; | ||
255 | cb = erk+48; | ||
256 | pcb = cb+32; | ||
257 | r2 = pcb+32; | ||
258 | |||
259 | permute(er, r, perm4, 48); | ||
260 | |||
261 | xor(erk, er, ki[forw ? i : 15 - i], 48); | ||
262 | |||
263 | for (j = 0; j < 8; j++) | ||
264 | for (k = 0; k < 6; k++) | ||
265 | b[j][k] = erk[j * 6 + k]; | ||
266 | |||
267 | for (j = 0; j < 8; j++) { | ||
268 | int m, n; | ||
269 | m = (b[j][0] << 1) | b[j][5]; | ||
270 | |||
271 | n = (b[j][1] << 3) | (b[j][2] << 2) | (b[j][3] << | ||
272 | 1) | b[j][4]; | ||
273 | |||
274 | for (k = 0; k < 4; k++) | ||
275 | b[j][k] = | ||
276 | (sbox[j][m][n] & (1 << (3 - k))) ? 1 : 0; | ||
277 | } | ||
278 | |||
279 | for (j = 0; j < 8; j++) | ||
280 | for (k = 0; k < 4; k++) | ||
281 | cb[j * 4 + k] = b[j][k]; | ||
282 | permute(pcb, cb, perm5, 32); | ||
283 | |||
284 | xor(r2, l, pcb, 32); | ||
285 | |||
286 | for (j = 0; j < 32; j++) | ||
287 | l[j] = r[j]; | ||
288 | |||
289 | for (j = 0; j < 32; j++) | ||
290 | r[j] = r2[j]; | ||
291 | |||
292 | kfree(er); | ||
293 | } | ||
294 | |||
295 | concat(rl, r, l, 32, 32); | ||
296 | |||
297 | permute(out, rl, perm6, 64); | ||
298 | kfree(pk1); | ||
299 | kfree(ki); | ||
300 | } | ||
301 | |||
302 | static void | ||
303 | str_to_key(unsigned char *str, unsigned char *key) | ||
304 | { | ||
305 | int i; | ||
306 | |||
307 | key[0] = str[0] >> 1; | ||
308 | key[1] = ((str[0] & 0x01) << 6) | (str[1] >> 2); | ||
309 | key[2] = ((str[1] & 0x03) << 5) | (str[2] >> 3); | ||
310 | key[3] = ((str[2] & 0x07) << 4) | (str[3] >> 4); | ||
311 | key[4] = ((str[3] & 0x0F) << 3) | (str[4] >> 5); | ||
312 | key[5] = ((str[4] & 0x1F) << 2) | (str[5] >> 6); | ||
313 | key[6] = ((str[5] & 0x3F) << 1) | (str[6] >> 7); | ||
314 | key[7] = str[6] & 0x7F; | ||
315 | for (i = 0; i < 8; i++) | ||
316 | key[i] = (key[i] << 1); | ||
317 | } | ||
318 | |||
319 | static void | ||
320 | smbhash(unsigned char *out, const unsigned char *in, unsigned char *key, | ||
321 | int forw) | ||
322 | { | ||
323 | int i; | ||
324 | char *outb; /* outb[64] */ | ||
325 | char *inb; /* inb[64] */ | ||
326 | char *keyb; /* keyb[64] */ | ||
327 | unsigned char key2[8]; | ||
328 | |||
329 | outb = kmalloc(64 * 3, GFP_KERNEL); | ||
330 | if (outb == NULL) | ||
331 | return; | ||
332 | |||
333 | inb = outb + 64; | ||
334 | keyb = inb + 64; | ||
335 | |||
336 | str_to_key(key, key2); | ||
337 | |||
338 | for (i = 0; i < 64; i++) { | ||
339 | inb[i] = (in[i / 8] & (1 << (7 - (i % 8)))) ? 1 : 0; | ||
340 | keyb[i] = (key2[i / 8] & (1 << (7 - (i % 8)))) ? 1 : 0; | ||
341 | outb[i] = 0; | ||
342 | } | ||
343 | |||
344 | dohash(outb, inb, keyb, forw); | ||
345 | |||
346 | for (i = 0; i < 8; i++) | ||
347 | out[i] = 0; | ||
348 | |||
349 | for (i = 0; i < 64; i++) { | ||
350 | if (outb[i]) | ||
351 | out[i / 8] |= (1 << (7 - (i % 8))); | ||
352 | } | ||
353 | kfree(outb); | ||
354 | } | ||
355 | |||
356 | void | ||
357 | E_P16(unsigned char *p14, unsigned char *p16) | ||
358 | { | ||
359 | unsigned char sp8[8] = | ||
360 | { 0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 }; | ||
361 | smbhash(p16, sp8, p14, 1); | ||
362 | smbhash(p16 + 8, sp8, p14 + 7, 1); | ||
363 | } | ||
364 | |||
365 | void | ||
366 | E_P24(unsigned char *p21, const unsigned char *c8, unsigned char *p24) | ||
367 | { | ||
368 | smbhash(p24, c8, p21, 1); | ||
369 | smbhash(p24 + 8, c8, p21 + 7, 1); | ||
370 | smbhash(p24 + 16, c8, p21 + 14, 1); | ||
371 | } | ||
372 | |||
373 | #if 0 /* currently unused */ | ||
374 | static void | ||
375 | D_P16(unsigned char *p14, unsigned char *in, unsigned char *out) | ||
376 | { | ||
377 | smbhash(out, in, p14, 0); | ||
378 | smbhash(out + 8, in + 8, p14 + 7, 0); | ||
379 | } | ||
380 | |||
381 | static void | ||
382 | E_old_pw_hash(unsigned char *p14, unsigned char *in, unsigned char *out) | ||
383 | { | ||
384 | smbhash(out, in, p14, 1); | ||
385 | smbhash(out + 8, in + 8, p14 + 7, 1); | ||
386 | } | ||
387 | /* these routines are currently unneeded, but may be | ||
388 | needed later */ | ||
389 | void | ||
390 | cred_hash1(unsigned char *out, unsigned char *in, unsigned char *key) | ||
391 | { | ||
392 | unsigned char buf[8]; | ||
393 | |||
394 | smbhash(buf, in, key, 1); | ||
395 | smbhash(out, buf, key + 9, 1); | ||
396 | } | ||
397 | |||
398 | void | ||
399 | cred_hash2(unsigned char *out, unsigned char *in, unsigned char *key) | ||
400 | { | ||
401 | unsigned char buf[8]; | ||
402 | static unsigned char key2[8]; | ||
403 | |||
404 | smbhash(buf, in, key, 1); | ||
405 | key2[0] = key[7]; | ||
406 | smbhash(out, buf, key2, 1); | ||
407 | } | ||
408 | |||
409 | void | ||
410 | cred_hash3(unsigned char *out, unsigned char *in, unsigned char *key, int forw) | ||
411 | { | ||
412 | static unsigned char key2[8]; | ||
413 | |||
414 | smbhash(out, in, key, forw); | ||
415 | key2[0] = key[7]; | ||
416 | smbhash(out + 8, in + 8, key2, forw); | ||
417 | } | ||
418 | #endif /* unneeded routines */ | ||
diff --git a/fs/cifs/smbencrypt.c b/fs/cifs/smbencrypt.c index b5041c849981..1525d5e662b6 100644 --- a/fs/cifs/smbencrypt.c +++ b/fs/cifs/smbencrypt.c | |||
@@ -47,6 +47,88 @@ | |||
47 | #define SSVALX(buf,pos,val) (CVAL(buf,pos)=(val)&0xFF,CVAL(buf,pos+1)=(val)>>8) | 47 | #define SSVALX(buf,pos,val) (CVAL(buf,pos)=(val)&0xFF,CVAL(buf,pos+1)=(val)>>8) |
48 | #define SSVAL(buf,pos,val) SSVALX((buf),(pos),((__u16)(val))) | 48 | #define SSVAL(buf,pos,val) SSVALX((buf),(pos),((__u16)(val))) |
49 | 49 | ||
50 | static void | ||
51 | str_to_key(unsigned char *str, unsigned char *key) | ||
52 | { | ||
53 | int i; | ||
54 | |||
55 | key[0] = str[0] >> 1; | ||
56 | key[1] = ((str[0] & 0x01) << 6) | (str[1] >> 2); | ||
57 | key[2] = ((str[1] & 0x03) << 5) | (str[2] >> 3); | ||
58 | key[3] = ((str[2] & 0x07) << 4) | (str[3] >> 4); | ||
59 | key[4] = ((str[3] & 0x0F) << 3) | (str[4] >> 5); | ||
60 | key[5] = ((str[4] & 0x1F) << 2) | (str[5] >> 6); | ||
61 | key[6] = ((str[5] & 0x3F) << 1) | (str[6] >> 7); | ||
62 | key[7] = str[6] & 0x7F; | ||
63 | for (i = 0; i < 8; i++) | ||
64 | key[i] = (key[i] << 1); | ||
65 | } | ||
66 | |||
67 | static int | ||
68 | smbhash(unsigned char *out, const unsigned char *in, unsigned char *key) | ||
69 | { | ||
70 | int rc; | ||
71 | unsigned char key2[8]; | ||
72 | struct crypto_blkcipher *tfm_des; | ||
73 | struct scatterlist sgin, sgout; | ||
74 | struct blkcipher_desc desc; | ||
75 | |||
76 | str_to_key(key, key2); | ||
77 | |||
78 | tfm_des = crypto_alloc_blkcipher("ecb(des)", 0, CRYPTO_ALG_ASYNC); | ||
79 | if (IS_ERR(tfm_des)) { | ||
80 | rc = PTR_ERR(tfm_des); | ||
81 | cERROR(1, "could not allocate des crypto API\n"); | ||
82 | goto smbhash_err; | ||
83 | } | ||
84 | |||
85 | desc.tfm = tfm_des; | ||
86 | |||
87 | crypto_blkcipher_setkey(tfm_des, key2, 8); | ||
88 | |||
89 | sg_init_one(&sgin, in, 8); | ||
90 | sg_init_one(&sgout, out, 8); | ||
91 | |||
92 | rc = crypto_blkcipher_encrypt(&desc, &sgout, &sgin, 8); | ||
93 | if (rc) { | ||
94 | cERROR(1, "could not encrypt crypt key rc: %d\n", rc); | ||
95 | crypto_free_blkcipher(tfm_des); | ||
96 | goto smbhash_err; | ||
97 | } | ||
98 | |||
99 | smbhash_err: | ||
100 | return rc; | ||
101 | } | ||
102 | |||
103 | static int | ||
104 | E_P16(unsigned char *p14, unsigned char *p16) | ||
105 | { | ||
106 | int rc; | ||
107 | unsigned char sp8[8] = | ||
108 | { 0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 }; | ||
109 | |||
110 | rc = smbhash(p16, sp8, p14); | ||
111 | if (rc) | ||
112 | return rc; | ||
113 | rc = smbhash(p16 + 8, sp8, p14 + 7); | ||
114 | return rc; | ||
115 | } | ||
116 | |||
117 | static int | ||
118 | E_P24(unsigned char *p21, const unsigned char *c8, unsigned char *p24) | ||
119 | { | ||
120 | int rc; | ||
121 | |||
122 | rc = smbhash(p24, c8, p21); | ||
123 | if (rc) | ||
124 | return rc; | ||
125 | rc = smbhash(p24 + 8, c8, p21 + 7); | ||
126 | if (rc) | ||
127 | return rc; | ||
128 | rc = smbhash(p24 + 16, c8, p21 + 14); | ||
129 | return rc; | ||
130 | } | ||
131 | |||
50 | /* produce a md4 message digest from data of length n bytes */ | 132 | /* produce a md4 message digest from data of length n bytes */ |
51 | int | 133 | int |
52 | mdfour(unsigned char *md4_hash, unsigned char *link_str, int link_len) | 134 | mdfour(unsigned char *md4_hash, unsigned char *link_str, int link_len) |
@@ -87,40 +169,30 @@ mdfour_err: | |||
87 | return rc; | 169 | return rc; |
88 | } | 170 | } |
89 | 171 | ||
90 | /* Does the des encryption from the NT or LM MD4 hash. */ | ||
91 | static void | ||
92 | SMBOWFencrypt(unsigned char passwd[16], const unsigned char *c8, | ||
93 | unsigned char p24[24]) | ||
94 | { | ||
95 | unsigned char p21[21]; | ||
96 | |||
97 | memset(p21, '\0', 21); | ||
98 | |||
99 | memcpy(p21, passwd, 16); | ||
100 | E_P24(p21, c8, p24); | ||
101 | } | ||
102 | |||
103 | /* | 172 | /* |
104 | This implements the X/Open SMB password encryption | 173 | This implements the X/Open SMB password encryption |
105 | It takes a password, a 8 byte "crypt key" and puts 24 bytes of | 174 | It takes a password, a 8 byte "crypt key" and puts 24 bytes of |
106 | encrypted password into p24 */ | 175 | encrypted password into p24 */ |
107 | /* Note that password must be uppercased and null terminated */ | 176 | /* Note that password must be uppercased and null terminated */ |
108 | void | 177 | int |
109 | SMBencrypt(unsigned char *passwd, const unsigned char *c8, unsigned char *p24) | 178 | SMBencrypt(unsigned char *passwd, const unsigned char *c8, unsigned char *p24) |
110 | { | 179 | { |
111 | unsigned char p14[15], p21[21]; | 180 | int rc; |
181 | unsigned char p14[14], p16[16], p21[21]; | ||
112 | 182 | ||
113 | memset(p21, '\0', 21); | ||
114 | memset(p14, '\0', 14); | 183 | memset(p14, '\0', 14); |
115 | strncpy((char *) p14, (char *) passwd, 14); | 184 | memset(p16, '\0', 16); |
185 | memset(p21, '\0', 21); | ||
116 | 186 | ||
117 | /* strupper((char *)p14); *//* BB at least uppercase the easy range */ | 187 | memcpy(p14, passwd, 14); |
118 | E_P16(p14, p21); | 188 | rc = E_P16(p14, p16); |
189 | if (rc) | ||
190 | return rc; | ||
119 | 191 | ||
120 | SMBOWFencrypt(p21, c8, p24); | 192 | memcpy(p21, p16, 16); |
193 | rc = E_P24(p21, c8, p24); | ||
121 | 194 | ||
122 | memset(p14, 0, 15); | 195 | return rc; |
123 | memset(p21, 0, 21); | ||
124 | } | 196 | } |
125 | 197 | ||
126 | /* Routines for Windows NT MD4 Hash functions. */ | 198 | /* Routines for Windows NT MD4 Hash functions. */ |
@@ -279,16 +351,18 @@ int | |||
279 | SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24) | 351 | SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24) |
280 | { | 352 | { |
281 | int rc; | 353 | int rc; |
282 | unsigned char p21[21]; | 354 | unsigned char p16[16], p21[21]; |
283 | 355 | ||
356 | memset(p16, '\0', 16); | ||
284 | memset(p21, '\0', 21); | 357 | memset(p21, '\0', 21); |
285 | 358 | ||
286 | rc = E_md4hash(passwd, p21); | 359 | rc = E_md4hash(passwd, p16); |
287 | if (rc) { | 360 | if (rc) { |
288 | cFYI(1, "%s Can't generate NT hash, error: %d", __func__, rc); | 361 | cFYI(1, "%s Can't generate NT hash, error: %d", __func__, rc); |
289 | return rc; | 362 | return rc; |
290 | } | 363 | } |
291 | SMBOWFencrypt(p21, c8, p24); | 364 | memcpy(p21, p16, 16); |
365 | rc = E_P24(p21, c8, p24); | ||
292 | return rc; | 366 | return rc; |
293 | } | 367 | } |
294 | 368 | ||
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index 46d8756f2b24..f2513fb8c391 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c | |||
@@ -129,7 +129,7 @@ smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec) | |||
129 | unsigned int len = iov[0].iov_len; | 129 | unsigned int len = iov[0].iov_len; |
130 | unsigned int total_len; | 130 | unsigned int total_len; |
131 | int first_vec = 0; | 131 | int first_vec = 0; |
132 | unsigned int smb_buf_length = smb_buffer->smb_buf_length; | 132 | unsigned int smb_buf_length = be32_to_cpu(smb_buffer->smb_buf_length); |
133 | struct socket *ssocket = server->ssocket; | 133 | struct socket *ssocket = server->ssocket; |
134 | 134 | ||
135 | if (ssocket == NULL) | 135 | if (ssocket == NULL) |
@@ -144,17 +144,10 @@ smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec) | |||
144 | else | 144 | else |
145 | smb_msg.msg_flags = MSG_NOSIGNAL; | 145 | smb_msg.msg_flags = MSG_NOSIGNAL; |
146 | 146 | ||
147 | /* smb header is converted in header_assemble. bcc and rest of SMB word | ||
148 | area, and byte area if necessary, is converted to littleendian in | ||
149 | cifssmb.c and RFC1001 len is converted to bigendian in smb_send | ||
150 | Flags2 is converted in SendReceive */ | ||
151 | |||
152 | |||
153 | total_len = 0; | 147 | total_len = 0; |
154 | for (i = 0; i < n_vec; i++) | 148 | for (i = 0; i < n_vec; i++) |
155 | total_len += iov[i].iov_len; | 149 | total_len += iov[i].iov_len; |
156 | 150 | ||
157 | smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length); | ||
158 | cFYI(1, "Sending smb: total_len %d", total_len); | 151 | cFYI(1, "Sending smb: total_len %d", total_len); |
159 | dump_smb(smb_buffer, len); | 152 | dump_smb(smb_buffer, len); |
160 | 153 | ||
@@ -243,7 +236,7 @@ smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec) | |||
243 | 236 | ||
244 | /* Don't want to modify the buffer as a | 237 | /* Don't want to modify the buffer as a |
245 | side effect of this call. */ | 238 | side effect of this call. */ |
246 | smb_buffer->smb_buf_length = smb_buf_length; | 239 | smb_buffer->smb_buf_length = cpu_to_be32(smb_buf_length); |
247 | 240 | ||
248 | return rc; | 241 | return rc; |
249 | } | 242 | } |
@@ -387,7 +380,7 @@ cifs_call_async(struct TCP_Server_Info *server, struct smb_hdr *in_buf, | |||
387 | #ifdef CONFIG_CIFS_STATS2 | 380 | #ifdef CONFIG_CIFS_STATS2 |
388 | atomic_inc(&server->inSend); | 381 | atomic_inc(&server->inSend); |
389 | #endif | 382 | #endif |
390 | rc = smb_send(server, in_buf, in_buf->smb_buf_length); | 383 | rc = smb_send(server, in_buf, be32_to_cpu(in_buf->smb_buf_length)); |
391 | #ifdef CONFIG_CIFS_STATS2 | 384 | #ifdef CONFIG_CIFS_STATS2 |
392 | atomic_dec(&server->inSend); | 385 | atomic_dec(&server->inSend); |
393 | mid->when_sent = jiffies; | 386 | mid->when_sent = jiffies; |
@@ -422,7 +415,7 @@ SendReceiveNoRsp(const unsigned int xid, struct cifsSesInfo *ses, | |||
422 | int resp_buf_type; | 415 | int resp_buf_type; |
423 | 416 | ||
424 | iov[0].iov_base = (char *)in_buf; | 417 | iov[0].iov_base = (char *)in_buf; |
425 | iov[0].iov_len = in_buf->smb_buf_length + 4; | 418 | iov[0].iov_len = be32_to_cpu(in_buf->smb_buf_length) + 4; |
426 | flags |= CIFS_NO_RESP; | 419 | flags |= CIFS_NO_RESP; |
427 | rc = SendReceive2(xid, ses, iov, 1, &resp_buf_type, flags); | 420 | rc = SendReceive2(xid, ses, iov, 1, &resp_buf_type, flags); |
428 | cFYI(DBG2, "SendRcvNoRsp flags %d rc %d", flags, rc); | 421 | cFYI(DBG2, "SendRcvNoRsp flags %d rc %d", flags, rc); |
@@ -488,10 +481,10 @@ send_nt_cancel(struct TCP_Server_Info *server, struct smb_hdr *in_buf, | |||
488 | int rc = 0; | 481 | int rc = 0; |
489 | 482 | ||
490 | /* -4 for RFC1001 length and +2 for BCC field */ | 483 | /* -4 for RFC1001 length and +2 for BCC field */ |
491 | in_buf->smb_buf_length = sizeof(struct smb_hdr) - 4 + 2; | 484 | in_buf->smb_buf_length = cpu_to_be32(sizeof(struct smb_hdr) - 4 + 2); |
492 | in_buf->Command = SMB_COM_NT_CANCEL; | 485 | in_buf->Command = SMB_COM_NT_CANCEL; |
493 | in_buf->WordCount = 0; | 486 | in_buf->WordCount = 0; |
494 | put_bcc_le(0, in_buf); | 487 | put_bcc(0, in_buf); |
495 | 488 | ||
496 | mutex_lock(&server->srv_mutex); | 489 | mutex_lock(&server->srv_mutex); |
497 | rc = cifs_sign_smb(in_buf, server, &mid->sequence_number); | 490 | rc = cifs_sign_smb(in_buf, server, &mid->sequence_number); |
@@ -499,7 +492,7 @@ send_nt_cancel(struct TCP_Server_Info *server, struct smb_hdr *in_buf, | |||
499 | mutex_unlock(&server->srv_mutex); | 492 | mutex_unlock(&server->srv_mutex); |
500 | return rc; | 493 | return rc; |
501 | } | 494 | } |
502 | rc = smb_send(server, in_buf, in_buf->smb_buf_length); | 495 | rc = smb_send(server, in_buf, be32_to_cpu(in_buf->smb_buf_length)); |
503 | mutex_unlock(&server->srv_mutex); | 496 | mutex_unlock(&server->srv_mutex); |
504 | 497 | ||
505 | cFYI(1, "issued NT_CANCEL for mid %u, rc = %d", | 498 | cFYI(1, "issued NT_CANCEL for mid %u, rc = %d", |
@@ -612,7 +605,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, | |||
612 | return rc; | 605 | return rc; |
613 | } | 606 | } |
614 | 607 | ||
615 | receive_len = midQ->resp_buf->smb_buf_length; | 608 | receive_len = be32_to_cpu(midQ->resp_buf->smb_buf_length); |
616 | 609 | ||
617 | if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) { | 610 | if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) { |
618 | cERROR(1, "Frame too large received. Length: %d Xid: %d", | 611 | cERROR(1, "Frame too large received. Length: %d Xid: %d", |
@@ -651,11 +644,6 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, | |||
651 | rc = map_smb_to_linux_error(midQ->resp_buf, | 644 | rc = map_smb_to_linux_error(midQ->resp_buf, |
652 | flags & CIFS_LOG_ERROR); | 645 | flags & CIFS_LOG_ERROR); |
653 | 646 | ||
654 | /* convert ByteCount if necessary */ | ||
655 | if (receive_len >= sizeof(struct smb_hdr) - 4 | ||
656 | /* do not count RFC1001 header */ + | ||
657 | (2 * midQ->resp_buf->WordCount) + 2 /* bcc */ ) | ||
658 | put_bcc(get_bcc_le(midQ->resp_buf), midQ->resp_buf); | ||
659 | if ((flags & CIFS_NO_RESP) == 0) | 647 | if ((flags & CIFS_NO_RESP) == 0) |
660 | midQ->resp_buf = NULL; /* mark it so buf will | 648 | midQ->resp_buf = NULL; /* mark it so buf will |
661 | not be freed by | 649 | not be freed by |
@@ -698,9 +686,10 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, | |||
698 | to the same server. We may make this configurable later or | 686 | to the same server. We may make this configurable later or |
699 | use ses->maxReq */ | 687 | use ses->maxReq */ |
700 | 688 | ||
701 | if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) { | 689 | if (be32_to_cpu(in_buf->smb_buf_length) > CIFSMaxBufSize + |
690 | MAX_CIFS_HDR_SIZE - 4) { | ||
702 | cERROR(1, "Illegal length, greater than maximum frame, %d", | 691 | cERROR(1, "Illegal length, greater than maximum frame, %d", |
703 | in_buf->smb_buf_length); | 692 | be32_to_cpu(in_buf->smb_buf_length)); |
704 | return -EIO; | 693 | return -EIO; |
705 | } | 694 | } |
706 | 695 | ||
@@ -733,7 +722,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, | |||
733 | #ifdef CONFIG_CIFS_STATS2 | 722 | #ifdef CONFIG_CIFS_STATS2 |
734 | atomic_inc(&ses->server->inSend); | 723 | atomic_inc(&ses->server->inSend); |
735 | #endif | 724 | #endif |
736 | rc = smb_send(ses->server, in_buf, in_buf->smb_buf_length); | 725 | rc = smb_send(ses->server, in_buf, be32_to_cpu(in_buf->smb_buf_length)); |
737 | #ifdef CONFIG_CIFS_STATS2 | 726 | #ifdef CONFIG_CIFS_STATS2 |
738 | atomic_dec(&ses->server->inSend); | 727 | atomic_dec(&ses->server->inSend); |
739 | midQ->when_sent = jiffies; | 728 | midQ->when_sent = jiffies; |
@@ -768,7 +757,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, | |||
768 | return rc; | 757 | return rc; |
769 | } | 758 | } |
770 | 759 | ||
771 | receive_len = midQ->resp_buf->smb_buf_length; | 760 | receive_len = be32_to_cpu(midQ->resp_buf->smb_buf_length); |
772 | 761 | ||
773 | if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) { | 762 | if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) { |
774 | cERROR(1, "Frame too large received. Length: %d Xid: %d", | 763 | cERROR(1, "Frame too large received. Length: %d Xid: %d", |
@@ -781,7 +770,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, | |||
781 | 770 | ||
782 | if (midQ->resp_buf && out_buf | 771 | if (midQ->resp_buf && out_buf |
783 | && (midQ->midState == MID_RESPONSE_RECEIVED)) { | 772 | && (midQ->midState == MID_RESPONSE_RECEIVED)) { |
784 | out_buf->smb_buf_length = receive_len; | 773 | out_buf->smb_buf_length = cpu_to_be32(receive_len); |
785 | memcpy((char *)out_buf + 4, | 774 | memcpy((char *)out_buf + 4, |
786 | (char *)midQ->resp_buf + 4, | 775 | (char *)midQ->resp_buf + 4, |
787 | receive_len); | 776 | receive_len); |
@@ -800,16 +789,10 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, | |||
800 | } | 789 | } |
801 | } | 790 | } |
802 | 791 | ||
803 | *pbytes_returned = out_buf->smb_buf_length; | 792 | *pbytes_returned = be32_to_cpu(out_buf->smb_buf_length); |
804 | 793 | ||
805 | /* BB special case reconnect tid and uid here? */ | 794 | /* BB special case reconnect tid and uid here? */ |
806 | rc = map_smb_to_linux_error(out_buf, 0 /* no log */ ); | 795 | rc = map_smb_to_linux_error(out_buf, 0 /* no log */ ); |
807 | |||
808 | /* convert ByteCount if necessary */ | ||
809 | if (receive_len >= sizeof(struct smb_hdr) - 4 | ||
810 | /* do not count RFC1001 header */ + | ||
811 | (2 * out_buf->WordCount) + 2 /* bcc */ ) | ||
812 | put_bcc(get_bcc_le(midQ->resp_buf), midQ->resp_buf); | ||
813 | } else { | 796 | } else { |
814 | rc = -EIO; | 797 | rc = -EIO; |
815 | cERROR(1, "Bad MID state?"); | 798 | cERROR(1, "Bad MID state?"); |
@@ -877,9 +860,10 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon, | |||
877 | to the same server. We may make this configurable later or | 860 | to the same server. We may make this configurable later or |
878 | use ses->maxReq */ | 861 | use ses->maxReq */ |
879 | 862 | ||
880 | if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) { | 863 | if (be32_to_cpu(in_buf->smb_buf_length) > CIFSMaxBufSize + |
864 | MAX_CIFS_HDR_SIZE - 4) { | ||
881 | cERROR(1, "Illegal length, greater than maximum frame, %d", | 865 | cERROR(1, "Illegal length, greater than maximum frame, %d", |
882 | in_buf->smb_buf_length); | 866 | be32_to_cpu(in_buf->smb_buf_length)); |
883 | return -EIO; | 867 | return -EIO; |
884 | } | 868 | } |
885 | 869 | ||
@@ -910,7 +894,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon, | |||
910 | #ifdef CONFIG_CIFS_STATS2 | 894 | #ifdef CONFIG_CIFS_STATS2 |
911 | atomic_inc(&ses->server->inSend); | 895 | atomic_inc(&ses->server->inSend); |
912 | #endif | 896 | #endif |
913 | rc = smb_send(ses->server, in_buf, in_buf->smb_buf_length); | 897 | rc = smb_send(ses->server, in_buf, be32_to_cpu(in_buf->smb_buf_length)); |
914 | #ifdef CONFIG_CIFS_STATS2 | 898 | #ifdef CONFIG_CIFS_STATS2 |
915 | atomic_dec(&ses->server->inSend); | 899 | atomic_dec(&ses->server->inSend); |
916 | midQ->when_sent = jiffies; | 900 | midQ->when_sent = jiffies; |
@@ -977,7 +961,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon, | |||
977 | if (rc != 0) | 961 | if (rc != 0) |
978 | return rc; | 962 | return rc; |
979 | 963 | ||
980 | receive_len = midQ->resp_buf->smb_buf_length; | 964 | receive_len = be32_to_cpu(midQ->resp_buf->smb_buf_length); |
981 | if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) { | 965 | if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) { |
982 | cERROR(1, "Frame too large received. Length: %d Xid: %d", | 966 | cERROR(1, "Frame too large received. Length: %d Xid: %d", |
983 | receive_len, xid); | 967 | receive_len, xid); |
@@ -993,7 +977,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon, | |||
993 | goto out; | 977 | goto out; |
994 | } | 978 | } |
995 | 979 | ||
996 | out_buf->smb_buf_length = receive_len; | 980 | out_buf->smb_buf_length = cpu_to_be32(receive_len); |
997 | memcpy((char *)out_buf + 4, | 981 | memcpy((char *)out_buf + 4, |
998 | (char *)midQ->resp_buf + 4, | 982 | (char *)midQ->resp_buf + 4, |
999 | receive_len); | 983 | receive_len); |
@@ -1012,17 +996,11 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon, | |||
1012 | } | 996 | } |
1013 | } | 997 | } |
1014 | 998 | ||
1015 | *pbytes_returned = out_buf->smb_buf_length; | 999 | *pbytes_returned = be32_to_cpu(out_buf->smb_buf_length); |
1016 | 1000 | ||
1017 | /* BB special case reconnect tid and uid here? */ | 1001 | /* BB special case reconnect tid and uid here? */ |
1018 | rc = map_smb_to_linux_error(out_buf, 0 /* no log */ ); | 1002 | rc = map_smb_to_linux_error(out_buf, 0 /* no log */ ); |
1019 | 1003 | ||
1020 | /* convert ByteCount if necessary */ | ||
1021 | if (receive_len >= sizeof(struct smb_hdr) - 4 | ||
1022 | /* do not count RFC1001 header */ + | ||
1023 | (2 * out_buf->WordCount) + 2 /* bcc */ ) | ||
1024 | put_bcc(get_bcc_le(out_buf), out_buf); | ||
1025 | |||
1026 | out: | 1004 | out: |
1027 | delete_mid(midQ); | 1005 | delete_mid(midQ); |
1028 | if (rstart && rc == -EACCES) | 1006 | if (rstart && rc == -EACCES) |
diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c index eae2a1491608..912995e013ec 100644 --- a/fs/cifs/xattr.c +++ b/fs/cifs/xattr.c | |||
@@ -112,6 +112,7 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name, | |||
112 | struct cifsTconInfo *pTcon; | 112 | struct cifsTconInfo *pTcon; |
113 | struct super_block *sb; | 113 | struct super_block *sb; |
114 | char *full_path; | 114 | char *full_path; |
115 | struct cifs_ntsd *pacl; | ||
115 | 116 | ||
116 | if (direntry == NULL) | 117 | if (direntry == NULL) |
117 | return -EIO; | 118 | return -EIO; |
@@ -166,6 +167,25 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name, | |||
166 | rc = CIFSSMBSetEA(xid, pTcon, full_path, ea_name, ea_value, | 167 | rc = CIFSSMBSetEA(xid, pTcon, full_path, ea_name, ea_value, |
167 | (__u16)value_size, cifs_sb->local_nls, | 168 | (__u16)value_size, cifs_sb->local_nls, |
168 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 169 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); |
170 | } else if (strncmp(ea_name, CIFS_XATTR_CIFS_ACL, | ||
171 | strlen(CIFS_XATTR_CIFS_ACL)) == 0) { | ||
172 | pacl = kmalloc(value_size, GFP_KERNEL); | ||
173 | if (!pacl) { | ||
174 | cFYI(1, "%s: Can't allocate memory for ACL", | ||
175 | __func__); | ||
176 | rc = -ENOMEM; | ||
177 | } else { | ||
178 | #ifdef CONFIG_CIFS_ACL | ||
179 | memcpy(pacl, ea_value, value_size); | ||
180 | rc = set_cifs_acl(pacl, value_size, | ||
181 | direntry->d_inode, full_path); | ||
182 | if (rc == 0) /* force revalidate of the inode */ | ||
183 | CIFS_I(direntry->d_inode)->time = 0; | ||
184 | kfree(pacl); | ||
185 | #else | ||
186 | cFYI(1, "Set CIFS ACL not supported yet"); | ||
187 | #endif /* CONFIG_CIFS_ACL */ | ||
188 | } | ||
169 | } else { | 189 | } else { |
170 | int temp; | 190 | int temp; |
171 | temp = strncmp(ea_name, POSIX_ACL_XATTR_ACCESS, | 191 | temp = strncmp(ea_name, POSIX_ACL_XATTR_ACCESS, |
diff --git a/fs/super.c b/fs/super.c index 8a06881b1920..c04f7e0b7ed2 100644 --- a/fs/super.c +++ b/fs/super.c | |||
@@ -948,8 +948,7 @@ mount_fs(struct file_system_type *type, int flags, const char *name, void *data) | |||
948 | * filesystems should never set s_maxbytes larger than MAX_LFS_FILESIZE | 948 | * filesystems should never set s_maxbytes larger than MAX_LFS_FILESIZE |
949 | * but s_maxbytes was an unsigned long long for many releases. Throw | 949 | * but s_maxbytes was an unsigned long long for many releases. Throw |
950 | * this warning for a little while to try and catch filesystems that | 950 | * this warning for a little while to try and catch filesystems that |
951 | * violate this rule. This warning should be either removed or | 951 | * violate this rule. |
952 | * converted to a BUG() in 2.6.34. | ||
953 | */ | 952 | */ |
954 | WARN((sb->s_maxbytes < 0), "%s set sb->s_maxbytes to " | 953 | WARN((sb->s_maxbytes < 0), "%s set sb->s_maxbytes to " |
955 | "negative value (%lld)\n", type->name, sb->s_maxbytes); | 954 | "negative value (%lld)\n", type->name, sb->s_maxbytes); |