blob: e16b6cc1e31b42fe6c98b1a735762628fc997425 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * fs/cifs/connect.c
3 *
Steve French1080ef72011-02-24 18:07:19 +00004 * Copyright (C) International Business Machines Corp., 2002,2011
Linus Torvalds1da177e2005-04-16 15:20:36 -07005 * Author(s): Steve French (sfrench@us.ibm.com)
6 *
7 * This library is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published
9 * by the Free Software Foundation; either version 2.1 of the License, or
10 * (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15 * the GNU Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this library; if not, write to the Free Software
Steve Frenchfb8c4b12007-07-10 01:16:18 +000019 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Linus Torvalds1da177e2005-04-16 15:20:36 -070020 */
21#include <linux/fs.h>
22#include <linux/net.h>
23#include <linux/string.h>
Ingo Molnar3f07c012017-02-08 18:51:30 +010024#include <linux/sched/signal.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070025#include <linux/list.h>
26#include <linux/wait.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090027#include <linux/slab.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070028#include <linux/pagemap.h>
29#include <linux/ctype.h>
30#include <linux/utsname.h>
31#include <linux/mempool.h>
Steve Frenchb8643e12005-04-28 22:41:07 -070032#include <linux/delay.h>
Steve Frenchf1914012005-08-18 09:37:34 -070033#include <linux/completion.h>
Igor Mammedovaaf737a2007-04-03 19:16:43 +000034#include <linux/kthread.h>
Steve French0ae0efa2005-10-10 10:57:19 -070035#include <linux/pagevec.h>
Nigel Cunningham7dfb7102006-12-06 20:34:23 -080036#include <linux/freezer.h>
Igor Mammedov5c2503a2009-04-21 19:31:05 +040037#include <linux/namei.h>
Andrew Lunnc6e970a2017-03-28 23:45:06 +020038#include <linux/uuid.h>
Linus Torvalds7c0f6ba2016-12-24 11:46:01 -080039#include <linux/uaccess.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070040#include <asm/processor.h>
Jeff Layton50b64e32009-06-02 06:55:20 -040041#include <linux/inet.h>
Paul Gortmaker143cb492011-07-01 14:23:34 -040042#include <linux/module.h>
Jeff Layton8a8798a2012-01-17 16:09:15 -050043#include <keys/user-type.h>
Steve French0e2beda2009-01-30 21:24:41 +000044#include <net/ipv6.h>
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040045#include <linux/parser.h>
Christoph Hellwig2f8b5442016-11-01 07:40:13 -060046#include <linux/bvec.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070047#include "cifspdu.h"
48#include "cifsglob.h"
49#include "cifsproto.h"
50#include "cifs_unicode.h"
51#include "cifs_debug.h"
52#include "cifs_fs_sb.h"
53#include "ntlmssp.h"
54#include "nterr.h"
55#include "rfc1002pdu.h"
Suresh Jayaraman488f1d2d2010-07-05 18:12:15 +053056#include "fscache.h"
Pavel Shilovsky53e0e112016-11-04 11:50:31 -070057#include "smb2proto.h"
Long Li2f894642017-11-22 17:38:34 -070058#include "smbdirect.h"
Paulo Alcantara1c780222018-11-14 16:24:03 -020059#include "dns_resolve.h"
Paulo Alcantara93d5cb52018-11-14 17:13:25 -020060#include "cifsfs.h"
Paulo Alcantara1c780222018-11-14 16:24:03 -020061#ifdef CONFIG_CIFS_DFS_UPCALL
62#include "dfs_cache.h"
63#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -070064
Linus Torvalds1da177e2005-04-16 15:20:36 -070065extern mempool_t *cifs_req_poolp;
Steve Frenchf92a7202018-05-24 04:11:07 -050066extern bool disable_legacy_dialects;
Linus Torvalds1da177e2005-04-16 15:20:36 -070067
Jeff Layton2de970f2010-10-06 19:51:12 -040068/* FIXME: should these be tunable? */
Jeff Layton9d002df2010-10-06 19:51:11 -040069#define TLINK_ERROR_EXPIRE (1 * HZ)
Jeff Layton2de970f2010-10-06 19:51:12 -040070#define TLINK_IDLE_EXPIRE (600 * HZ)
Jeff Layton9d002df2010-10-06 19:51:11 -040071
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040072enum {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040073 /* Mount options that take no arguments */
74 Opt_user_xattr, Opt_nouser_xattr,
75 Opt_forceuid, Opt_noforceuid,
Jeff Layton72bd4812012-10-03 16:02:36 -040076 Opt_forcegid, Opt_noforcegid,
Steve French3e7a02d2019-09-11 21:46:20 -050077 Opt_noblocksend, Opt_noautotune, Opt_nolease,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040078 Opt_hard, Opt_soft, Opt_perm, Opt_noperm,
Steve French2baa2682014-09-27 02:19:01 -050079 Opt_mapposix, Opt_nomapposix,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040080 Opt_mapchars, Opt_nomapchars, Opt_sfu,
81 Opt_nosfu, Opt_nodfs, Opt_posixpaths,
Steve Frenchb3266142018-05-20 23:41:10 -050082 Opt_noposixpaths, Opt_nounix, Opt_unix,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040083 Opt_nocase,
84 Opt_brl, Opt_nobrl,
Steve French3d4ef9a2018-04-25 22:19:09 -050085 Opt_handlecache, Opt_nohandlecache,
Steve French95932652016-09-23 01:36:34 -050086 Opt_forcemandatorylock, Opt_setuidfromacl, Opt_setuids,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040087 Opt_nosetuids, Opt_dynperm, Opt_nodynperm,
88 Opt_nohard, Opt_nosoft,
89 Opt_nointr, Opt_intr,
90 Opt_nostrictsync, Opt_strictsync,
91 Opt_serverino, Opt_noserverino,
92 Opt_rwpidforward, Opt_cifsacl, Opt_nocifsacl,
93 Opt_acl, Opt_noacl, Opt_locallease,
Steve French4f5c10f2019-09-03 21:18:49 -050094 Opt_sign, Opt_ignore_signature, Opt_seal, Opt_noac,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -040095 Opt_fsc, Opt_mfsymlinks,
Jeff Laytona0b3df52013-05-24 07:40:59 -040096 Opt_multiuser, Opt_sloppy, Opt_nosharesock,
Steve Frenchb2a30772015-09-29 21:49:28 -050097 Opt_persistent, Opt_nopersistent,
Steve French592fafe2015-11-03 10:08:53 -060098 Opt_resilient, Opt_noresilient,
Steve French412094a2019-06-24 02:01:42 -050099 Opt_domainauto, Opt_rdma, Opt_modesid,
Steve French9fe5ff12019-06-24 20:39:04 -0500100 Opt_compress,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400101
102 /* Mount options which take numeric value */
103 Opt_backupuid, Opt_backupgid, Opt_uid,
104 Opt_cruid, Opt_gid, Opt_file_mode,
105 Opt_dirmode, Opt_port,
Steve French563317e2019-09-08 23:22:02 -0500106 Opt_min_enc_offload,
Steve Frenche8506d22019-02-28 21:32:15 -0600107 Opt_blocksize, Opt_rsize, Opt_wsize, Opt_actimeo,
Steve Frenchca567eb2019-03-29 16:31:07 -0500108 Opt_echo_interval, Opt_max_credits, Opt_handletimeout,
Steve French8b217fe2016-11-11 22:36:20 -0600109 Opt_snapshot,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400110
111 /* Mount options which take string value */
112 Opt_user, Opt_pass, Opt_ip,
Jeff Layton73a999f2013-03-22 08:42:57 -0400113 Opt_domain, Opt_srcaddr, Opt_iocharset,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400114 Opt_netbiosname, Opt_servern,
Jeff Layton23db65f2012-05-15 12:20:51 -0400115 Opt_ver, Opt_vers, Opt_sec, Opt_cache,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400116
117 /* Mount options to be ignored */
118 Opt_ignore,
119
120 /* Options which could be blank */
121 Opt_blank_pass,
Sachin Prabhu4fe9e962012-04-10 18:12:27 +0100122 Opt_blank_user,
123 Opt_blank_ip,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400124
125 Opt_err
126};
127
128static const match_table_t cifs_mount_option_tokens = {
129
130 { Opt_user_xattr, "user_xattr" },
131 { Opt_nouser_xattr, "nouser_xattr" },
132 { Opt_forceuid, "forceuid" },
133 { Opt_noforceuid, "noforceuid" },
Jeff Layton72bd4812012-10-03 16:02:36 -0400134 { Opt_forcegid, "forcegid" },
135 { Opt_noforcegid, "noforcegid" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400136 { Opt_noblocksend, "noblocksend" },
137 { Opt_noautotune, "noautotune" },
Steve French3e7a02d2019-09-11 21:46:20 -0500138 { Opt_nolease, "nolease" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400139 { Opt_hard, "hard" },
140 { Opt_soft, "soft" },
141 { Opt_perm, "perm" },
142 { Opt_noperm, "noperm" },
Steve French2baa2682014-09-27 02:19:01 -0500143 { Opt_mapchars, "mapchars" }, /* SFU style */
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400144 { Opt_nomapchars, "nomapchars" },
Steve French2baa2682014-09-27 02:19:01 -0500145 { Opt_mapposix, "mapposix" }, /* SFM style */
146 { Opt_nomapposix, "nomapposix" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400147 { Opt_sfu, "sfu" },
148 { Opt_nosfu, "nosfu" },
149 { Opt_nodfs, "nodfs" },
150 { Opt_posixpaths, "posixpaths" },
151 { Opt_noposixpaths, "noposixpaths" },
152 { Opt_nounix, "nounix" },
153 { Opt_nounix, "nolinux" },
Steve Frenchb3266142018-05-20 23:41:10 -0500154 { Opt_nounix, "noposix" },
155 { Opt_unix, "unix" },
156 { Opt_unix, "linux" },
157 { Opt_unix, "posix" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400158 { Opt_nocase, "nocase" },
159 { Opt_nocase, "ignorecase" },
160 { Opt_brl, "brl" },
161 { Opt_nobrl, "nobrl" },
Steve French3d4ef9a2018-04-25 22:19:09 -0500162 { Opt_handlecache, "handlecache" },
163 { Opt_nohandlecache, "nohandlecache" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400164 { Opt_nobrl, "nolock" },
165 { Opt_forcemandatorylock, "forcemandatorylock" },
Pavel Shilovsky5cfdddc2012-03-27 20:51:15 +0400166 { Opt_forcemandatorylock, "forcemand" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400167 { Opt_setuids, "setuids" },
168 { Opt_nosetuids, "nosetuids" },
Steve French95932652016-09-23 01:36:34 -0500169 { Opt_setuidfromacl, "idsfromsid" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400170 { Opt_dynperm, "dynperm" },
171 { Opt_nodynperm, "nodynperm" },
172 { Opt_nohard, "nohard" },
173 { Opt_nosoft, "nosoft" },
174 { Opt_nointr, "nointr" },
175 { Opt_intr, "intr" },
176 { Opt_nostrictsync, "nostrictsync" },
177 { Opt_strictsync, "strictsync" },
178 { Opt_serverino, "serverino" },
179 { Opt_noserverino, "noserverino" },
180 { Opt_rwpidforward, "rwpidforward" },
Steve French412094a2019-06-24 02:01:42 -0500181 { Opt_modesid, "modefromsid" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400182 { Opt_cifsacl, "cifsacl" },
183 { Opt_nocifsacl, "nocifsacl" },
184 { Opt_acl, "acl" },
185 { Opt_noacl, "noacl" },
186 { Opt_locallease, "locallease" },
187 { Opt_sign, "sign" },
Steve French4f5c10f2019-09-03 21:18:49 -0500188 { Opt_ignore_signature, "signloosely" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400189 { Opt_seal, "seal" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400190 { Opt_noac, "noac" },
191 { Opt_fsc, "fsc" },
192 { Opt_mfsymlinks, "mfsymlinks" },
193 { Opt_multiuser, "multiuser" },
Jeff Laytond8162552012-03-23 14:40:56 -0400194 { Opt_sloppy, "sloppy" },
Jeff Laytona0b3df52013-05-24 07:40:59 -0400195 { Opt_nosharesock, "nosharesock" },
Steve Frenchb2a30772015-09-29 21:49:28 -0500196 { Opt_persistent, "persistenthandles"},
197 { Opt_nopersistent, "nopersistenthandles"},
Steve French592fafe2015-11-03 10:08:53 -0600198 { Opt_resilient, "resilienthandles"},
199 { Opt_noresilient, "noresilienthandles"},
Germano Percossi39566442016-12-15 12:31:18 +0530200 { Opt_domainauto, "domainauto"},
Long Li8339dd32017-11-07 01:54:55 -0700201 { Opt_rdma, "rdma"},
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400202
203 { Opt_backupuid, "backupuid=%s" },
204 { Opt_backupgid, "backupgid=%s" },
205 { Opt_uid, "uid=%s" },
206 { Opt_cruid, "cruid=%s" },
207 { Opt_gid, "gid=%s" },
208 { Opt_file_mode, "file_mode=%s" },
209 { Opt_dirmode, "dirmode=%s" },
210 { Opt_dirmode, "dir_mode=%s" },
211 { Opt_port, "port=%s" },
Steve French563317e2019-09-08 23:22:02 -0500212 { Opt_min_enc_offload, "esize=%s" },
Steve Frenche8506d22019-02-28 21:32:15 -0600213 { Opt_blocksize, "bsize=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400214 { Opt_rsize, "rsize=%s" },
215 { Opt_wsize, "wsize=%s" },
216 { Opt_actimeo, "actimeo=%s" },
Steve Frenchca567eb2019-03-29 16:31:07 -0500217 { Opt_handletimeout, "handletimeout=%s" },
Steve Frenchadfeb3e2015-12-18 12:31:36 -0600218 { Opt_echo_interval, "echo_interval=%s" },
Steve French141891f2016-09-23 00:44:16 -0500219 { Opt_max_credits, "max_credits=%s" },
Steve French8b217fe2016-11-11 22:36:20 -0600220 { Opt_snapshot, "snapshot=%s" },
Steve French9fe5ff12019-06-24 20:39:04 -0500221 { Opt_compress, "compress=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400222
Sachin Prabhu4fe9e962012-04-10 18:12:27 +0100223 { Opt_blank_user, "user=" },
224 { Opt_blank_user, "username=" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400225 { Opt_user, "user=%s" },
226 { Opt_user, "username=%s" },
227 { Opt_blank_pass, "pass=" },
Jesper Nilsson3c15b4c2012-11-29 17:31:16 +0100228 { Opt_blank_pass, "password=" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400229 { Opt_pass, "pass=%s" },
230 { Opt_pass, "password=%s" },
Sachin Prabhu4fe9e962012-04-10 18:12:27 +0100231 { Opt_blank_ip, "ip=" },
232 { Opt_blank_ip, "addr=" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400233 { Opt_ip, "ip=%s" },
234 { Opt_ip, "addr=%s" },
Jeff Layton73a999f2013-03-22 08:42:57 -0400235 { Opt_ignore, "unc=%s" },
236 { Opt_ignore, "target=%s" },
237 { Opt_ignore, "path=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400238 { Opt_domain, "dom=%s" },
239 { Opt_domain, "domain=%s" },
240 { Opt_domain, "workgroup=%s" },
241 { Opt_srcaddr, "srcaddr=%s" },
Jeff Layton73a999f2013-03-22 08:42:57 -0400242 { Opt_ignore, "prefixpath=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400243 { Opt_iocharset, "iocharset=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400244 { Opt_netbiosname, "netbiosname=%s" },
245 { Opt_servern, "servern=%s" },
246 { Opt_ver, "ver=%s" },
Jeff Layton23db65f2012-05-15 12:20:51 -0400247 { Opt_vers, "vers=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400248 { Opt_sec, "sec=%s" },
Jeff Layton15b6a472012-05-16 07:50:15 -0400249 { Opt_cache, "cache=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400250
251 { Opt_ignore, "cred" },
252 { Opt_ignore, "credentials" },
Jeff Laytona557b972012-05-02 14:02:40 -0400253 { Opt_ignore, "cred=%s" },
254 { Opt_ignore, "credentials=%s" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400255 { Opt_ignore, "guest" },
256 { Opt_ignore, "rw" },
257 { Opt_ignore, "ro" },
258 { Opt_ignore, "suid" },
259 { Opt_ignore, "nosuid" },
260 { Opt_ignore, "exec" },
261 { Opt_ignore, "noexec" },
262 { Opt_ignore, "nodev" },
263 { Opt_ignore, "noauto" },
264 { Opt_ignore, "dev" },
265 { Opt_ignore, "mand" },
266 { Opt_ignore, "nomand" },
Steve French9b9c5be2018-09-22 12:07:06 -0500267 { Opt_ignore, "relatime" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400268 { Opt_ignore, "_netdev" },
269
270 { Opt_err, NULL }
271};
272
273enum {
274 Opt_sec_krb5, Opt_sec_krb5i, Opt_sec_krb5p,
275 Opt_sec_ntlmsspi, Opt_sec_ntlmssp,
Jeff Layton76596242012-07-23 20:34:17 -0400276 Opt_ntlm, Opt_sec_ntlmi, Opt_sec_ntlmv2,
277 Opt_sec_ntlmv2i, Opt_sec_lanman,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400278 Opt_sec_none,
279
280 Opt_sec_err
281};
282
283static const match_table_t cifs_secflavor_tokens = {
284 { Opt_sec_krb5, "krb5" },
285 { Opt_sec_krb5i, "krb5i" },
286 { Opt_sec_krb5p, "krb5p" },
287 { Opt_sec_ntlmsspi, "ntlmsspi" },
288 { Opt_sec_ntlmssp, "ntlmssp" },
289 { Opt_ntlm, "ntlm" },
290 { Opt_sec_ntlmi, "ntlmi" },
Jeff Layton76596242012-07-23 20:34:17 -0400291 { Opt_sec_ntlmv2, "nontlm" },
292 { Opt_sec_ntlmv2, "ntlmv2" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400293 { Opt_sec_ntlmv2i, "ntlmv2i" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400294 { Opt_sec_lanman, "lanman" },
295 { Opt_sec_none, "none" },
296
297 { Opt_sec_err, NULL }
298};
299
Jeff Layton15b6a472012-05-16 07:50:15 -0400300/* cache flavors */
301enum {
302 Opt_cache_loose,
303 Opt_cache_strict,
304 Opt_cache_none,
Steve French83bbfa72019-08-27 23:58:54 -0500305 Opt_cache_ro,
Steve French41e033f2019-08-30 02:12:41 -0500306 Opt_cache_rw,
Jeff Layton15b6a472012-05-16 07:50:15 -0400307 Opt_cache_err
308};
309
310static const match_table_t cifs_cacheflavor_tokens = {
311 { Opt_cache_loose, "loose" },
312 { Opt_cache_strict, "strict" },
313 { Opt_cache_none, "none" },
Steve French83bbfa72019-08-27 23:58:54 -0500314 { Opt_cache_ro, "ro" },
Steve French41e033f2019-08-30 02:12:41 -0500315 { Opt_cache_rw, "singleclient" },
Jeff Layton15b6a472012-05-16 07:50:15 -0400316 { Opt_cache_err, NULL }
317};
318
Jeff Layton23db65f2012-05-15 12:20:51 -0400319static const match_table_t cifs_smb_version_tokens = {
320 { Smb_1, SMB1_VERSION_STRING },
Steve Frenchdd446b12012-11-28 23:21:06 -0600321 { Smb_20, SMB20_VERSION_STRING},
Steve French1080ef72011-02-24 18:07:19 +0000322 { Smb_21, SMB21_VERSION_STRING },
Steve Frenche4aa25e2012-10-01 12:26:22 -0500323 { Smb_30, SMB30_VERSION_STRING },
Steve French20b6d8b2013-06-12 22:48:41 -0500324 { Smb_302, SMB302_VERSION_STRING },
Kenneth D'souza4a3b38a2018-11-17 10:33:30 +0530325 { Smb_302, ALT_SMB302_VERSION_STRING },
Steve French5f7fbf72014-12-17 22:52:58 -0600326 { Smb_311, SMB311_VERSION_STRING },
Steve Frenchaab18932015-06-23 23:37:11 -0500327 { Smb_311, ALT_SMB311_VERSION_STRING },
Steve French9764c022017-09-17 10:41:35 -0500328 { Smb_3any, SMB3ANY_VERSION_STRING },
329 { Smb_default, SMBDEFAULT_VERSION_STRING },
Steve French5f7fbf72014-12-17 22:52:58 -0600330 { Smb_version_err, NULL }
Jeff Layton23db65f2012-05-15 12:20:51 -0400331};
332
Pavel Shilovskya9f1b852010-12-13 19:08:35 +0300333static int ip_connect(struct TCP_Server_Info *server);
334static int generic_ip_connect(struct TCP_Server_Info *server);
Jeff Laytonb647c352010-10-28 11:16:44 -0400335static void tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink);
Jeff Layton2de970f2010-10-06 19:51:12 -0400336static void cifs_prune_tlinks(struct work_struct *work);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200337static char *extract_hostname(const char *unc);
338
Paulo Alcantara28eb24f2018-11-20 15:16:36 -0200339/*
340 * Resolve hostname and set ip addr in tcp ses. Useful for hostnames that may
341 * get their ip addresses changed at some point.
342 *
343 * This should be called with server->srv_mutex held.
344 */
345#ifdef CONFIG_CIFS_DFS_UPCALL
346static int reconn_set_ipaddr(struct TCP_Server_Info *server)
347{
348 int rc;
349 int len;
350 char *unc, *ipaddr = NULL;
351
352 if (!server->hostname)
353 return -EINVAL;
354
355 len = strlen(server->hostname) + 3;
356
357 unc = kmalloc(len, GFP_KERNEL);
358 if (!unc) {
359 cifs_dbg(FYI, "%s: failed to create UNC path\n", __func__);
360 return -ENOMEM;
361 }
Ronnie Sahlberg74ea5f92019-02-09 09:51:11 +1000362 scnprintf(unc, len, "\\\\%s", server->hostname);
Paulo Alcantara28eb24f2018-11-20 15:16:36 -0200363
364 rc = dns_resolve_server_name_to_ip(unc, &ipaddr);
365 kfree(unc);
366
367 if (rc < 0) {
368 cifs_dbg(FYI, "%s: failed to resolve server part of %s to IP: %d\n",
369 __func__, server->hostname, rc);
370 return rc;
371 }
372
373 rc = cifs_convert_address((struct sockaddr *)&server->dstaddr, ipaddr,
374 strlen(ipaddr));
375 kfree(ipaddr);
376
377 return !rc ? -1 : 0;
378}
379#else
380static inline int reconn_set_ipaddr(struct TCP_Server_Info *server)
381{
382 return 0;
383}
384#endif
385
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200386#ifdef CONFIG_CIFS_DFS_UPCALL
387struct super_cb_data {
388 struct TCP_Server_Info *server;
389 struct cifs_sb_info *cifs_sb;
390};
391
392/* These functions must be called with server->srv_mutex held */
393
394static void super_cb(struct super_block *sb, void *arg)
395{
396 struct super_cb_data *d = arg;
397 struct cifs_sb_info *cifs_sb;
398 struct cifs_tcon *tcon;
399
400 if (d->cifs_sb)
401 return;
402
403 cifs_sb = CIFS_SB(sb);
404 tcon = cifs_sb_master_tcon(cifs_sb);
405 if (tcon->ses->server == d->server)
406 d->cifs_sb = cifs_sb;
407}
408
409static inline struct cifs_sb_info *
410find_super_by_tcp(struct TCP_Server_Info *server)
411{
412 struct super_cb_data d = {
413 .server = server,
414 .cifs_sb = NULL,
415 };
416
417 iterate_supers_type(&cifs_fs_type, super_cb, &d);
418 return d.cifs_sb ? d.cifs_sb : ERR_PTR(-ENOENT);
419}
420
421static void reconn_inval_dfs_target(struct TCP_Server_Info *server,
422 struct cifs_sb_info *cifs_sb,
423 struct dfs_cache_tgt_list *tgt_list,
424 struct dfs_cache_tgt_iterator **tgt_it)
425{
426 const char *name;
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200427
428 if (!cifs_sb || !cifs_sb->origin_fullpath || !tgt_list ||
429 !server->nr_targets)
430 return;
431
432 if (!*tgt_it) {
433 *tgt_it = dfs_cache_get_tgt_iterator(tgt_list);
434 } else {
435 *tgt_it = dfs_cache_get_next_tgt(tgt_list, *tgt_it);
436 if (!*tgt_it)
437 *tgt_it = dfs_cache_get_tgt_iterator(tgt_list);
438 }
439
440 cifs_dbg(FYI, "%s: UNC: %s\n", __func__, cifs_sb->origin_fullpath);
441
442 name = dfs_cache_get_tgt_name(*tgt_it);
443
444 kfree(server->hostname);
445
446 server->hostname = extract_hostname(name);
Dan Carpenter84288172019-01-05 15:25:29 +0300447 if (IS_ERR(server->hostname)) {
448 cifs_dbg(FYI,
449 "%s: failed to extract hostname from target: %ld\n",
450 __func__, PTR_ERR(server->hostname));
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200451 }
452}
453
454static inline int reconn_setup_dfs_targets(struct cifs_sb_info *cifs_sb,
455 struct dfs_cache_tgt_list *tl,
456 struct dfs_cache_tgt_iterator **it)
457{
458 if (!cifs_sb->origin_fullpath)
459 return -EOPNOTSUPP;
460 return dfs_cache_noreq_find(cifs_sb->origin_fullpath + 1, NULL, tl);
461}
462#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700463
Jeff Laytond5c56052008-12-01 18:42:33 -0500464/*
465 * cifs tcp session reconnection
466 *
467 * mark tcp session as reconnecting so temporarily locked
468 * mark all smb sessions as reconnecting for tcp session
469 * reconnect tcp session
470 * wake up waiters on reconnection? - (not needed currently)
471 */
Pavel Shilovsky28ea5292012-05-23 16:18:00 +0400472int
Linus Torvalds1da177e2005-04-16 15:20:36 -0700473cifs_reconnect(struct TCP_Server_Info *server)
474{
475 int rc = 0;
Jeff Laytonf1987b42008-11-15 11:12:47 -0500476 struct list_head *tmp, *tmp2;
Steve French96daf2b2011-05-27 04:34:02 +0000477 struct cifs_ses *ses;
478 struct cifs_tcon *tcon;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000479 struct mid_q_entry *mid_entry;
Jeff Layton3c1105d2011-05-22 07:09:13 -0400480 struct list_head retry_list;
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200481#ifdef CONFIG_CIFS_DFS_UPCALL
Paulo Alcantara23324402018-11-20 14:37:18 -0200482 struct cifs_sb_info *cifs_sb = NULL;
483 struct dfs_cache_tgt_list tgt_list = {0};
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200484 struct dfs_cache_tgt_iterator *tgt_it = NULL;
485#endif
Steve French50c2f752007-07-13 00:33:32 +0000486
Linus Torvalds1da177e2005-04-16 15:20:36 -0700487 spin_lock(&GlobalMid_Lock);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200488 server->nr_targets = 1;
489#ifdef CONFIG_CIFS_DFS_UPCALL
Ronnie Sahlberg61cabc72019-06-14 13:02:29 +1000490 spin_unlock(&GlobalMid_Lock);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200491 cifs_sb = find_super_by_tcp(server);
492 if (IS_ERR(cifs_sb)) {
493 rc = PTR_ERR(cifs_sb);
494 cifs_dbg(FYI, "%s: will not do DFS failover: rc = %d\n",
495 __func__, rc);
496 cifs_sb = NULL;
497 } else {
498 rc = reconn_setup_dfs_targets(cifs_sb, &tgt_list, &tgt_it);
Steve French55a7f002019-01-01 17:19:45 -0600499 if (rc && (rc != -EOPNOTSUPP)) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000500 cifs_server_dbg(VFS, "%s: no target servers for DFS failover\n",
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200501 __func__);
502 } else {
503 server->nr_targets = dfs_cache_get_nr_tgts(&tgt_list);
504 }
505 }
506 cifs_dbg(FYI, "%s: will retry %d target(s)\n", __func__,
507 server->nr_targets);
Ronnie Sahlberg61cabc72019-06-14 13:02:29 +1000508 spin_lock(&GlobalMid_Lock);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200509#endif
Jeff Layton469ee612008-10-16 18:46:39 +0000510 if (server->tcpStatus == CifsExiting) {
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000511 /* the demux thread will exit normally
Linus Torvalds1da177e2005-04-16 15:20:36 -0700512 next time through the loop */
513 spin_unlock(&GlobalMid_Lock);
514 return rc;
515 } else
516 server->tcpStatus = CifsNeedReconnect;
517 spin_unlock(&GlobalMid_Lock);
518 server->maxBuf = 0;
Pavel Shilovskyaa24d1e2011-12-27 16:23:34 +0400519 server->max_read = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700520
Steve French6e4d3bb2018-09-22 11:25:04 -0500521 cifs_dbg(FYI, "Mark tcp session as need reconnect\n");
Steve Frenchbf1fdeb2018-07-30 19:23:09 -0500522 trace_smb3_reconnect(server->CurrentMid, server->hostname);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700523
524 /* before reconnecting the tcp session, mark the smb session (uid)
525 and the tid bad so they are not used until reconnected */
Joe Perchesf96637b2013-05-04 22:12:25 -0500526 cifs_dbg(FYI, "%s: marking sessions and tcons for reconnect\n",
527 __func__);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +0530528 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -0500529 list_for_each(tmp, &server->smb_ses_list) {
Steve French96daf2b2011-05-27 04:34:02 +0000530 ses = list_entry(tmp, struct cifs_ses, smb_ses_list);
Jeff Layton14fbf502008-11-14 13:53:46 -0500531 ses->need_reconnect = true;
Jeff Laytonf1987b42008-11-15 11:12:47 -0500532 list_for_each(tmp2, &ses->tcon_list) {
Steve French96daf2b2011-05-27 04:34:02 +0000533 tcon = list_entry(tmp2, struct cifs_tcon, tcon_list);
Jeff Laytonf1987b42008-11-15 11:12:47 -0500534 tcon->need_reconnect = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700535 }
Aurelien Aptelb327a712018-01-24 13:46:10 +0100536 if (ses->tcon_ipc)
537 ses->tcon_ipc->need_reconnect = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +0530539 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500540
Linus Torvalds1da177e2005-04-16 15:20:36 -0700541 /* do not want to be sending data on a socket we are freeing */
Joe Perchesf96637b2013-05-04 22:12:25 -0500542 cifs_dbg(FYI, "%s: tearing down socket\n", __func__);
Jeff Layton72ca5452008-12-01 07:09:36 -0500543 mutex_lock(&server->srv_mutex);
Long Li1d2a4f52019-05-13 21:01:28 -0700544 if (server->ssocket) {
545 cifs_dbg(FYI, "State: 0x%x Flags: 0x%lx\n",
546 server->ssocket->state, server->ssocket->flags);
547 kernel_sock_shutdown(server->ssocket, SHUT_WR);
548 cifs_dbg(FYI, "Post shutdown state: 0x%x Flags: 0x%lx\n",
549 server->ssocket->state, server->ssocket->flags);
550 sock_release(server->ssocket);
551 server->ssocket = NULL;
552 }
553 server->sequence_number = 0;
554 server->session_estab = false;
555 kfree(server->session_key.response);
556 server->session_key.response = NULL;
557 server->session_key.len = 0;
558 server->lstrp = jiffies;
Long Li214bab42019-04-05 21:36:35 +0000559
560 /* mark submitted MIDs for retry and issue callback */
561 INIT_LIST_HEAD(&retry_list);
562 cifs_dbg(FYI, "%s: moving mids to private list\n", __func__);
563 spin_lock(&GlobalMid_Lock);
564 list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
565 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
566 if (mid_entry->mid_state == MID_REQUEST_SUBMITTED)
567 mid_entry->mid_state = MID_RETRY_NEEDED;
568 list_move(&mid_entry->qhead, &retry_list);
569 }
570 spin_unlock(&GlobalMid_Lock);
Long Li1d2a4f52019-05-13 21:01:28 -0700571 mutex_unlock(&server->srv_mutex);
Long Li214bab42019-04-05 21:36:35 +0000572
573 cifs_dbg(FYI, "%s: issuing mid callbacks\n", __func__);
574 list_for_each_safe(tmp, tmp2, &retry_list) {
575 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
576 list_del_init(&mid_entry->qhead);
577 mid_entry->callback(mid_entry);
578 }
579
Long Li1d2a4f52019-05-13 21:01:28 -0700580 if (cifs_rdma_enabled(server)) {
581 mutex_lock(&server->srv_mutex);
Long Li050b8c32019-04-04 11:35:42 -0500582 smbd_destroy(server);
Long Li1d2a4f52019-05-13 21:01:28 -0700583 mutex_unlock(&server->srv_mutex);
584 }
Jeff Layton3c1105d2011-05-22 07:09:13 -0400585
Jeff Layton7fdbaa12011-06-10 16:14:57 -0400586 do {
Steve French6c3d8902006-07-31 22:46:20 +0000587 try_to_freeze();
Pavel Shilovskya9f1b852010-12-13 19:08:35 +0300588
Jeff Layton73e216a2013-09-05 08:38:10 -0400589 mutex_lock(&server->srv_mutex);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200590 /*
591 * Set up next DFS target server (if any) for reconnect. If DFS
592 * feature is disabled, then we will retry last server we
593 * connected to before.
594 */
Long Li781a8052017-11-22 17:38:36 -0700595 if (cifs_rdma_enabled(server))
596 rc = smbd_reconnect(server);
597 else
598 rc = generic_ip_connect(server);
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000599 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500600 cifs_dbg(FYI, "reconnect error %d\n", rc);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200601#ifdef CONFIG_CIFS_DFS_UPCALL
602 reconn_inval_dfs_target(server, cifs_sb, &tgt_list,
603 &tgt_it);
604#endif
Paulo Alcantara28eb24f2018-11-20 15:16:36 -0200605 rc = reconn_set_ipaddr(server);
606 if (rc) {
607 cifs_dbg(FYI, "%s: failed to resolve hostname: %d\n",
608 __func__, rc);
609 }
Federico Sauter4afe2602015-03-17 17:45:28 +0100610 mutex_unlock(&server->srv_mutex);
Steve French0cb766a2005-04-28 22:41:11 -0700611 msleep(3000);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700612 } else {
613 atomic_inc(&tcpSesReconnectCount);
Pavel Shilovsky335b7b62019-01-16 11:12:41 -0800614 set_credits(server, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700615 spin_lock(&GlobalMid_Lock);
Jeff Layton469ee612008-10-16 18:46:39 +0000616 if (server->tcpStatus != CifsExiting)
Steve Frenchfd88ce92011-04-12 01:01:14 +0000617 server->tcpStatus = CifsNeedNegotiate;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000618 spin_unlock(&GlobalMid_Lock);
Federico Sauter4afe2602015-03-17 17:45:28 +0100619 mutex_unlock(&server->srv_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620 }
Jeff Layton7fdbaa12011-06-10 16:14:57 -0400621 } while (server->tcpStatus == CifsNeedReconnect);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500622
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200623#ifdef CONFIG_CIFS_DFS_UPCALL
624 if (tgt_it) {
625 rc = dfs_cache_noreq_update_tgthint(cifs_sb->origin_fullpath + 1,
626 tgt_it);
627 if (rc) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000628 cifs_server_dbg(VFS, "%s: failed to update DFS target hint: rc = %d\n",
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200629 __func__, rc);
630 }
631 rc = dfs_cache_update_vol(cifs_sb->origin_fullpath, server);
632 if (rc) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000633 cifs_server_dbg(VFS, "%s: failed to update vol info in DFS cache: rc = %d\n",
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200634 __func__, rc);
635 }
Paulo Alcantara23324402018-11-20 14:37:18 -0200636 dfs_cache_free_tgts(&tgt_list);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200637 }
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200638#endif
Sachin Prabhub8c60012016-10-20 19:52:24 -0400639 if (server->tcpStatus == CifsNeedNegotiate)
640 mod_delayed_work(cifsiod_wq, &server->echo, 0);
641
Linus Torvalds1da177e2005-04-16 15:20:36 -0700642 return rc;
643}
644
Jeff Laytonc74093b2011-01-11 07:24:23 -0500645static void
646cifs_echo_request(struct work_struct *work)
647{
648 int rc;
649 struct TCP_Server_Info *server = container_of(work,
650 struct TCP_Server_Info, echo.work);
Sachin Prabhub8c60012016-10-20 19:52:24 -0400651 unsigned long echo_interval;
Jeff Laytonc74093b2011-01-11 07:24:23 -0500652
Jeff Layton247ec9b2011-02-04 17:09:50 -0500653 /*
Sachin Prabhub8c60012016-10-20 19:52:24 -0400654 * If we need to renegotiate, set echo interval to zero to
655 * immediately call echo service where we can renegotiate.
656 */
657 if (server->tcpStatus == CifsNeedNegotiate)
658 echo_interval = 0;
659 else
660 echo_interval = server->echo_interval;
661
662 /*
663 * We cannot send an echo if it is disabled.
664 * Also, no need to ping if we got a response recently.
Jeff Layton247ec9b2011-02-04 17:09:50 -0500665 */
Steve French4fcd1812016-06-22 20:12:05 -0500666
667 if (server->tcpStatus == CifsNeedReconnect ||
Sachin Prabhub8c60012016-10-20 19:52:24 -0400668 server->tcpStatus == CifsExiting ||
669 server->tcpStatus == CifsNew ||
Pavel Shilovskyf6d76172012-05-25 14:47:16 +0400670 (server->ops->can_echo && !server->ops->can_echo(server)) ||
Steve Frenchadfeb3e2015-12-18 12:31:36 -0600671 time_before(jiffies, server->lstrp + echo_interval - HZ))
Jeff Laytonc74093b2011-01-11 07:24:23 -0500672 goto requeue_echo;
673
Pavel Shilovskyf6d76172012-05-25 14:47:16 +0400674 rc = server->ops->echo ? server->ops->echo(server) : -ENOSYS;
Jeff Laytonc74093b2011-01-11 07:24:23 -0500675 if (rc)
Joe Perchesf96637b2013-05-04 22:12:25 -0500676 cifs_dbg(FYI, "Unable to send echo request to server: %s\n",
677 server->hostname);
Jeff Laytonc74093b2011-01-11 07:24:23 -0500678
679requeue_echo:
Sachin Prabhub8c60012016-10-20 19:52:24 -0400680 queue_delayed_work(cifsiod_wq, &server->echo, server->echo_interval);
Jeff Laytonc74093b2011-01-11 07:24:23 -0500681}
682
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400683static bool
Jeff Layton2a37ef92011-10-19 15:29:23 -0400684allocate_buffers(struct TCP_Server_Info *server)
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400685{
Jeff Layton2a37ef92011-10-19 15:29:23 -0400686 if (!server->bigbuf) {
687 server->bigbuf = (char *)cifs_buf_get();
688 if (!server->bigbuf) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000689 cifs_server_dbg(VFS, "No memory for large SMB response\n");
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400690 msleep(3000);
691 /* retry will check if exiting */
692 return false;
693 }
Jeff Layton2a37ef92011-10-19 15:29:23 -0400694 } else if (server->large_buf) {
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400695 /* we are reusing a dirty large buf, clear its start */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400696 memset(server->bigbuf, 0, HEADER_SIZE(server));
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400697 }
698
Jeff Layton2a37ef92011-10-19 15:29:23 -0400699 if (!server->smallbuf) {
700 server->smallbuf = (char *)cifs_small_buf_get();
701 if (!server->smallbuf) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000702 cifs_server_dbg(VFS, "No memory for SMB response\n");
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400703 msleep(1000);
704 /* retry will check if exiting */
705 return false;
706 }
707 /* beginning of smb buffer is cleared in our buf_get */
708 } else {
709 /* if existing small buf clear beginning */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400710 memset(server->smallbuf, 0, HEADER_SIZE(server));
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400711 }
712
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400713 return true;
714}
715
Jeff Laytonba749e62011-10-11 06:41:32 -0400716static bool
717server_unresponsive(struct TCP_Server_Info *server)
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400718{
Pavel Shilovsky6dae51a2012-02-21 16:50:23 +0300719 /*
Ronnie Sahlbergf2caf902019-07-06 06:52:46 +1000720 * We need to wait 3 echo intervals to make sure we handle such
Pavel Shilovsky6dae51a2012-02-21 16:50:23 +0300721 * situations right:
722 * 1s client sends a normal SMB request
Ronnie Sahlbergbecc2ba2019-07-24 11:43:49 +1000723 * 2s client gets a response
Pavel Shilovsky6dae51a2012-02-21 16:50:23 +0300724 * 30s echo workqueue job pops, and decides we got a response recently
725 * and don't need to send another
726 * ...
727 * 65s kernel_recvmsg times out, and we see that we haven't gotten
728 * a response in >60s.
729 */
Samuel Cabrero76e75272017-07-11 12:44:39 +0200730 if ((server->tcpStatus == CifsGood ||
731 server->tcpStatus == CifsNeedNegotiate) &&
Ronnie Sahlbergf2caf902019-07-06 06:52:46 +1000732 time_after(jiffies, server->lstrp + 3 * server->echo_interval)) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000733 cifs_server_dbg(VFS, "has not responded in %lu seconds. Reconnecting...\n",
734 (3 * server->echo_interval) / HZ);
Jeff Laytonba749e62011-10-11 06:41:32 -0400735 cifs_reconnect(server);
736 wake_up(&server->response_q);
737 return true;
738 }
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400739
Jeff Laytonba749e62011-10-11 06:41:32 -0400740 return false;
741}
742
Pavel Shilovskyef68e832019-01-18 17:25:36 -0800743static inline bool
744zero_credits(struct TCP_Server_Info *server)
745{
746 int val;
747
748 spin_lock(&server->req_lock);
749 val = server->credits + server->echo_credits + server->oplock_credits;
750 if (server->in_flight == 0 && val == 0) {
751 spin_unlock(&server->req_lock);
752 return true;
753 }
754 spin_unlock(&server->req_lock);
755 return false;
756}
757
Al Viro71335662016-01-09 19:54:50 -0500758static int
759cifs_readv_from_socket(struct TCP_Server_Info *server, struct msghdr *smb_msg)
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400760{
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400761 int length = 0;
762 int total_read;
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400763
Al Viro71335662016-01-09 19:54:50 -0500764 smb_msg->msg_control = NULL;
765 smb_msg->msg_controllen = 0;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400766
Al Viro71335662016-01-09 19:54:50 -0500767 for (total_read = 0; msg_data_left(smb_msg); total_read += length) {
Jeff Layton95edcff2011-12-01 20:22:41 -0500768 try_to_freeze();
769
Pavel Shilovskyef68e832019-01-18 17:25:36 -0800770 /* reconnect if no credits and no requests in flight */
771 if (zero_credits(server)) {
772 cifs_reconnect(server);
773 return -ECONNABORTED;
774 }
775
Al Viro71335662016-01-09 19:54:50 -0500776 if (server_unresponsive(server))
777 return -ECONNABORTED;
Long Li2fef1372017-11-22 17:38:41 -0700778 if (cifs_rdma_enabled(server) && server->smbd_conn)
779 length = smbd_recv(server->smbd_conn, smb_msg);
780 else
781 length = sock_recvmsg(server->ssocket, smb_msg, 0);
Al Viro71335662016-01-09 19:54:50 -0500782
783 if (server->tcpStatus == CifsExiting)
784 return -ESHUTDOWN;
785
786 if (server->tcpStatus == CifsNeedReconnect) {
787 cifs_reconnect(server);
788 return -ECONNABORTED;
Jeff Laytonba749e62011-10-11 06:41:32 -0400789 }
790
Al Viro71335662016-01-09 19:54:50 -0500791 if (length == -ERESTARTSYS ||
792 length == -EAGAIN ||
793 length == -EINTR) {
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400794 /*
795 * Minimum sleep to prevent looping, allowing socket
796 * to clear and app threads to set tcpStatus
797 * CifsNeedReconnect if server hung.
798 */
799 usleep_range(1000, 2000);
800 length = 0;
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400801 continue;
Al Viro71335662016-01-09 19:54:50 -0500802 }
803
804 if (length <= 0) {
Al Viro09aab882015-11-13 03:00:17 -0500805 cifs_dbg(FYI, "Received no data or error: %d\n", length);
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400806 cifs_reconnect(server);
Al Viro71335662016-01-09 19:54:50 -0500807 return -ECONNABORTED;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400808 }
809 }
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400810 return total_read;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400811}
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400812
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400813int
814cifs_read_from_socket(struct TCP_Server_Info *server, char *buf,
815 unsigned int to_read)
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400816{
Al Viro71335662016-01-09 19:54:50 -0500817 struct msghdr smb_msg;
818 struct kvec iov = {.iov_base = buf, .iov_len = to_read};
David Howellsaa563d72018-10-20 00:57:56 +0100819 iov_iter_kvec(&smb_msg.msg_iter, READ, &iov, 1, to_read);
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400820
Al Viro71335662016-01-09 19:54:50 -0500821 return cifs_readv_from_socket(server, &smb_msg);
822}
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400823
Al Viro71335662016-01-09 19:54:50 -0500824int
825cifs_read_page_from_socket(struct TCP_Server_Info *server, struct page *page,
Long Li1dbe3462018-05-30 12:47:55 -0700826 unsigned int page_offset, unsigned int to_read)
Al Viro71335662016-01-09 19:54:50 -0500827{
828 struct msghdr smb_msg;
Long Li1dbe3462018-05-30 12:47:55 -0700829 struct bio_vec bv = {
830 .bv_page = page, .bv_len = to_read, .bv_offset = page_offset};
David Howellsaa563d72018-10-20 00:57:56 +0100831 iov_iter_bvec(&smb_msg.msg_iter, READ, &bv, 1, to_read);
Al Viro71335662016-01-09 19:54:50 -0500832 return cifs_readv_from_socket(server, &smb_msg);
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400833}
834
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400835static bool
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400836is_smb_response(struct TCP_Server_Info *server, unsigned char type)
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400837{
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400838 /*
839 * The first byte big endian of the length field,
840 * is actually not part of the length but the type
841 * with the most common, zero, as regular data.
842 */
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400843 switch (type) {
844 case RFC1002_SESSION_MESSAGE:
845 /* Regular SMB response */
846 return true;
847 case RFC1002_SESSION_KEEP_ALIVE:
Joe Perchesf96637b2013-05-04 22:12:25 -0500848 cifs_dbg(FYI, "RFC 1002 session keep alive\n");
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400849 break;
850 case RFC1002_POSITIVE_SESSION_RESPONSE:
Joe Perchesf96637b2013-05-04 22:12:25 -0500851 cifs_dbg(FYI, "RFC 1002 positive session response\n");
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400852 break;
853 case RFC1002_NEGATIVE_SESSION_RESPONSE:
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400854 /*
855 * We get this from Windows 98 instead of an error on
856 * SMB negprot response.
857 */
Joe Perchesf96637b2013-05-04 22:12:25 -0500858 cifs_dbg(FYI, "RFC 1002 negative session response\n");
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400859 /* give server a second to clean up */
860 msleep(1000);
861 /*
862 * Always try 445 first on reconnect since we get NACK
863 * on some if we ever connected to port 139 (the NACK
864 * is since we do not begin with RFC1001 session
865 * initialize frame).
866 */
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400867 cifs_set_port((struct sockaddr *)&server->dstaddr, CIFS_PORT);
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400868 cifs_reconnect(server);
869 wake_up(&server->response_q);
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400870 break;
871 default:
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000872 cifs_server_dbg(VFS, "RFC 1002 unknown response type 0x%x\n", type);
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400873 cifs_reconnect(server);
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400874 }
875
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400876 return false;
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400877}
878
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400879void
880dequeue_mid(struct mid_q_entry *mid, bool malformed)
Jeff Laytonea1f4502011-10-19 15:29:05 -0400881{
882#ifdef CONFIG_CIFS_STATS2
883 mid->when_received = jiffies;
884#endif
885 spin_lock(&GlobalMid_Lock);
886 if (!malformed)
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400887 mid->mid_state = MID_RESPONSE_RECEIVED;
Jeff Laytonea1f4502011-10-19 15:29:05 -0400888 else
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400889 mid->mid_state = MID_RESPONSE_MALFORMED;
Ronnie Sahlbergddf83af2018-08-30 10:12:59 +1000890 /*
891 * Trying to handle/dequeue a mid after the send_recv()
892 * function has finished processing it is a bug.
893 */
894 if (mid->mid_flags & MID_DELETED)
895 printk_once(KERN_WARNING
896 "trying to dequeue a deleted mid\n");
897 else
898 list_del_init(&mid->qhead);
Jeff Laytonea1f4502011-10-19 15:29:05 -0400899 spin_unlock(&GlobalMid_Lock);
900}
901
Jeff Laytonc8054eb2011-10-19 15:29:31 -0400902static void
903handle_mid(struct mid_q_entry *mid, struct TCP_Server_Info *server,
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400904 char *buf, int malformed)
Jeff Laytonea1f4502011-10-19 15:29:05 -0400905{
Pavel Shilovsky316cf942012-05-23 14:31:03 +0400906 if (server->ops->check_trans2 &&
907 server->ops->check_trans2(mid, server, buf, malformed))
Jeff Laytonc8054eb2011-10-19 15:29:31 -0400908 return;
Jeff Laytonea1f4502011-10-19 15:29:05 -0400909 mid->resp_buf = buf;
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400910 mid->large_buf = server->large_buf;
Jeff Layton2a37ef92011-10-19 15:29:23 -0400911 /* Was previous buf put in mpx struct for multi-rsp? */
912 if (!mid->multiRsp) {
913 /* smb buffer will be freed by user thread */
914 if (server->large_buf)
915 server->bigbuf = NULL;
916 else
917 server->smallbuf = NULL;
918 }
Jeff Laytonffc00e22011-10-19 15:29:13 -0400919 dequeue_mid(mid, malformed);
Pavel Shilovskyad69bae2011-08-01 13:19:43 +0400920}
921
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400922static void clean_demultiplex_info(struct TCP_Server_Info *server)
923{
924 int length;
925
926 /* take it off the list, if it's not already */
927 spin_lock(&cifs_tcp_ses_lock);
928 list_del_init(&server->tcp_ses_list);
929 spin_unlock(&cifs_tcp_ses_lock);
930
931 spin_lock(&GlobalMid_Lock);
932 server->tcpStatus = CifsExiting;
933 spin_unlock(&GlobalMid_Lock);
934 wake_up_all(&server->response_q);
935
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +0400936 /* check if we have blocked requests that need to free */
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +0300937 spin_lock(&server->req_lock);
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +0400938 if (server->credits <= 0)
939 server->credits = 1;
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +0300940 spin_unlock(&server->req_lock);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400941 /*
942 * Although there should not be any requests blocked on this queue it
943 * can not hurt to be paranoid and try to wake up requests that may
944 * haven been blocked when more than 50 at time were on the wire to the
945 * same server - they now will see the session is in exit state and get
946 * out of SendReceive.
947 */
948 wake_up_all(&server->request_q);
949 /* give those requests time to exit */
950 msleep(125);
Long Li050b8c32019-04-04 11:35:42 -0500951 if (cifs_rdma_enabled(server))
952 smbd_destroy(server);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400953 if (server->ssocket) {
954 sock_release(server->ssocket);
955 server->ssocket = NULL;
956 }
957
958 if (!list_empty(&server->pending_mid_q)) {
959 struct list_head dispose_list;
960 struct mid_q_entry *mid_entry;
961 struct list_head *tmp, *tmp2;
962
963 INIT_LIST_HEAD(&dispose_list);
964 spin_lock(&GlobalMid_Lock);
965 list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
966 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Joe Perchesf96637b2013-05-04 22:12:25 -0500967 cifs_dbg(FYI, "Clearing mid 0x%llx\n", mid_entry->mid);
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400968 mid_entry->mid_state = MID_SHUTDOWN;
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400969 list_move(&mid_entry->qhead, &dispose_list);
970 }
971 spin_unlock(&GlobalMid_Lock);
972
973 /* now walk dispose list and issue callbacks */
974 list_for_each_safe(tmp, tmp2, &dispose_list) {
975 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Joe Perchesf96637b2013-05-04 22:12:25 -0500976 cifs_dbg(FYI, "Callback mid 0x%llx\n", mid_entry->mid);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400977 list_del_init(&mid_entry->qhead);
978 mid_entry->callback(mid_entry);
979 }
980 /* 1/8th of sec is more than enough time for them to exit */
981 msleep(125);
982 }
983
984 if (!list_empty(&server->pending_mid_q)) {
985 /*
986 * mpx threads have not exited yet give them at least the smb
987 * send timeout time for long ops.
988 *
989 * Due to delays on oplock break requests, we need to wait at
990 * least 45 seconds before giving up on a request getting a
991 * response and going ahead and killing cifsd.
992 */
Joe Perchesf96637b2013-05-04 22:12:25 -0500993 cifs_dbg(FYI, "Wait for exit from demultiplex thread\n");
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400994 msleep(46000);
995 /*
996 * If threads still have not exited they are probably never
997 * coming home not much else we can do but free the memory.
998 */
999 }
1000
1001 kfree(server->hostname);
1002 kfree(server);
1003
1004 length = atomic_dec_return(&tcpSesAllocCount);
1005 if (length > 0)
David Rientjes11d83362015-04-14 15:48:21 -07001006 mempool_resize(cifs_req_poolp, length + cifs_min_rcv);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +04001007}
1008
Pavel Shilovskye7015fb2011-08-01 13:19:41 +04001009static int
Jeff Laytone9097ab2011-10-19 15:29:40 -04001010standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1011{
1012 int length;
1013 char *buf = server->smallbuf;
Ronnie Sahlberg2e964672018-04-09 18:06:26 +10001014 unsigned int pdu_length = server->pdu_size;
Jeff Laytone9097ab2011-10-19 15:29:40 -04001015
1016 /* make sure this will fit in a large buffer */
Ronnie Sahlberg93012bf2018-03-31 11:45:31 +11001017 if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server) -
1018 server->vals->header_preamble_size) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10001019 cifs_server_dbg(VFS, "SMB response too long (%u bytes)\n", pdu_length);
Jeff Laytone9097ab2011-10-19 15:29:40 -04001020 cifs_reconnect(server);
1021 wake_up(&server->response_q);
Pavel Shilovsky3fabaa22014-07-10 09:55:52 +04001022 return -ECONNABORTED;
Jeff Laytone9097ab2011-10-19 15:29:40 -04001023 }
1024
1025 /* switch to large buffer if too big for a small one */
1026 if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) {
1027 server->large_buf = true;
Pavel Shilovskyd4e48542012-03-23 14:28:02 -04001028 memcpy(server->bigbuf, buf, server->total_read);
Jeff Laytone9097ab2011-10-19 15:29:40 -04001029 buf = server->bigbuf;
Jeff Laytone9097ab2011-10-19 15:29:40 -04001030 }
1031
1032 /* now read the rest */
Pavel Shilovsky1887f602012-05-17 12:45:31 +04001033 length = cifs_read_from_socket(server, buf + HEADER_SIZE(server) - 1,
Ronnie Sahlberg93012bf2018-03-31 11:45:31 +11001034 pdu_length - HEADER_SIZE(server) + 1
1035 + server->vals->header_preamble_size);
1036
Jeff Laytone9097ab2011-10-19 15:29:40 -04001037 if (length < 0)
1038 return length;
1039 server->total_read += length;
1040
Pavel Shilovskyd4e48542012-03-23 14:28:02 -04001041 dump_smb(buf, server->total_read);
Jeff Laytone9097ab2011-10-19 15:29:40 -04001042
Pavel Shilovsky4326ed22016-11-17 15:24:46 -08001043 return cifs_handle_standard(server, mid);
1044}
1045
1046int
1047cifs_handle_standard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1048{
1049 char *buf = server->large_buf ? server->bigbuf : server->smallbuf;
1050 int length;
1051
Jeff Laytone9097ab2011-10-19 15:29:40 -04001052 /*
1053 * We know that we received enough to get to the MID as we
1054 * checked the pdu_length earlier. Now check to see
1055 * if the rest of the header is OK. We borrow the length
1056 * var for the rest of the loop to avoid a new stack var.
1057 *
1058 * 48 bytes is enough to display the header and a little bit
1059 * into the payload for debugging purposes.
1060 */
Steve French373512e2015-12-18 13:05:30 -06001061 length = server->ops->check_message(buf, server->total_read, server);
Jeff Laytone9097ab2011-10-19 15:29:40 -04001062 if (length != 0)
1063 cifs_dump_mem("Bad SMB: ", buf,
1064 min_t(unsigned int, server->total_read, 48));
1065
Pavel Shilovsky511c54a2017-07-08 14:32:00 -07001066 if (server->ops->is_session_expired &&
1067 server->ops->is_session_expired(buf)) {
1068 cifs_reconnect(server);
1069 wake_up(&server->response_q);
1070 return -1;
1071 }
1072
Pavel Shilovsky2e44b282012-09-18 16:20:33 -07001073 if (server->ops->is_status_pending &&
Pavel Shilovsky66265f12019-01-23 17:11:16 -08001074 server->ops->is_status_pending(buf, server))
Pavel Shilovsky2e44b282012-09-18 16:20:33 -07001075 return -1;
1076
Jeff Laytonff4fa4a2012-02-07 06:31:05 -05001077 if (!mid)
1078 return length;
Jeff Laytone9097ab2011-10-19 15:29:40 -04001079
Pavel Shilovskyd4e48542012-03-23 14:28:02 -04001080 handle_mid(mid, server, buf, length);
Jeff Laytonff4fa4a2012-02-07 06:31:05 -05001081 return 0;
Jeff Laytone9097ab2011-10-19 15:29:40 -04001082}
1083
Ronnie Sahlbergeca00452019-02-05 12:56:44 +10001084static void
1085smb2_add_credits_from_hdr(char *buffer, struct TCP_Server_Info *server)
1086{
1087 struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buffer;
1088
1089 /*
1090 * SMB1 does not use credits.
1091 */
1092 if (server->vals->header_preamble_size)
1093 return;
1094
1095 if (shdr->CreditRequest) {
1096 spin_lock(&server->req_lock);
1097 server->credits += le16_to_cpu(shdr->CreditRequest);
1098 spin_unlock(&server->req_lock);
1099 wake_up(&server->request_q);
1100 }
1101}
1102
1103
Jeff Laytone9097ab2011-10-19 15:29:40 -04001104static int
Al Viro7c97c202011-06-21 08:51:28 -04001105cifs_demultiplex_thread(void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001106{
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001107 int i, num_mids, length;
Al Viro7c97c202011-06-21 08:51:28 -04001108 struct TCP_Server_Info *server = p;
Jeff Layton2a37ef92011-10-19 15:29:23 -04001109 unsigned int pdu_length;
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001110 unsigned int next_offset;
Jeff Layton2a37ef92011-10-19 15:29:23 -04001111 char *buf = NULL;
Steve Frencha5c3e1c2014-09-16 04:16:19 -05001112 struct task_struct *task_to_wake = NULL;
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001113 struct mid_q_entry *mids[MAX_COMPOUND];
1114 char *bufs[MAX_COMPOUND];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001115
Linus Torvalds1da177e2005-04-16 15:20:36 -07001116 current->flags |= PF_MEMALLOC;
Joe Perchesf96637b2013-05-04 22:12:25 -05001117 cifs_dbg(FYI, "Demultiplex PID: %d\n", task_pid_nr(current));
Jeff Layton93d0ec82008-08-02 08:00:48 -04001118
1119 length = atomic_inc_return(&tcpSesAllocCount);
1120 if (length > 1)
David Rientjes11d83362015-04-14 15:48:21 -07001121 mempool_resize(cifs_req_poolp, length + cifs_min_rcv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001122
Rafael J. Wysocki83144182007-07-17 04:03:35 -07001123 set_freezable();
Eric W. Biederman33da8e72019-08-16 12:33:54 -05001124 allow_kernel_signal(SIGKILL);
Jeff Layton469ee612008-10-16 18:46:39 +00001125 while (server->tcpStatus != CifsExiting) {
Steve Frenchede13272005-08-30 20:10:14 -07001126 if (try_to_freeze())
1127 continue;
Steve Frenchb8643e12005-04-28 22:41:07 -07001128
Jeff Layton2a37ef92011-10-19 15:29:23 -04001129 if (!allocate_buffers(server))
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +04001130 continue;
Steve Frenchb8643e12005-04-28 22:41:07 -07001131
Jeff Layton2a37ef92011-10-19 15:29:23 -04001132 server->large_buf = false;
Jeff Layton2a37ef92011-10-19 15:29:23 -04001133 buf = server->smallbuf;
Steve Frenchf01d5e12007-08-30 21:13:31 +00001134 pdu_length = 4; /* enough to get RFC1001 header */
Steve Frenchfda35942011-01-20 18:06:34 +00001135
Jeff Laytone28bc5b2011-10-19 15:30:07 -04001136 length = cifs_read_from_socket(server, buf, pdu_length);
Jeff Laytona52c1eb2011-10-11 06:41:32 -04001137 if (length < 0)
Steve Frenchfda35942011-01-20 18:06:34 +00001138 continue;
Ronnie Sahlberg977b6172018-06-01 10:53:02 +10001139
1140 if (server->vals->header_preamble_size == 0)
1141 server->total_read = 0;
1142 else
1143 server->total_read = length;
Steve French67010fb2005-04-28 22:41:09 -07001144
Pavel Shilovsky98bac622011-08-01 13:19:42 +04001145 /*
1146 * The right amount was read from socket - 4 bytes,
1147 * so we can now interpret the length field.
1148 */
Pavel Shilovskyd4e48542012-03-23 14:28:02 -04001149 pdu_length = get_rfc1002_length(buf);
Steve French46810cb2005-04-28 22:41:09 -07001150
Joe Perchesf96637b2013-05-04 22:12:25 -05001151 cifs_dbg(FYI, "RFC1002 header 0x%x\n", pdu_length);
Jeff Laytonfe11e4c2011-10-11 06:41:32 -04001152 if (!is_smb_response(server, buf[0]))
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001153 continue;
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001154next_pdu:
1155 server->pdu_size = pdu_length;
Steve Frenche4eb2952005-04-28 22:41:09 -07001156
Jeff Layton89482a52011-10-19 15:28:57 -04001157 /* make sure we have enough to get to the MID */
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001158 if (server->pdu_size < HEADER_SIZE(server) - 1 -
Ronnie Sahlberg93012bf2018-03-31 11:45:31 +11001159 server->vals->header_preamble_size) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10001160 cifs_server_dbg(VFS, "SMB response too short (%u bytes)\n",
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001161 server->pdu_size);
Jeff Layton89482a52011-10-19 15:28:57 -04001162 cifs_reconnect(server);
1163 wake_up(&server->response_q);
1164 continue;
Steve Frenche4eb2952005-04-28 22:41:09 -07001165 }
Pavel Shilovskye7015fb2011-08-01 13:19:41 +04001166
Jeff Layton89482a52011-10-19 15:28:57 -04001167 /* read down to the MID */
Ronnie Sahlberg93012bf2018-03-31 11:45:31 +11001168 length = cifs_read_from_socket(server,
1169 buf + server->vals->header_preamble_size,
1170 HEADER_SIZE(server) - 1
1171 - server->vals->header_preamble_size);
Jeff Layton89482a52011-10-19 15:28:57 -04001172 if (length < 0)
1173 continue;
Jeff Layton2a37ef92011-10-19 15:29:23 -04001174 server->total_read += length;
Jeff Layton89482a52011-10-19 15:28:57 -04001175
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001176 if (server->ops->next_header) {
1177 next_offset = server->ops->next_header(buf);
1178 if (next_offset)
1179 server->pdu_size = next_offset;
1180 }
1181
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001182 memset(mids, 0, sizeof(mids));
1183 memset(bufs, 0, sizeof(bufs));
1184 num_mids = 0;
1185
Pavel Shilovsky9bb17e02016-11-17 15:24:34 -08001186 if (server->ops->is_transform_hdr &&
1187 server->ops->receive_transform &&
1188 server->ops->is_transform_hdr(buf)) {
1189 length = server->ops->receive_transform(server,
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001190 mids,
1191 bufs,
1192 &num_mids);
Pavel Shilovsky9bb17e02016-11-17 15:24:34 -08001193 } else {
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001194 mids[0] = server->ops->find_mid(server, buf);
1195 bufs[0] = buf;
Steve French7af929d2018-10-02 18:54:09 -05001196 num_mids = 1;
Jeff Laytonc8054eb2011-10-19 15:29:31 -04001197
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001198 if (!mids[0] || !mids[0]->receive)
1199 length = standard_receive3(server, mids[0]);
Pavel Shilovsky9bb17e02016-11-17 15:24:34 -08001200 else
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001201 length = mids[0]->receive(server, mids[0]);
Pavel Shilovsky9bb17e02016-11-17 15:24:34 -08001202 }
Jeff Layton44d22d82011-10-19 15:29:49 -04001203
Lars Persson696e4202018-06-25 14:05:25 +02001204 if (length < 0) {
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001205 for (i = 0; i < num_mids; i++)
1206 if (mids[i])
1207 cifs_mid_q_entry_release(mids[i]);
Steve Frenche4eb2952005-04-28 22:41:09 -07001208 continue;
Lars Persson696e4202018-06-25 14:05:25 +02001209 }
Steve Frenche4eb2952005-04-28 22:41:09 -07001210
Steve Frenchfda35942011-01-20 18:06:34 +00001211 server->lstrp = jiffies;
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001212
1213 for (i = 0; i < num_mids; i++) {
1214 if (mids[i] != NULL) {
1215 mids[i]->resp_buf_size = server->pdu_size;
1216 if ((mids[i]->mid_flags & MID_WAIT_CANCELLED) &&
1217 mids[i]->mid_state == MID_RESPONSE_RECEIVED &&
1218 server->ops->handle_cancelled_mid)
1219 server->ops->handle_cancelled_mid(
1220 mids[i]->resp_buf,
Sachin Prabhu38bd4902017-03-03 15:41:38 -08001221 server);
1222
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001223 if (!mids[i]->multiRsp || mids[i]->multiEnd)
1224 mids[i]->callback(mids[i]);
Lars Persson696e4202018-06-25 14:05:25 +02001225
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001226 cifs_mid_q_entry_release(mids[i]);
1227 } else if (server->ops->is_oplock_break &&
1228 server->ops->is_oplock_break(bufs[i],
1229 server)) {
Ronnie Sahlbergeca00452019-02-05 12:56:44 +10001230 smb2_add_credits_from_hdr(bufs[i], server);
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001231 cifs_dbg(FYI, "Received oplock break\n");
1232 } else {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10001233 cifs_server_dbg(VFS, "No task to wake, unknown frame "
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001234 "received! NumMids %d\n",
1235 atomic_read(&midCount));
1236 cifs_dump_mem("Received Data is: ", bufs[i],
1237 HEADER_SIZE(server));
Ronnie Sahlberg3e272572019-07-06 06:43:08 +10001238 smb2_add_credits_from_hdr(bufs[i], server);
Steve French39798772006-05-31 22:40:51 +00001239#ifdef CONFIG_CIFS_DEBUG2
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001240 if (server->ops->dump_detail)
1241 server->ops->dump_detail(bufs[i],
1242 server);
1243 cifs_dump_mids(server);
Steve French39798772006-05-31 22:40:51 +00001244#endif /* CIFS_DEBUG2 */
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001245 }
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001246 }
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001247
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001248 if (pdu_length > server->pdu_size) {
1249 if (!allocate_buffers(server))
1250 continue;
1251 pdu_length -= server->pdu_size;
1252 server->total_read = 0;
1253 server->large_buf = false;
1254 buf = server->smallbuf;
1255 goto next_pdu;
Steve Frenche4eb2952005-04-28 22:41:09 -07001256 }
1257 } /* end while !EXITING */
1258
Justin P. Mattockfd62cb72011-02-24 22:15:02 -08001259 /* buffer usually freed in free_mid - need to free it here on exit */
Jeff Layton2a37ef92011-10-19 15:29:23 -04001260 cifs_buf_release(server->bigbuf);
1261 if (server->smallbuf) /* no sense logging a debug message if NULL */
1262 cifs_small_buf_release(server->smallbuf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001263
Steve Frencha5c3e1c2014-09-16 04:16:19 -05001264 task_to_wake = xchg(&server->tsk, NULL);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +04001265 clean_demultiplex_info(server);
Steve Frencha5c3e1c2014-09-16 04:16:19 -05001266
1267 /* if server->tsk was NULL then wait for a signal before exiting */
1268 if (!task_to_wake) {
1269 set_current_state(TASK_INTERRUPTIBLE);
1270 while (!signal_pending(current)) {
1271 schedule();
1272 set_current_state(TASK_INTERRUPTIBLE);
1273 }
1274 set_current_state(TASK_RUNNING);
1275 }
1276
Jeff Layton0468a2c2008-12-01 07:09:35 -05001277 module_put_and_exit(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001278}
1279
Jeff Laytonc359cf32007-11-16 22:22:06 +00001280/* extract the host portion of the UNC string */
1281static char *
1282extract_hostname(const char *unc)
1283{
1284 const char *src;
1285 char *dst, *delim;
1286 unsigned int len;
1287
1288 /* skip double chars at beginning of string */
1289 /* BB: check validity of these bytes? */
Paulo Alcantarac34fea52018-11-14 14:03:40 -02001290 if (strlen(unc) < 3)
1291 return ERR_PTR(-EINVAL);
1292 for (src = unc; *src && *src == '\\'; src++)
1293 ;
1294 if (!*src)
1295 return ERR_PTR(-EINVAL);
Jeff Laytonc359cf32007-11-16 22:22:06 +00001296
1297 /* delimiter between hostname and sharename is always '\\' now */
1298 delim = strchr(src, '\\');
1299 if (!delim)
1300 return ERR_PTR(-EINVAL);
1301
1302 len = delim - src;
1303 dst = kmalloc((len + 1), GFP_KERNEL);
1304 if (dst == NULL)
1305 return ERR_PTR(-ENOMEM);
1306
1307 memcpy(dst, src, len);
1308 dst[len] = '\0';
1309
1310 return dst;
1311}
1312
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001313static int get_option_ul(substring_t args[], unsigned long *option)
1314{
1315 int rc;
1316 char *string;
1317
1318 string = match_strdup(args);
1319 if (string == NULL)
1320 return -ENOMEM;
Sachin Prabhubfa890a2012-04-13 14:04:32 +01001321 rc = kstrtoul(string, 0, option);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001322 kfree(string);
1323
1324 return rc;
1325}
1326
Eric W. Biederman3da46562013-02-06 01:37:39 -08001327static int get_option_uid(substring_t args[], kuid_t *result)
1328{
1329 unsigned long value;
1330 kuid_t uid;
1331 int rc;
1332
1333 rc = get_option_ul(args, &value);
1334 if (rc)
1335 return rc;
1336
1337 uid = make_kuid(current_user_ns(), value);
1338 if (!uid_valid(uid))
1339 return -EINVAL;
1340
1341 *result = uid;
1342 return 0;
1343}
1344
1345static int get_option_gid(substring_t args[], kgid_t *result)
1346{
1347 unsigned long value;
1348 kgid_t gid;
1349 int rc;
1350
1351 rc = get_option_ul(args, &value);
1352 if (rc)
1353 return rc;
1354
1355 gid = make_kgid(current_user_ns(), value);
1356 if (!gid_valid(gid))
1357 return -EINVAL;
1358
1359 *result = gid;
1360 return 0;
1361}
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001362
1363static int cifs_parse_security_flavors(char *value,
1364 struct smb_vol *vol)
1365{
1366
1367 substring_t args[MAX_OPT_ARGS];
1368
Jeff Layton1e3cc572013-06-10 17:12:23 -05001369 /*
1370 * With mount options, the last one should win. Reset any existing
1371 * settings back to default.
1372 */
1373 vol->sectype = Unspecified;
1374 vol->sign = false;
1375
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001376 switch (match_token(value, cifs_secflavor_tokens, args)) {
Jeff Layton3f618222013-06-12 19:52:14 -05001377 case Opt_sec_krb5p:
1378 cifs_dbg(VFS, "sec=krb5p is not supported!\n");
1379 return 1;
1380 case Opt_sec_krb5i:
1381 vol->sign = true;
1382 /* Fallthrough */
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001383 case Opt_sec_krb5:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001384 vol->sectype = Kerberos;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001385 break;
1386 case Opt_sec_ntlmsspi:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001387 vol->sign = true;
Jeff Layton3f618222013-06-12 19:52:14 -05001388 /* Fallthrough */
1389 case Opt_sec_ntlmssp:
1390 vol->sectype = RawNTLMSSP;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001391 break;
1392 case Opt_sec_ntlmi:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001393 vol->sign = true;
Jeff Layton3f618222013-06-12 19:52:14 -05001394 /* Fallthrough */
1395 case Opt_ntlm:
1396 vol->sectype = NTLM;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001397 break;
1398 case Opt_sec_ntlmv2i:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001399 vol->sign = true;
Jeff Layton3f618222013-06-12 19:52:14 -05001400 /* Fallthrough */
1401 case Opt_sec_ntlmv2:
1402 vol->sectype = NTLMv2;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001403 break;
1404#ifdef CONFIG_CIFS_WEAK_PW_HASH
1405 case Opt_sec_lanman:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001406 vol->sectype = LANMAN;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001407 break;
1408#endif
1409 case Opt_sec_none:
1410 vol->nullauth = 1;
1411 break;
1412 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05001413 cifs_dbg(VFS, "bad security option: %s\n", value);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001414 return 1;
1415 }
1416
1417 return 0;
1418}
1419
Linus Torvalds1da177e2005-04-16 15:20:36 -07001420static int
Jeff Layton15b6a472012-05-16 07:50:15 -04001421cifs_parse_cache_flavor(char *value, struct smb_vol *vol)
1422{
1423 substring_t args[MAX_OPT_ARGS];
1424
1425 switch (match_token(value, cifs_cacheflavor_tokens, args)) {
1426 case Opt_cache_loose:
1427 vol->direct_io = false;
1428 vol->strict_io = false;
Steve French83bbfa72019-08-27 23:58:54 -05001429 vol->cache_ro = false;
Steve French41e033f2019-08-30 02:12:41 -05001430 vol->cache_rw = false;
Jeff Layton15b6a472012-05-16 07:50:15 -04001431 break;
1432 case Opt_cache_strict:
1433 vol->direct_io = false;
1434 vol->strict_io = true;
Steve French83bbfa72019-08-27 23:58:54 -05001435 vol->cache_ro = false;
Steve French41e033f2019-08-30 02:12:41 -05001436 vol->cache_rw = false;
Jeff Layton15b6a472012-05-16 07:50:15 -04001437 break;
1438 case Opt_cache_none:
1439 vol->direct_io = true;
1440 vol->strict_io = false;
Steve French83bbfa72019-08-27 23:58:54 -05001441 vol->cache_ro = false;
Steve French41e033f2019-08-30 02:12:41 -05001442 vol->cache_rw = false;
Steve French83bbfa72019-08-27 23:58:54 -05001443 break;
1444 case Opt_cache_ro:
1445 vol->direct_io = false;
1446 vol->strict_io = false;
1447 vol->cache_ro = true;
Steve French41e033f2019-08-30 02:12:41 -05001448 vol->cache_rw = false;
1449 break;
1450 case Opt_cache_rw:
1451 vol->direct_io = false;
1452 vol->strict_io = false;
1453 vol->cache_ro = false;
1454 vol->cache_rw = true;
Jeff Layton15b6a472012-05-16 07:50:15 -04001455 break;
1456 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05001457 cifs_dbg(VFS, "bad cache= option: %s\n", value);
Jeff Layton15b6a472012-05-16 07:50:15 -04001458 return 1;
1459 }
1460 return 0;
1461}
1462
1463static int
Steve Frenchc7c137b2018-06-06 17:59:29 -05001464cifs_parse_smb_version(char *value, struct smb_vol *vol, bool is_smb3)
Jeff Layton23db65f2012-05-15 12:20:51 -04001465{
1466 substring_t args[MAX_OPT_ARGS];
1467
1468 switch (match_token(value, cifs_smb_version_tokens, args)) {
Steve French74204512018-06-19 14:34:08 -05001469#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
Jeff Layton23db65f2012-05-15 12:20:51 -04001470 case Smb_1:
Steve Frenchf92a7202018-05-24 04:11:07 -05001471 if (disable_legacy_dialects) {
1472 cifs_dbg(VFS, "mount with legacy dialect disabled\n");
1473 return 1;
1474 }
Steve Frenchc7c137b2018-06-06 17:59:29 -05001475 if (is_smb3) {
1476 cifs_dbg(VFS, "vers=1.0 (cifs) not permitted when mounting with smb3\n");
1477 return 1;
1478 }
Jeff Layton23db65f2012-05-15 12:20:51 -04001479 vol->ops = &smb1_operations;
1480 vol->vals = &smb1_values;
1481 break;
Steve Frenchdd446b12012-11-28 23:21:06 -06001482 case Smb_20:
Steve Frenchf92a7202018-05-24 04:11:07 -05001483 if (disable_legacy_dialects) {
1484 cifs_dbg(VFS, "mount with legacy dialect disabled\n");
1485 return 1;
1486 }
Steve Frenchc7c137b2018-06-06 17:59:29 -05001487 if (is_smb3) {
1488 cifs_dbg(VFS, "vers=2.0 not permitted when mounting with smb3\n");
1489 return 1;
1490 }
Pavel Shilovsky53ef1012013-09-05 16:11:28 +04001491 vol->ops = &smb20_operations;
Steve Frenchdd446b12012-11-28 23:21:06 -06001492 vol->vals = &smb20_values;
1493 break;
Steve French74204512018-06-19 14:34:08 -05001494#else
1495 case Smb_1:
1496 cifs_dbg(VFS, "vers=1.0 (cifs) mount not permitted when legacy dialects disabled\n");
1497 return 1;
1498 case Smb_20:
1499 cifs_dbg(VFS, "vers=2.0 mount not permitted when legacy dialects disabled\n");
1500 return 1;
1501#endif /* CIFS_ALLOW_INSECURE_LEGACY */
Steve French1080ef72011-02-24 18:07:19 +00001502 case Smb_21:
1503 vol->ops = &smb21_operations;
1504 vol->vals = &smb21_values;
1505 break;
Steve Frenche4aa25e2012-10-01 12:26:22 -05001506 case Smb_30:
Steve French38107d42012-12-08 22:08:06 -06001507 vol->ops = &smb30_operations;
Steve Frenche4aa25e2012-10-01 12:26:22 -05001508 vol->vals = &smb30_values;
1509 break;
Steve French20b6d8b2013-06-12 22:48:41 -05001510 case Smb_302:
1511 vol->ops = &smb30_operations; /* currently identical with 3.0 */
1512 vol->vals = &smb302_values;
1513 break;
Steve French5f7fbf72014-12-17 22:52:58 -06001514 case Smb_311:
Steve Frenchaab18932015-06-23 23:37:11 -05001515 vol->ops = &smb311_operations;
Steve French5f7fbf72014-12-17 22:52:58 -06001516 vol->vals = &smb311_values;
1517 break;
Steve French9764c022017-09-17 10:41:35 -05001518 case Smb_3any:
1519 vol->ops = &smb30_operations; /* currently identical with 3.0 */
1520 vol->vals = &smb3any_values;
1521 break;
1522 case Smb_default:
1523 vol->ops = &smb30_operations; /* currently identical with 3.0 */
1524 vol->vals = &smbdefault_values;
1525 break;
Jeff Layton23db65f2012-05-15 12:20:51 -04001526 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05001527 cifs_dbg(VFS, "Unknown vers= option specified: %s\n", value);
Jeff Layton23db65f2012-05-15 12:20:51 -04001528 return 1;
1529 }
1530 return 0;
1531}
1532
Jeff Laytond387a5c2012-12-10 06:10:46 -05001533/*
1534 * Parse a devname into substrings and populate the vol->UNC and vol->prepath
1535 * fields with the result. Returns 0 on success and an error otherwise.
1536 */
1537static int
1538cifs_parse_devname(const char *devname, struct smb_vol *vol)
1539{
1540 char *pos;
1541 const char *delims = "/\\";
1542 size_t len;
1543
Yao Liu68e26722019-01-28 19:47:28 +08001544 if (unlikely(!devname || !*devname)) {
1545 cifs_dbg(VFS, "Device name not specified.\n");
1546 return -EINVAL;
1547 }
1548
Jeff Laytond387a5c2012-12-10 06:10:46 -05001549 /* make sure we have a valid UNC double delimiter prefix */
1550 len = strspn(devname, delims);
1551 if (len != 2)
1552 return -EINVAL;
1553
1554 /* find delimiter between host and sharename */
1555 pos = strpbrk(devname + 2, delims);
1556 if (!pos)
1557 return -EINVAL;
1558
1559 /* skip past delimiter */
1560 ++pos;
1561
1562 /* now go until next delimiter or end of string */
1563 len = strcspn(pos, delims);
1564
1565 /* move "pos" up to delimiter or NULL */
1566 pos += len;
1567 vol->UNC = kstrndup(devname, pos - devname, GFP_KERNEL);
1568 if (!vol->UNC)
1569 return -ENOMEM;
1570
1571 convert_delimiter(vol->UNC, '\\');
1572
Sachin Prabhu11e31642016-02-08 13:44:01 +05301573 /* skip any delimiter */
1574 if (*pos == '/' || *pos == '\\')
1575 pos++;
1576
1577 /* If pos is NULL then no prepath */
1578 if (!*pos)
Jeff Laytond387a5c2012-12-10 06:10:46 -05001579 return 0;
1580
1581 vol->prepath = kstrdup(pos, GFP_KERNEL);
1582 if (!vol->prepath)
1583 return -ENOMEM;
1584
1585 return 0;
1586}
1587
Jeff Layton23db65f2012-05-15 12:20:51 -04001588static int
Sean Finneyb9468452011-04-11 13:19:32 +00001589cifs_parse_mount_options(const char *mountdata, const char *devname,
Steve Frenchc7c137b2018-06-06 17:59:29 -05001590 struct smb_vol *vol, bool is_smb3)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001591{
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001592 char *data, *end;
Vasily Averin957df452011-06-06 11:33:12 +04001593 char *mountdata_copy = NULL, *options;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001594 unsigned int temp_len, i, j;
1595 char separator[2];
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001596 short int override_uid = -1;
1597 short int override_gid = -1;
1598 bool uid_specified = false;
1599 bool gid_specified = false;
Jeff Laytond8162552012-03-23 14:40:56 -04001600 bool sloppy = false;
1601 char *invalid = NULL;
Jeff Layton88463992010-11-22 15:31:03 -05001602 char *nodename = utsname()->nodename;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001603 char *string = NULL;
1604 char *tmp_end, *value;
1605 char delim;
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001606 bool got_ip = false;
Steve French7e682f72017-08-31 21:34:24 -05001607 bool got_version = false;
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001608 unsigned short port = 0;
1609 struct sockaddr *dstaddr = (struct sockaddr *)&vol->dstaddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001610
1611 separator[0] = ',';
Steve French50c2f752007-07-13 00:33:32 +00001612 separator[1] = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001613 delim = separator[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001614
Jeff Layton6ee95422012-11-26 11:09:57 -05001615 /* ensure we always start with zeroed-out smb_vol */
1616 memset(vol, 0, sizeof(*vol));
1617
Jeff Layton88463992010-11-22 15:31:03 -05001618 /*
1619 * does not have to be perfect mapping since field is
1620 * informational, only used for servers that do not support
1621 * port 445 and it can be overridden at mount time
1622 */
Jeff Layton1397f2e2011-01-07 11:30:28 -05001623 memset(vol->source_rfc1001_name, 0x20, RFC1001_NAME_LEN);
1624 for (i = 0; i < strnlen(nodename, RFC1001_NAME_LEN); i++)
Jeff Layton88463992010-11-22 15:31:03 -05001625 vol->source_rfc1001_name[i] = toupper(nodename[i]);
1626
Jeff Layton1397f2e2011-01-07 11:30:28 -05001627 vol->source_rfc1001_name[RFC1001_NAME_LEN] = 0;
Steve Frencha10faeb22005-08-22 21:38:31 -07001628 /* null target name indicates to use *SMBSERVR default called name
1629 if we end up sending RFC1001 session initialize */
1630 vol->target_rfc1001_name[0] = 0;
Jeff Layton3e4b3e12010-07-19 18:00:17 -04001631 vol->cred_uid = current_uid();
1632 vol->linux_uid = current_uid();
David Howellsa001e5b2008-11-14 10:38:47 +11001633 vol->linux_gid = current_gid();
Steve Frenche8506d22019-02-28 21:32:15 -06001634 vol->bsize = 1024 * 1024; /* can improve cp performance significantly */
Steve French2baa2682014-09-27 02:19:01 -05001635 /*
1636 * default to SFM style remapping of seven reserved characters
1637 * unless user overrides it or we negotiate CIFS POSIX where
1638 * it is unnecessary. Can not simultaneously use more than one mapping
1639 * since then readdir could list files that open could not open
1640 */
1641 vol->remap = true;
1642
Jeff Laytonf55ed1a2009-05-26 16:28:11 -04001643 /* default to only allowing write access to owner of the mount */
1644 vol->dir_mode = vol->file_mode = S_IRUGO | S_IXUGO | S_IWUSR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001645
1646 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
Jeremy Allisonac670552005-06-22 17:26:35 -07001647 /* default is always to request posix paths. */
1648 vol->posix_paths = 1;
Jeff Laytona0c92172009-05-27 15:40:47 -04001649 /* default to using server inode numbers where available */
1650 vol->server_ino = 1;
Jeremy Allisonac670552005-06-22 17:26:35 -07001651
Jeff Layton1b359202012-09-19 15:20:27 -07001652 /* default is to use strict cifs caching semantics */
1653 vol->strict_io = true;
1654
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301655 vol->actimeo = CIFS_DEF_ACTIMEO;
1656
Steve Frenchca567eb2019-03-29 16:31:07 -05001657 /* Most clients set timeout to 0, allows server to use its default */
1658 vol->handle_timeout = 0; /* See MS-SMB2 spec section 2.2.14.2.12 */
1659
Steve French9764c022017-09-17 10:41:35 -05001660 /* offer SMB2.1 and later (SMB3 etc). Secure and widely accepted */
1661 vol->ops = &smb30_operations;
1662 vol->vals = &smbdefault_values;
Jeff Layton23db65f2012-05-15 12:20:51 -04001663
Rabin Vincentb782fcc2016-07-19 09:25:45 +02001664 vol->echo_interval = SMB_ECHO_INTERVAL_DEFAULT;
1665
Sean Finneyb9468452011-04-11 13:19:32 +00001666 if (!mountdata)
1667 goto cifs_parse_mount_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001668
Sean Finneyb9468452011-04-11 13:19:32 +00001669 mountdata_copy = kstrndup(mountdata, PAGE_SIZE, GFP_KERNEL);
1670 if (!mountdata_copy)
1671 goto cifs_parse_mount_err;
1672
1673 options = mountdata_copy;
Pavel Shilovsky4906e502011-04-14 22:00:56 +04001674 end = options + strlen(options);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001675
Steve French50c2f752007-07-13 00:33:32 +00001676 if (strncmp(options, "sep=", 4) == 0) {
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001677 if (options[4] != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001678 separator[0] = options[4];
1679 options += 5;
1680 } else {
Joe Perchesf96637b2013-05-04 22:12:25 -05001681 cifs_dbg(FYI, "Null separator not allowed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001682 }
1683 }
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001684 vol->backupuid_specified = false; /* no backup intent for a user */
1685 vol->backupgid_specified = false; /* no backup intent for a group */
Steve French50c2f752007-07-13 00:33:32 +00001686
Jeff Layton37d4f992013-05-24 07:40:05 -04001687 switch (cifs_parse_devname(devname, vol)) {
1688 case 0:
1689 break;
1690 case -ENOMEM:
1691 cifs_dbg(VFS, "Unable to allocate memory for devname.\n");
1692 goto cifs_parse_mount_err;
1693 case -EINVAL:
1694 cifs_dbg(VFS, "Malformed UNC in devname.\n");
1695 goto cifs_parse_mount_err;
1696 default:
1697 cifs_dbg(VFS, "Unknown error parsing devname.\n");
1698 goto cifs_parse_mount_err;
Jeff Laytond387a5c2012-12-10 06:10:46 -05001699 }
1700
Linus Torvalds1da177e2005-04-16 15:20:36 -07001701 while ((data = strsep(&options, separator)) != NULL) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001702 substring_t args[MAX_OPT_ARGS];
1703 unsigned long option;
1704 int token;
1705
Linus Torvalds1da177e2005-04-16 15:20:36 -07001706 if (!*data)
1707 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001708
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001709 token = match_token(data, cifs_mount_option_tokens, args);
1710
1711 switch (token) {
1712
1713 /* Ingnore the following */
1714 case Opt_ignore:
1715 break;
1716
1717 /* Boolean values */
1718 case Opt_user_xattr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001719 vol->no_xattr = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001720 break;
1721 case Opt_nouser_xattr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001722 vol->no_xattr = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001723 break;
1724 case Opt_forceuid:
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001725 override_uid = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001726 break;
1727 case Opt_noforceuid:
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001728 override_uid = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001729 break;
Jeff Layton72bd4812012-10-03 16:02:36 -04001730 case Opt_forcegid:
1731 override_gid = 1;
1732 break;
1733 case Opt_noforcegid:
1734 override_gid = 0;
1735 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001736 case Opt_noblocksend:
Steve Frenchedf1ae42008-10-29 00:47:57 +00001737 vol->noblocksnd = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001738 break;
1739 case Opt_noautotune:
Steve Frenchedf1ae42008-10-29 00:47:57 +00001740 vol->noautotune = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001741 break;
Steve French3e7a02d2019-09-11 21:46:20 -05001742 case Opt_nolease:
1743 vol->no_lease = 1;
1744 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001745 case Opt_hard:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001746 vol->retry = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001747 break;
1748 case Opt_soft:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001749 vol->retry = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001750 break;
1751 case Opt_perm:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001752 vol->noperm = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001753 break;
1754 case Opt_noperm:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001755 vol->noperm = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001756 break;
1757 case Opt_mapchars:
Steve French2baa2682014-09-27 02:19:01 -05001758 vol->sfu_remap = true;
1759 vol->remap = false; /* disable SFM mapping */
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001760 break;
1761 case Opt_nomapchars:
Steve French2baa2682014-09-27 02:19:01 -05001762 vol->sfu_remap = false;
1763 break;
1764 case Opt_mapposix:
1765 vol->remap = true;
1766 vol->sfu_remap = false; /* disable SFU mapping */
1767 break;
1768 case Opt_nomapposix:
1769 vol->remap = false;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001770 break;
1771 case Opt_sfu:
Steve French50c2f752007-07-13 00:33:32 +00001772 vol->sfu_emul = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001773 break;
1774 case Opt_nosfu:
Steve French50c2f752007-07-13 00:33:32 +00001775 vol->sfu_emul = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001776 break;
1777 case Opt_nodfs:
Steve French2c1b8612008-10-16 18:35:21 +00001778 vol->nodfs = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001779 break;
1780 case Opt_posixpaths:
Jeremy Allisonac670552005-06-22 17:26:35 -07001781 vol->posix_paths = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001782 break;
1783 case Opt_noposixpaths:
Jeremy Allisonac670552005-06-22 17:26:35 -07001784 vol->posix_paths = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001785 break;
1786 case Opt_nounix:
Steve Frenchb3266142018-05-20 23:41:10 -05001787 if (vol->linux_ext)
1788 cifs_dbg(VFS,
1789 "conflicting unix mount options\n");
Steve Frenchc18c8422007-07-18 23:21:09 +00001790 vol->no_linux_ext = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001791 break;
Steve Frenchb3266142018-05-20 23:41:10 -05001792 case Opt_unix:
1793 if (vol->no_linux_ext)
1794 cifs_dbg(VFS,
1795 "conflicting unix mount options\n");
1796 vol->linux_ext = 1;
1797 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001798 case Opt_nocase:
Steve French50c2f752007-07-13 00:33:32 +00001799 vol->nocase = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001800 break;
1801 case Opt_brl:
Steve Frenchc46fa8a2005-08-18 20:49:57 -07001802 vol->nobrl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001803 break;
1804 case Opt_nobrl:
Steve Frenchc46fa8a2005-08-18 20:49:57 -07001805 vol->nobrl = 1;
Pavel Shilovsky5cfdddc2012-03-27 20:51:15 +04001806 /*
1807 * turn off mandatory locking in mode
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001808 * if remote locking is turned off since the
Pavel Shilovsky5cfdddc2012-03-27 20:51:15 +04001809 * local vfs will do advisory
1810 */
Steve French50c2f752007-07-13 00:33:32 +00001811 if (vol->file_mode ==
1812 (S_IALLUGO & ~(S_ISUID | S_IXGRP)))
Steve Frenchd3485d32005-08-19 11:04:29 -07001813 vol->file_mode = S_IALLUGO;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001814 break;
Steve French3d4ef9a2018-04-25 22:19:09 -05001815 case Opt_nohandlecache:
1816 vol->nohandlecache = 1;
1817 break;
1818 case Opt_handlecache:
1819 vol->nohandlecache = 0;
1820 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001821 case Opt_forcemandatorylock:
Steve French13a6e422008-12-02 17:24:33 +00001822 vol->mand_lock = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001823 break;
1824 case Opt_setuids:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001825 vol->setuids = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001826 break;
1827 case Opt_nosetuids:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001828 vol->setuids = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001829 break;
Steve French95932652016-09-23 01:36:34 -05001830 case Opt_setuidfromacl:
1831 vol->setuidfromacl = 1;
1832 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001833 case Opt_dynperm:
Jeff Laytond0a9c072008-05-12 22:23:49 +00001834 vol->dynperm = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001835 break;
1836 case Opt_nodynperm:
Jeff Laytond0a9c072008-05-12 22:23:49 +00001837 vol->dynperm = false;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001838 break;
1839 case Opt_nohard:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001840 vol->retry = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001841 break;
1842 case Opt_nosoft:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001843 vol->retry = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001844 break;
1845 case Opt_nointr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001846 vol->intr = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001847 break;
1848 case Opt_intr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001849 vol->intr = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001850 break;
1851 case Opt_nostrictsync:
Steve Frenchbe652442009-02-23 15:21:59 +00001852 vol->nostrictsync = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001853 break;
1854 case Opt_strictsync:
Steve Frenchbe652442009-02-23 15:21:59 +00001855 vol->nostrictsync = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001856 break;
1857 case Opt_serverino:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001858 vol->server_ino = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001859 break;
1860 case Opt_noserverino:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001861 vol->server_ino = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001862 break;
1863 case Opt_rwpidforward:
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001864 vol->rwpidforward = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001865 break;
Steve French412094a2019-06-24 02:01:42 -05001866 case Opt_modesid:
1867 vol->mode_ace = 1;
1868 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001869 case Opt_cifsacl:
Steve French0a4b92c2006-01-12 15:44:21 -08001870 vol->cifs_acl = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001871 break;
1872 case Opt_nocifsacl:
Steve French0a4b92c2006-01-12 15:44:21 -08001873 vol->cifs_acl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001874 break;
1875 case Opt_acl:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001876 vol->no_psx_acl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001877 break;
1878 case Opt_noacl:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001879 vol->no_psx_acl = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001880 break;
1881 case Opt_locallease:
Steve French84210e92008-10-23 04:42:37 +00001882 vol->local_lease = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001883 break;
1884 case Opt_sign:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001885 vol->sign = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001886 break;
Steve French4f5c10f2019-09-03 21:18:49 -05001887 case Opt_ignore_signature:
1888 vol->sign = true;
1889 vol->ignore_signature = true;
1890 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001891 case Opt_seal:
Steve French95b1cb92008-05-15 16:44:38 +00001892 /* we do not do the following in secFlags because seal
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001893 * is a per tree connection (mount) not a per socket
1894 * or per-smb connection option in the protocol
1895 * vol->secFlg |= CIFSSEC_MUST_SEAL;
1896 */
Steve French95b1cb92008-05-15 16:44:38 +00001897 vol->seal = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001898 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001899 case Opt_noac:
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001900 pr_warn("CIFS: Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001901 break;
1902 case Opt_fsc:
Suresh Jayaraman607a5692010-11-24 17:49:05 +05301903#ifndef CONFIG_CIFS_FSCACHE
Joe Perchesf96637b2013-05-04 22:12:25 -05001904 cifs_dbg(VFS, "FS-Cache support needs CONFIG_CIFS_FSCACHE kernel config option set\n");
Sean Finneyb9468452011-04-11 13:19:32 +00001905 goto cifs_parse_mount_err;
Suresh Jayaraman607a5692010-11-24 17:49:05 +05301906#endif
Suresh Jayaramanfa1df752010-07-05 18:13:36 +05301907 vol->fsc = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001908 break;
1909 case Opt_mfsymlinks:
Stefan Metzmacher736a33202010-07-30 14:56:00 +02001910 vol->mfsymlinks = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001911 break;
1912 case Opt_multiuser:
Jeff Layton0eb8a132010-10-06 19:51:12 -04001913 vol->multiuser = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001914 break;
Jeff Laytond8162552012-03-23 14:40:56 -04001915 case Opt_sloppy:
1916 sloppy = true;
1917 break;
Jeff Laytona0b3df52013-05-24 07:40:59 -04001918 case Opt_nosharesock:
1919 vol->nosharesock = true;
1920 break;
Steve Frenchb2a30772015-09-29 21:49:28 -05001921 case Opt_nopersistent:
1922 vol->nopersistent = true;
1923 if (vol->persistent) {
1924 cifs_dbg(VFS,
1925 "persistenthandles mount options conflict\n");
1926 goto cifs_parse_mount_err;
1927 }
1928 break;
1929 case Opt_persistent:
1930 vol->persistent = true;
Steve French592fafe2015-11-03 10:08:53 -06001931 if ((vol->nopersistent) || (vol->resilient)) {
Steve Frenchb2a30772015-09-29 21:49:28 -05001932 cifs_dbg(VFS,
1933 "persistenthandles mount options conflict\n");
1934 goto cifs_parse_mount_err;
1935 }
1936 break;
Steve French592fafe2015-11-03 10:08:53 -06001937 case Opt_resilient:
1938 vol->resilient = true;
1939 if (vol->persistent) {
1940 cifs_dbg(VFS,
1941 "persistenthandles mount options conflict\n");
1942 goto cifs_parse_mount_err;
1943 }
1944 break;
1945 case Opt_noresilient:
1946 vol->resilient = false; /* already the default */
1947 break;
Germano Percossi39566442016-12-15 12:31:18 +05301948 case Opt_domainauto:
1949 vol->domainauto = true;
1950 break;
Long Li8339dd32017-11-07 01:54:55 -07001951 case Opt_rdma:
1952 vol->rdma = true;
1953 break;
Steve French9fe5ff12019-06-24 20:39:04 -05001954 case Opt_compress:
1955 vol->compression = UNKNOWN_TYPE;
1956 cifs_dbg(VFS,
1957 "SMB3 compression support is experimental\n");
1958 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001959
1960 /* Numeric Values */
1961 case Opt_backupuid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001962 if (get_option_uid(args, &vol->backupuid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001963 cifs_dbg(VFS, "%s: Invalid backupuid value\n",
1964 __func__);
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001965 goto cifs_parse_mount_err;
1966 }
1967 vol->backupuid_specified = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001968 break;
1969 case Opt_backupgid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001970 if (get_option_gid(args, &vol->backupgid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001971 cifs_dbg(VFS, "%s: Invalid backupgid value\n",
1972 __func__);
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001973 goto cifs_parse_mount_err;
1974 }
1975 vol->backupgid_specified = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001976 break;
1977 case Opt_uid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001978 if (get_option_uid(args, &vol->linux_uid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001979 cifs_dbg(VFS, "%s: Invalid uid value\n",
1980 __func__);
Sean Finneyb9468452011-04-11 13:19:32 +00001981 goto cifs_parse_mount_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001982 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001983 uid_specified = true;
1984 break;
1985 case Opt_cruid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001986 if (get_option_uid(args, &vol->cred_uid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001987 cifs_dbg(VFS, "%s: Invalid cruid value\n",
1988 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001989 goto cifs_parse_mount_err;
1990 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001991 break;
1992 case Opt_gid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001993 if (get_option_gid(args, &vol->linux_gid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001994 cifs_dbg(VFS, "%s: Invalid gid value\n",
1995 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001996 goto cifs_parse_mount_err;
1997 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001998 gid_specified = true;
1999 break;
2000 case Opt_file_mode:
2001 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002002 cifs_dbg(VFS, "%s: Invalid file_mode value\n",
2003 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002004 goto cifs_parse_mount_err;
2005 }
2006 vol->file_mode = option;
2007 break;
2008 case Opt_dirmode:
2009 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002010 cifs_dbg(VFS, "%s: Invalid dir_mode value\n",
2011 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002012 goto cifs_parse_mount_err;
2013 }
2014 vol->dir_mode = option;
2015 break;
2016 case Opt_port:
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002017 if (get_option_ul(args, &option) ||
2018 option > USHRT_MAX) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002019 cifs_dbg(VFS, "%s: Invalid port value\n",
2020 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002021 goto cifs_parse_mount_err;
2022 }
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002023 port = (unsigned short)option;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002024 break;
Steve French563317e2019-09-08 23:22:02 -05002025 case Opt_min_enc_offload:
2026 if (get_option_ul(args, &option)) {
2027 cifs_dbg(VFS, "Invalid minimum encrypted read offload size (esize)\n");
2028 goto cifs_parse_mount_err;
2029 }
2030 vol->min_offload = option;
2031 break;
Steve Frenche8506d22019-02-28 21:32:15 -06002032 case Opt_blocksize:
2033 if (get_option_ul(args, &option)) {
2034 cifs_dbg(VFS, "%s: Invalid blocksize value\n",
2035 __func__);
2036 goto cifs_parse_mount_err;
2037 }
2038 /*
2039 * inode blocksize realistically should never need to be
2040 * less than 16K or greater than 16M and default is 1MB.
2041 * Note that small inode block sizes (e.g. 64K) can lead
2042 * to very poor performance of common tools like cp and scp
2043 */
2044 if ((option < CIFS_MAX_MSGSIZE) ||
2045 (option > (4 * SMB3_DEFAULT_IOSIZE))) {
2046 cifs_dbg(VFS, "%s: Invalid blocksize\n",
2047 __func__);
2048 goto cifs_parse_mount_err;
2049 }
2050 vol->bsize = option;
2051 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002052 case Opt_rsize:
2053 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002054 cifs_dbg(VFS, "%s: Invalid rsize value\n",
2055 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002056 goto cifs_parse_mount_err;
2057 }
2058 vol->rsize = option;
2059 break;
2060 case Opt_wsize:
2061 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002062 cifs_dbg(VFS, "%s: Invalid wsize value\n",
2063 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002064 goto cifs_parse_mount_err;
2065 }
2066 vol->wsize = option;
2067 break;
2068 case Opt_actimeo:
2069 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002070 cifs_dbg(VFS, "%s: Invalid actimeo value\n",
2071 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002072 goto cifs_parse_mount_err;
2073 }
2074 vol->actimeo = HZ * option;
2075 if (vol->actimeo > CIFS_MAX_ACTIMEO) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002076 cifs_dbg(VFS, "attribute cache timeout too large\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002077 goto cifs_parse_mount_err;
2078 }
2079 break;
Steve Frenchca567eb2019-03-29 16:31:07 -05002080 case Opt_handletimeout:
2081 if (get_option_ul(args, &option)) {
2082 cifs_dbg(VFS, "%s: Invalid handletimeout value\n",
2083 __func__);
2084 goto cifs_parse_mount_err;
2085 }
2086 vol->handle_timeout = option;
2087 if (vol->handle_timeout > SMB3_MAX_HANDLE_TIMEOUT) {
2088 cifs_dbg(VFS, "Invalid handle cache timeout, longer than 16 minutes\n");
2089 goto cifs_parse_mount_err;
2090 }
2091 break;
Steve Frenchadfeb3e2015-12-18 12:31:36 -06002092 case Opt_echo_interval:
2093 if (get_option_ul(args, &option)) {
2094 cifs_dbg(VFS, "%s: Invalid echo interval value\n",
2095 __func__);
2096 goto cifs_parse_mount_err;
2097 }
2098 vol->echo_interval = option;
2099 break;
Steve French8b217fe2016-11-11 22:36:20 -06002100 case Opt_snapshot:
2101 if (get_option_ul(args, &option)) {
2102 cifs_dbg(VFS, "%s: Invalid snapshot time\n",
2103 __func__);
2104 goto cifs_parse_mount_err;
2105 }
2106 vol->snapshot_time = option;
2107 break;
Steve French141891f2016-09-23 00:44:16 -05002108 case Opt_max_credits:
2109 if (get_option_ul(args, &option) || (option < 20) ||
2110 (option > 60000)) {
2111 cifs_dbg(VFS, "%s: Invalid max_credits value\n",
2112 __func__);
2113 goto cifs_parse_mount_err;
2114 }
2115 vol->max_credits = option;
2116 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002117
2118 /* String Arguments */
2119
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01002120 case Opt_blank_user:
2121 /* null user, ie. anonymous authentication */
2122 vol->nullauth = 1;
2123 vol->username = NULL;
2124 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002125 case Opt_user:
2126 string = match_strdup(args);
2127 if (string == NULL)
2128 goto out_nomem;
2129
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04002130 if (strnlen(string, CIFS_MAX_USERNAME_LEN) >
2131 CIFS_MAX_USERNAME_LEN) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002132 pr_warn("CIFS: username too long\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002133 goto cifs_parse_mount_err;
2134 }
Taesoo Kim2bd50fb2015-03-21 19:08:30 -04002135
2136 kfree(vol->username);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002137 vol->username = kstrdup(string, GFP_KERNEL);
Joe Perchesf96637b2013-05-04 22:12:25 -05002138 if (!vol->username)
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002139 goto cifs_parse_mount_err;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002140 break;
2141 case Opt_blank_pass:
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002142 /* passwords have to be handled differently
2143 * to allow the character used for deliminator
2144 * to be passed within them
2145 */
2146
Sachin Prabhuc369c9a2013-04-09 18:17:41 +01002147 /*
2148 * Check if this is a case where the password
2149 * starts with a delimiter
2150 */
2151 tmp_end = strchr(data, '=');
2152 tmp_end++;
2153 if (!(tmp_end < end && tmp_end[1] == delim)) {
2154 /* No it is not. Set the password to NULL */
Aurelien Aptel97f4b722018-01-25 15:59:39 +01002155 kzfree(vol->password);
Sachin Prabhuc369c9a2013-04-09 18:17:41 +01002156 vol->password = NULL;
2157 break;
2158 }
Gustavo A. R. Silva07fa6012018-11-27 10:01:51 +11002159 /* Fallthrough - to Opt_pass below.*/
Sachin Prabhuc369c9a2013-04-09 18:17:41 +01002160 case Opt_pass:
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002161 /* Obtain the value string */
2162 value = strchr(data, '=');
Sachin Prabhu10238072012-03-28 18:07:08 +01002163 value++;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002164
2165 /* Set tmp_end to end of the string */
2166 tmp_end = (char *) value + strlen(value);
2167
2168 /* Check if following character is the deliminator
2169 * If yes, we have encountered a double deliminator
2170 * reset the NULL character to the deliminator
2171 */
Suresh Jayaramane73f8432012-06-12 07:15:50 +05302172 if (tmp_end < end && tmp_end[1] == delim) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002173 tmp_end[0] = delim;
2174
Suresh Jayaramane73f8432012-06-12 07:15:50 +05302175 /* Keep iterating until we get to a single
2176 * deliminator OR the end
2177 */
2178 while ((tmp_end = strchr(tmp_end, delim))
2179 != NULL && (tmp_end[1] == delim)) {
2180 tmp_end = (char *) &tmp_end[2];
2181 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002182
Suresh Jayaramane73f8432012-06-12 07:15:50 +05302183 /* Reset var options to point to next element */
2184 if (tmp_end) {
2185 tmp_end[0] = '\0';
2186 options = (char *) &tmp_end[1];
2187 } else
2188 /* Reached the end of the mount option
2189 * string */
2190 options = end;
2191 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002192
Aurelien Aptel97f4b722018-01-25 15:59:39 +01002193 kzfree(vol->password);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002194 /* Now build new password string */
2195 temp_len = strlen(value);
2196 vol->password = kzalloc(temp_len+1, GFP_KERNEL);
2197 if (vol->password == NULL) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002198 pr_warn("CIFS: no memory for password\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002199 goto cifs_parse_mount_err;
2200 }
2201
2202 for (i = 0, j = 0; i < temp_len; i++, j++) {
2203 vol->password[j] = value[i];
2204 if ((value[i] == delim) &&
2205 value[i+1] == delim)
2206 /* skip the second deliminator */
2207 i++;
2208 }
2209 vol->password[j] = '\0';
2210 break;
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01002211 case Opt_blank_ip:
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002212 /* FIXME: should this be an error instead? */
2213 got_ip = false;
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01002214 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002215 case Opt_ip:
2216 string = match_strdup(args);
2217 if (string == NULL)
2218 goto out_nomem;
2219
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002220 if (!cifs_convert_address(dstaddr, string,
2221 strlen(string))) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002222 pr_err("CIFS: bad ip= option (%s).\n", string);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002223 goto cifs_parse_mount_err;
2224 }
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002225 got_ip = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002226 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002227 case Opt_domain:
2228 string = match_strdup(args);
2229 if (string == NULL)
2230 goto out_nomem;
2231
Chen Gang057d6332013-07-19 09:01:36 +08002232 if (strnlen(string, CIFS_MAX_DOMAINNAME_LEN)
2233 == CIFS_MAX_DOMAINNAME_LEN) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002234 pr_warn("CIFS: domain name too long\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002235 goto cifs_parse_mount_err;
2236 }
2237
Taesoo Kim2bd50fb2015-03-21 19:08:30 -04002238 kfree(vol->domainname);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002239 vol->domainname = kstrdup(string, GFP_KERNEL);
2240 if (!vol->domainname) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002241 pr_warn("CIFS: no memory for domainname\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002242 goto cifs_parse_mount_err;
2243 }
Joe Perchesf96637b2013-05-04 22:12:25 -05002244 cifs_dbg(FYI, "Domain name set\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002245 break;
2246 case Opt_srcaddr:
2247 string = match_strdup(args);
2248 if (string == NULL)
2249 goto out_nomem;
2250
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01002251 if (!cifs_convert_address(
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002252 (struct sockaddr *)&vol->srcaddr,
2253 string, strlen(string))) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002254 pr_warn("CIFS: Could not parse srcaddr: %s\n",
2255 string);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002256 goto cifs_parse_mount_err;
2257 }
2258 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002259 case Opt_iocharset:
2260 string = match_strdup(args);
2261 if (string == NULL)
2262 goto out_nomem;
2263
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01002264 if (strnlen(string, 1024) >= 65) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002265 pr_warn("CIFS: iocharset name too long.\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002266 goto cifs_parse_mount_err;
2267 }
2268
Rasmus Villemoes87e747c2014-10-13 15:54:35 -07002269 if (strncasecmp(string, "default", 7) != 0) {
Taesoo Kim2bd50fb2015-03-21 19:08:30 -04002270 kfree(vol->iocharset);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002271 vol->iocharset = kstrdup(string,
2272 GFP_KERNEL);
2273 if (!vol->iocharset) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002274 pr_warn("CIFS: no memory for charset\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002275 goto cifs_parse_mount_err;
2276 }
2277 }
2278 /* if iocharset not set then load_nls_default
2279 * is used by caller
2280 */
Joe Perchesf96637b2013-05-04 22:12:25 -05002281 cifs_dbg(FYI, "iocharset set to %s\n", string);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002282 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002283 case Opt_netbiosname:
2284 string = match_strdup(args);
2285 if (string == NULL)
2286 goto out_nomem;
2287
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002288 memset(vol->source_rfc1001_name, 0x20,
2289 RFC1001_NAME_LEN);
2290 /*
2291 * FIXME: are there cases in which a comma can
2292 * be valid in workstation netbios name (and
2293 * need special handling)?
2294 */
2295 for (i = 0; i < RFC1001_NAME_LEN; i++) {
2296 /* don't ucase netbiosname for user */
2297 if (string[i] == 0)
2298 break;
2299 vol->source_rfc1001_name[i] = string[i];
2300 }
2301 /* The string has 16th byte zero still from
2302 * set at top of the function
2303 */
2304 if (i == RFC1001_NAME_LEN && string[i] != 0)
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002305 pr_warn("CIFS: netbiosname longer than 15 truncated.\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002306 break;
2307 case Opt_servern:
2308 /* servernetbiosname specified override *SMBSERVER */
2309 string = match_strdup(args);
2310 if (string == NULL)
2311 goto out_nomem;
2312
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002313 /* last byte, type, is 0x20 for servr type */
2314 memset(vol->target_rfc1001_name, 0x20,
2315 RFC1001_NAME_LEN_WITH_NULL);
2316
2317 /* BB are there cases in which a comma can be
2318 valid in this workstation netbios name
2319 (and need special handling)? */
2320
2321 /* user or mount helper must uppercase the
2322 netbios name */
2323 for (i = 0; i < 15; i++) {
2324 if (string[i] == 0)
2325 break;
2326 vol->target_rfc1001_name[i] = string[i];
2327 }
2328 /* The string has 16th byte zero still from
2329 set at top of the function */
2330 if (i == RFC1001_NAME_LEN && string[i] != 0)
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002331 pr_warn("CIFS: server netbiosname longer than 15 truncated.\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002332 break;
2333 case Opt_ver:
Steve French7e682f72017-08-31 21:34:24 -05002334 /* version of mount userspace tools, not dialect */
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002335 string = match_strdup(args);
2336 if (string == NULL)
2337 goto out_nomem;
2338
Steve French7e682f72017-08-31 21:34:24 -05002339 /* If interface changes in mount.cifs bump to new ver */
Rasmus Villemoes87e747c2014-10-13 15:54:35 -07002340 if (strncasecmp(string, "1", 1) == 0) {
Steve French7e682f72017-08-31 21:34:24 -05002341 if (strlen(string) > 1) {
2342 pr_warn("Bad mount helper ver=%s. Did "
2343 "you want SMB1 (CIFS) dialect "
2344 "and mean to type vers=1.0 "
2345 "instead?\n", string);
2346 goto cifs_parse_mount_err;
2347 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002348 /* This is the default */
2349 break;
2350 }
2351 /* For all other value, error */
Steve French7e682f72017-08-31 21:34:24 -05002352 pr_warn("CIFS: Invalid mount helper version specified\n");
Sean Finneyb9468452011-04-11 13:19:32 +00002353 goto cifs_parse_mount_err;
Jeff Layton23db65f2012-05-15 12:20:51 -04002354 case Opt_vers:
Steve French7e682f72017-08-31 21:34:24 -05002355 /* protocol version (dialect) */
Jeff Layton23db65f2012-05-15 12:20:51 -04002356 string = match_strdup(args);
2357 if (string == NULL)
2358 goto out_nomem;
2359
Steve Frenchc7c137b2018-06-06 17:59:29 -05002360 if (cifs_parse_smb_version(string, vol, is_smb3) != 0)
Jeff Layton23db65f2012-05-15 12:20:51 -04002361 goto cifs_parse_mount_err;
Steve French7e682f72017-08-31 21:34:24 -05002362 got_version = true;
Jeff Layton23db65f2012-05-15 12:20:51 -04002363 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002364 case Opt_sec:
2365 string = match_strdup(args);
2366 if (string == NULL)
2367 goto out_nomem;
2368
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002369 if (cifs_parse_security_flavors(string, vol) != 0)
2370 goto cifs_parse_mount_err;
2371 break;
Jeff Layton15b6a472012-05-16 07:50:15 -04002372 case Opt_cache:
2373 string = match_strdup(args);
2374 if (string == NULL)
2375 goto out_nomem;
2376
2377 if (cifs_parse_cache_flavor(string, vol) != 0)
2378 goto cifs_parse_mount_err;
2379 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002380 default:
Jeff Laytond8162552012-03-23 14:40:56 -04002381 /*
2382 * An option we don't recognize. Save it off for later
2383 * if we haven't already found one
2384 */
2385 if (!invalid)
2386 invalid = data;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002387 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002388 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002389 /* Free up any allocated string */
2390 kfree(string);
2391 string = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002392 }
Jeff Layton0eb8a132010-10-06 19:51:12 -04002393
Jeff Laytond8162552012-03-23 14:40:56 -04002394 if (!sloppy && invalid) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002395 pr_err("CIFS: Unknown mount option \"%s\"\n", invalid);
Jeff Laytond8162552012-03-23 14:40:56 -04002396 goto cifs_parse_mount_err;
2397 }
2398
Long Li8339dd32017-11-07 01:54:55 -07002399 if (vol->rdma && vol->vals->protocol_id < SMB30_PROT_ID) {
2400 cifs_dbg(VFS, "SMB Direct requires Version >=3.0\n");
2401 goto cifs_parse_mount_err;
2402 }
2403
Jeff Layton8a8798a2012-01-17 16:09:15 -05002404#ifndef CONFIG_KEYS
2405 /* Muliuser mounts require CONFIG_KEYS support */
2406 if (vol->multiuser) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002407 cifs_dbg(VFS, "Multiuser mounts require kernels with CONFIG_KEYS enabled\n");
Sean Finneyb9468452011-04-11 13:19:32 +00002408 goto cifs_parse_mount_err;
Jeff Layton0eb8a132010-10-06 19:51:12 -04002409 }
Jeff Layton8a8798a2012-01-17 16:09:15 -05002410#endif
Jeff Laytone5e69ab2012-11-25 08:00:42 -05002411 if (!vol->UNC) {
Jeff Layton37d4f992013-05-24 07:40:05 -04002412 cifs_dbg(VFS, "CIFS mount error: No usable UNC path provided in device string!\n");
Jeff Laytone5e69ab2012-11-25 08:00:42 -05002413 goto cifs_parse_mount_err;
2414 }
Jeff Layton0eb8a132010-10-06 19:51:12 -04002415
Jeff Layton62a1a432012-12-10 06:10:45 -05002416 /* make sure UNC has a share name */
2417 if (!strchr(vol->UNC + 3, '\\')) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002418 cifs_dbg(VFS, "Malformed UNC. Unable to find share name.\n");
Jeff Layton62a1a432012-12-10 06:10:45 -05002419 goto cifs_parse_mount_err;
2420 }
2421
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002422 if (!got_ip) {
Daniel N Pettersson29bb3152017-04-27 11:32:36 +02002423 int len;
2424 const char *slash;
2425
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002426 /* No ip= option specified? Try to get it from UNC */
Daniel N Pettersson29bb3152017-04-27 11:32:36 +02002427 /* Use the address part of the UNC. */
2428 slash = strchr(&vol->UNC[2], '\\');
2429 len = slash - &vol->UNC[2];
2430 if (!cifs_convert_address(dstaddr, &vol->UNC[2], len)) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002431 pr_err("Unable to determine destination address.\n");
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002432 goto cifs_parse_mount_err;
2433 }
2434 }
2435
2436 /* set the port that we got earlier */
2437 cifs_set_port(dstaddr, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002438
Jeff Layton9b9d6b242009-07-31 06:56:09 -04002439 if (uid_specified)
2440 vol->override_uid = override_uid;
2441 else if (override_uid == 1)
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002442 pr_notice("CIFS: ignoring forceuid mount option specified with no uid= option.\n");
Jeff Layton9b9d6b242009-07-31 06:56:09 -04002443
2444 if (gid_specified)
2445 vol->override_gid = override_gid;
2446 else if (override_gid == 1)
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002447 pr_notice("CIFS: ignoring forcegid mount option specified with no gid= option.\n");
Jeff Layton9b9d6b242009-07-31 06:56:09 -04002448
Steve French7e682f72017-08-31 21:34:24 -05002449 if (got_version == false)
2450 pr_warn("No dialect specified on mount. Default has changed to "
Steve French9764c022017-09-17 10:41:35 -05002451 "a more secure dialect, SMB2.1 or later (e.g. SMB3), from CIFS "
Steve French7e682f72017-08-31 21:34:24 -05002452 "(SMB1). To use the less secure SMB1 dialect to access "
Steve French9764c022017-09-17 10:41:35 -05002453 "old servers which do not support SMB3 (or SMB2.1) specify vers=1.0"
2454 " on mount.\n");
Steve French7e682f72017-08-31 21:34:24 -05002455
Sean Finneyb9468452011-04-11 13:19:32 +00002456 kfree(mountdata_copy);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002457 return 0;
Sean Finneyb9468452011-04-11 13:19:32 +00002458
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002459out_nomem:
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002460 pr_warn("Could not allocate temporary buffer\n");
Sean Finneyb9468452011-04-11 13:19:32 +00002461cifs_parse_mount_err:
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002462 kfree(string);
Sean Finneyb9468452011-04-11 13:19:32 +00002463 kfree(mountdata_copy);
2464 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002465}
2466
Ben Greear3eb9a882010-09-01 17:06:02 -07002467/** Returns true if srcaddr isn't specified and rhs isn't
2468 * specified, or if srcaddr is specified and
2469 * matches the IP address of the rhs argument.
2470 */
Jeff Layton45151482010-07-06 20:43:02 -04002471static bool
Ben Greear3eb9a882010-09-01 17:06:02 -07002472srcip_matches(struct sockaddr *srcaddr, struct sockaddr *rhs)
2473{
2474 switch (srcaddr->sa_family) {
2475 case AF_UNSPEC:
2476 return (rhs->sa_family == AF_UNSPEC);
2477 case AF_INET: {
2478 struct sockaddr_in *saddr4 = (struct sockaddr_in *)srcaddr;
2479 struct sockaddr_in *vaddr4 = (struct sockaddr_in *)rhs;
2480 return (saddr4->sin_addr.s_addr == vaddr4->sin_addr.s_addr);
2481 }
2482 case AF_INET6: {
2483 struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)srcaddr;
Nickolai Zeldoviche3e27752013-01-16 21:36:17 -05002484 struct sockaddr_in6 *vaddr6 = (struct sockaddr_in6 *)rhs;
Ben Greear3eb9a882010-09-01 17:06:02 -07002485 return ipv6_addr_equal(&saddr6->sin6_addr, &vaddr6->sin6_addr);
2486 }
2487 default:
2488 WARN_ON(1);
2489 return false; /* don't expect to be here */
2490 }
2491}
2492
Pavel Shilovsky4b886132010-12-13 22:18:07 +03002493/*
2494 * If no port is specified in addr structure, we try to match with 445 port
2495 * and if it fails - with 139 ports. It should be called only if address
2496 * families of server and addr are equal.
2497 */
2498static bool
2499match_port(struct TCP_Server_Info *server, struct sockaddr *addr)
2500{
Steve French6da97912011-03-13 18:55:55 +00002501 __be16 port, *sport;
Pavel Shilovsky4b886132010-12-13 22:18:07 +03002502
Long Li3b249112019-05-15 14:09:04 -07002503 /* SMBDirect manages its own ports, don't match it here */
2504 if (server->rdma)
2505 return true;
2506
Pavel Shilovsky4b886132010-12-13 22:18:07 +03002507 switch (addr->sa_family) {
2508 case AF_INET:
2509 sport = &((struct sockaddr_in *) &server->dstaddr)->sin_port;
2510 port = ((struct sockaddr_in *) addr)->sin_port;
2511 break;
2512 case AF_INET6:
2513 sport = &((struct sockaddr_in6 *) &server->dstaddr)->sin6_port;
2514 port = ((struct sockaddr_in6 *) addr)->sin6_port;
2515 break;
2516 default:
2517 WARN_ON(1);
2518 return false;
2519 }
2520
2521 if (!port) {
2522 port = htons(CIFS_PORT);
2523 if (port == *sport)
2524 return true;
2525
2526 port = htons(RFC1001_PORT);
2527 }
2528
2529 return port == *sport;
2530}
Ben Greear3eb9a882010-09-01 17:06:02 -07002531
2532static bool
2533match_address(struct TCP_Server_Info *server, struct sockaddr *addr,
2534 struct sockaddr *srcaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002535{
Jeff Layton45151482010-07-06 20:43:02 -04002536 switch (addr->sa_family) {
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002537 case AF_INET: {
2538 struct sockaddr_in *addr4 = (struct sockaddr_in *)addr;
2539 struct sockaddr_in *srv_addr4 =
2540 (struct sockaddr_in *)&server->dstaddr;
2541
2542 if (addr4->sin_addr.s_addr != srv_addr4->sin_addr.s_addr)
Jeff Layton45151482010-07-06 20:43:02 -04002543 return false;
Jeff Layton45151482010-07-06 20:43:02 -04002544 break;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002545 }
2546 case AF_INET6: {
2547 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
2548 struct sockaddr_in6 *srv_addr6 =
2549 (struct sockaddr_in6 *)&server->dstaddr;
2550
Jeff Layton45151482010-07-06 20:43:02 -04002551 if (!ipv6_addr_equal(&addr6->sin6_addr,
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002552 &srv_addr6->sin6_addr))
Jeff Layton45151482010-07-06 20:43:02 -04002553 return false;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002554 if (addr6->sin6_scope_id != srv_addr6->sin6_scope_id)
Jeff Layton45151482010-07-06 20:43:02 -04002555 return false;
Jeff Layton45151482010-07-06 20:43:02 -04002556 break;
2557 }
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002558 default:
2559 WARN_ON(1);
2560 return false; /* don't expect to be here */
2561 }
Jeff Layton45151482010-07-06 20:43:02 -04002562
Ben Greear3eb9a882010-09-01 17:06:02 -07002563 if (!srcip_matches(srcaddr, (struct sockaddr *)&server->srcaddr))
2564 return false;
2565
Jeff Layton45151482010-07-06 20:43:02 -04002566 return true;
2567}
2568
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002569static bool
2570match_security(struct TCP_Server_Info *server, struct smb_vol *vol)
2571{
Jeff Layton3f618222013-06-12 19:52:14 -05002572 /*
2573 * The select_sectype function should either return the vol->sectype
2574 * that was specified, or "Unspecified" if that sectype was not
2575 * compatible with the given NEGOTIATE request.
2576 */
Sachin Prabhuef65aae2017-01-18 15:35:57 +05302577 if (server->ops->select_sectype(server, vol->sectype)
2578 == Unspecified)
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002579 return false;
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002580
Jeff Layton3f618222013-06-12 19:52:14 -05002581 /*
2582 * Now check if signing mode is acceptable. No need to check
2583 * global_secflags at this point since if MUST_SIGN is set then
2584 * the server->sign had better be too.
2585 */
Jeff Layton38d77c52013-05-26 07:01:00 -04002586 if (vol->sign && !server->sign)
2587 return false;
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002588
2589 return true;
2590}
2591
Jeff Layton9fa114f2012-11-26 11:09:57 -05002592static int match_server(struct TCP_Server_Info *server, struct smb_vol *vol)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002593{
Jeff Layton9fa114f2012-11-26 11:09:57 -05002594 struct sockaddr *addr = (struct sockaddr *)&vol->dstaddr;
2595
Jeff Laytona0b3df52013-05-24 07:40:59 -04002596 if (vol->nosharesock)
2597 return 0;
2598
Steve French43cdae82019-06-13 14:26:49 -05002599 /* If multidialect negotiation see if existing sessions match one */
2600 if (strcmp(vol->vals->version_string, SMB3ANY_VERSION_STRING) == 0) {
2601 if (server->vals->protocol_id < SMB30_PROT_ID)
2602 return 0;
2603 } else if (strcmp(vol->vals->version_string,
2604 SMBDEFAULT_VERSION_STRING) == 0) {
2605 if (server->vals->protocol_id < SMB21_PROT_ID)
2606 return 0;
2607 } else if ((server->vals != vol->vals) || (server->ops != vol->ops))
Jeff Layton23db65f2012-05-15 12:20:51 -04002608 return 0;
2609
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002610 if (!net_eq(cifs_net_ns(server), current->nsproxy->net_ns))
2611 return 0;
2612
2613 if (!match_address(server, addr,
2614 (struct sockaddr *)&vol->srcaddr))
2615 return 0;
2616
2617 if (!match_port(server, addr))
2618 return 0;
2619
2620 if (!match_security(server, vol))
2621 return 0;
2622
Rabin Vincentb782fcc2016-07-19 09:25:45 +02002623 if (server->echo_interval != vol->echo_interval * HZ)
Steve Frenchadfeb3e2015-12-18 12:31:36 -06002624 return 0;
2625
Long Li8339dd32017-11-07 01:54:55 -07002626 if (server->rdma != vol->rdma)
2627 return 0;
2628
Steve French4f5c10f2019-09-03 21:18:49 -05002629 if (server->ignore_signature != vol->ignore_signature)
2630 return 0;
2631
Steve French563317e2019-09-08 23:22:02 -05002632 if (server->min_offload != vol->min_offload)
2633 return 0;
2634
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002635 return 1;
2636}
2637
Paulo Alcantara54be1f62018-11-14 16:01:21 -02002638struct TCP_Server_Info *
Jeff Layton9fa114f2012-11-26 11:09:57 -05002639cifs_find_tcp_session(struct smb_vol *vol)
Jeff Layton45151482010-07-06 20:43:02 -04002640{
Jeff Laytone7ddee92008-11-14 13:44:38 -05002641 struct TCP_Server_Info *server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002642
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302643 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton45151482010-07-06 20:43:02 -04002644 list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
Jeff Layton9fa114f2012-11-26 11:09:57 -05002645 if (!match_server(server, vol))
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002646 continue;
2647
Jeff Laytone7ddee92008-11-14 13:44:38 -05002648 ++server->srv_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302649 spin_unlock(&cifs_tcp_ses_lock);
Joe Perchesf96637b2013-05-04 22:12:25 -05002650 cifs_dbg(FYI, "Existing tcp session with server found\n");
Jeff Laytone7ddee92008-11-14 13:44:38 -05002651 return server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002652 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302653 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002654 return NULL;
2655}
2656
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07002657void
2658cifs_put_tcp_session(struct TCP_Server_Info *server, int from_reconnect)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002659{
Steve Frencha5c3e1c2014-09-16 04:16:19 -05002660 struct task_struct *task;
2661
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302662 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002663 if (--server->srv_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302664 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002665 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002666 }
Steve Frenchdea570e02008-05-06 22:05:51 +00002667
Rob Landleyf1d0c992011-01-22 15:44:05 -06002668 put_net(cifs_net_ns(server));
2669
Jeff Laytone7ddee92008-11-14 13:44:38 -05002670 list_del_init(&server->tcp_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302671 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002672
Jeff Laytonc74093b2011-01-11 07:24:23 -05002673 cancel_delayed_work_sync(&server->echo);
2674
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07002675 if (from_reconnect)
2676 /*
2677 * Avoid deadlock here: reconnect work calls
2678 * cifs_put_tcp_session() at its end. Need to be sure
2679 * that reconnect work does nothing with server pointer after
2680 * that step.
2681 */
2682 cancel_delayed_work(&server->reconnect);
2683 else
2684 cancel_delayed_work_sync(&server->reconnect);
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07002685
Jeff Laytone7ddee92008-11-14 13:44:38 -05002686 spin_lock(&GlobalMid_Lock);
2687 server->tcpStatus = CifsExiting;
2688 spin_unlock(&GlobalMid_Lock);
2689
Pavel Shilovsky026e93d2016-11-03 16:47:37 -07002690 cifs_crypto_secmech_release(server);
Suresh Jayaraman488f1d2d2010-07-05 18:12:15 +05302691 cifs_fscache_release_client_cookie(server);
2692
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05002693 kfree(server->session_key.response);
2694 server->session_key.response = NULL;
2695 server->session_key.len = 0;
Steve Frencha5c3e1c2014-09-16 04:16:19 -05002696
2697 task = xchg(&server->tsk, NULL);
2698 if (task)
Eric W. Biederman72abe3b2019-05-15 12:33:50 -05002699 send_sig(SIGKILL, task, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002700}
2701
Jeff Layton63c038c2008-12-01 18:41:46 -05002702static struct TCP_Server_Info *
2703cifs_get_tcp_session(struct smb_vol *volume_info)
2704{
2705 struct TCP_Server_Info *tcp_ses = NULL;
Jeff Layton63c038c2008-12-01 18:41:46 -05002706 int rc;
2707
Joe Perchesf96637b2013-05-04 22:12:25 -05002708 cifs_dbg(FYI, "UNC: %s\n", volume_info->UNC);
Jeff Layton63c038c2008-12-01 18:41:46 -05002709
2710 /* see if we already have a matching tcp_ses */
Jeff Layton9fa114f2012-11-26 11:09:57 -05002711 tcp_ses = cifs_find_tcp_session(volume_info);
Jeff Layton63c038c2008-12-01 18:41:46 -05002712 if (tcp_ses)
2713 return tcp_ses;
2714
2715 tcp_ses = kzalloc(sizeof(struct TCP_Server_Info), GFP_KERNEL);
2716 if (!tcp_ses) {
2717 rc = -ENOMEM;
2718 goto out_err;
2719 }
2720
Jeff Layton23db65f2012-05-15 12:20:51 -04002721 tcp_ses->ops = volume_info->ops;
2722 tcp_ses->vals = volume_info->vals;
Rob Landleyf1d0c992011-01-22 15:44:05 -06002723 cifs_set_net_ns(tcp_ses, get_net(current->nsproxy->net_ns));
Jeff Layton63c038c2008-12-01 18:41:46 -05002724 tcp_ses->hostname = extract_hostname(volume_info->UNC);
2725 if (IS_ERR(tcp_ses->hostname)) {
2726 rc = PTR_ERR(tcp_ses->hostname);
Shirish Pargaonkarf7c5445a2010-10-26 18:10:24 -05002727 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002728 }
2729
2730 tcp_ses->noblocksnd = volume_info->noblocksnd;
2731 tcp_ses->noautotune = volume_info->noautotune;
Steve French6a5fa2362010-01-01 01:28:43 +00002732 tcp_ses->tcp_nodelay = volume_info->sockopt_tcp_nodelay;
Long Li8339dd32017-11-07 01:54:55 -07002733 tcp_ses->rdma = volume_info->rdma;
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +03002734 tcp_ses->in_flight = 0;
Steve French1b63f182019-09-09 22:57:11 -05002735 tcp_ses->max_in_flight = 0;
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +04002736 tcp_ses->credits = 1;
Jeff Layton63c038c2008-12-01 18:41:46 -05002737 init_waitqueue_head(&tcp_ses->response_q);
2738 init_waitqueue_head(&tcp_ses->request_q);
2739 INIT_LIST_HEAD(&tcp_ses->pending_mid_q);
2740 mutex_init(&tcp_ses->srv_mutex);
2741 memcpy(tcp_ses->workstation_RFC1001_name,
2742 volume_info->source_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
2743 memcpy(tcp_ses->server_RFC1001_name,
2744 volume_info->target_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
Shirish Pargaonkar5d0d2882010-10-13 18:15:00 -05002745 tcp_ses->session_estab = false;
Jeff Layton63c038c2008-12-01 18:41:46 -05002746 tcp_ses->sequence_number = 0;
Pavel Shilovsky5b964852019-01-18 11:30:26 -08002747 tcp_ses->reconnect_instance = 1;
Steve Frenchfda35942011-01-20 18:06:34 +00002748 tcp_ses->lstrp = jiffies;
Steve French9fe5ff12019-06-24 20:39:04 -05002749 tcp_ses->compress_algorithm = cpu_to_le16(volume_info->compression);
Jeff Layton58fa0152012-05-01 17:41:16 -04002750 spin_lock_init(&tcp_ses->req_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002751 INIT_LIST_HEAD(&tcp_ses->tcp_ses_list);
2752 INIT_LIST_HEAD(&tcp_ses->smb_ses_list);
Jeff Laytonc74093b2011-01-11 07:24:23 -05002753 INIT_DELAYED_WORK(&tcp_ses->echo, cifs_echo_request);
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07002754 INIT_DELAYED_WORK(&tcp_ses->reconnect, smb2_reconnect_server);
2755 mutex_init(&tcp_ses->reconnect_mutex);
Jeff Layton9fa114f2012-11-26 11:09:57 -05002756 memcpy(&tcp_ses->srcaddr, &volume_info->srcaddr,
2757 sizeof(tcp_ses->srcaddr));
2758 memcpy(&tcp_ses->dstaddr, &volume_info->dstaddr,
2759 sizeof(tcp_ses->dstaddr));
Steve Frenchfa70b872016-09-22 00:39:34 -05002760 generate_random_uuid(tcp_ses->client_guid);
Jeff Layton63c038c2008-12-01 18:41:46 -05002761 /*
2762 * at this point we are the only ones with the pointer
2763 * to the struct since the kernel thread not created yet
2764 * no need to spinlock this init of tcpStatus or srv_count
2765 */
2766 tcp_ses->tcpStatus = CifsNew;
2767 ++tcp_ses->srv_count;
2768
Steve Frenchadfeb3e2015-12-18 12:31:36 -06002769 if (volume_info->echo_interval >= SMB_ECHO_INTERVAL_MIN &&
2770 volume_info->echo_interval <= SMB_ECHO_INTERVAL_MAX)
2771 tcp_ses->echo_interval = volume_info->echo_interval * HZ;
2772 else
2773 tcp_ses->echo_interval = SMB_ECHO_INTERVAL_DEFAULT * HZ;
Long Li2f894642017-11-22 17:38:34 -07002774 if (tcp_ses->rdma) {
2775#ifndef CONFIG_CIFS_SMB_DIRECT
2776 cifs_dbg(VFS, "CONFIG_CIFS_SMB_DIRECT is not enabled\n");
2777 rc = -ENOENT;
2778 goto out_err_crypto_release;
2779#endif
2780 tcp_ses->smbd_conn = smbd_get_connection(
2781 tcp_ses, (struct sockaddr *)&volume_info->dstaddr);
2782 if (tcp_ses->smbd_conn) {
2783 cifs_dbg(VFS, "RDMA transport established\n");
2784 rc = 0;
2785 goto smbd_connected;
2786 } else {
2787 rc = -ENOENT;
2788 goto out_err_crypto_release;
2789 }
2790 }
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002791 rc = ip_connect(tcp_ses);
Jeff Layton63c038c2008-12-01 18:41:46 -05002792 if (rc < 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002793 cifs_dbg(VFS, "Error connecting to socket. Aborting operation.\n");
Shirish Pargaonkarf7c5445a2010-10-26 18:10:24 -05002794 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002795 }
Long Li2f894642017-11-22 17:38:34 -07002796smbd_connected:
Jeff Layton63c038c2008-12-01 18:41:46 -05002797 /*
2798 * since we're in a cifs function already, we know that
2799 * this will succeed. No need for try_module_get().
2800 */
2801 __module_get(THIS_MODULE);
Al Viro7c97c202011-06-21 08:51:28 -04002802 tcp_ses->tsk = kthread_run(cifs_demultiplex_thread,
Jeff Layton63c038c2008-12-01 18:41:46 -05002803 tcp_ses, "cifsd");
2804 if (IS_ERR(tcp_ses->tsk)) {
2805 rc = PTR_ERR(tcp_ses->tsk);
Joe Perchesf96637b2013-05-04 22:12:25 -05002806 cifs_dbg(VFS, "error %d create cifsd thread\n", rc);
Jeff Layton63c038c2008-12-01 18:41:46 -05002807 module_put(THIS_MODULE);
Shirish Pargaonkarf7c5445a2010-10-26 18:10:24 -05002808 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002809 }
Steve French563317e2019-09-08 23:22:02 -05002810 tcp_ses->min_offload = volume_info->min_offload;
Steve Frenchfd88ce92011-04-12 01:01:14 +00002811 tcp_ses->tcpStatus = CifsNeedNegotiate;
Jeff Layton63c038c2008-12-01 18:41:46 -05002812
Paulo Alcantara93d5cb52018-11-14 17:13:25 -02002813 tcp_ses->nr_targets = 1;
Steve French4f5c10f2019-09-03 21:18:49 -05002814 tcp_ses->ignore_signature = volume_info->ignore_signature;
Jeff Layton63c038c2008-12-01 18:41:46 -05002815 /* thread spawned, put it on the list */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302816 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002817 list_add(&tcp_ses->tcp_ses_list, &cifs_tcp_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302818 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002819
Suresh Jayaraman488f1d2d2010-07-05 18:12:15 +05302820 cifs_fscache_get_client_cookie(tcp_ses);
2821
Jeff Laytonc74093b2011-01-11 07:24:23 -05002822 /* queue echo request delayed work */
Steve Frenchadfeb3e2015-12-18 12:31:36 -06002823 queue_delayed_work(cifsiod_wq, &tcp_ses->echo, tcp_ses->echo_interval);
Jeff Laytonc74093b2011-01-11 07:24:23 -05002824
Jeff Layton63c038c2008-12-01 18:41:46 -05002825 return tcp_ses;
2826
Shirish Pargaonkarf7c5445a2010-10-26 18:10:24 -05002827out_err_crypto_release:
Pavel Shilovsky026e93d2016-11-03 16:47:37 -07002828 cifs_crypto_secmech_release(tcp_ses);
Shirish Pargaonkard2b91522010-10-21 14:25:08 -05002829
Rob Landleyf1d0c992011-01-22 15:44:05 -06002830 put_net(cifs_net_ns(tcp_ses));
2831
Jeff Layton63c038c2008-12-01 18:41:46 -05002832out_err:
2833 if (tcp_ses) {
Steve French8347a5c2009-10-06 18:31:29 +00002834 if (!IS_ERR(tcp_ses->hostname))
2835 kfree(tcp_ses->hostname);
Jeff Layton63c038c2008-12-01 18:41:46 -05002836 if (tcp_ses->ssocket)
2837 sock_release(tcp_ses->ssocket);
2838 kfree(tcp_ses);
2839 }
2840 return ERR_PTR(rc);
2841}
2842
Steve French96daf2b2011-05-27 04:34:02 +00002843static int match_session(struct cifs_ses *ses, struct smb_vol *vol)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002844{
Jeff Layton3f618222013-06-12 19:52:14 -05002845 if (vol->sectype != Unspecified &&
2846 vol->sectype != ses->sectype)
2847 return 0;
2848
2849 switch (ses->sectype) {
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002850 case Kerberos:
Eric W. Biederman64ed39d2013-02-06 02:30:39 -08002851 if (!uid_eq(vol->cred_uid, ses->cred_uid))
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002852 return 0;
2853 break;
2854 default:
Jeff Layton04febab2012-01-17 16:09:15 -05002855 /* NULL username means anonymous session */
2856 if (ses->user_name == NULL) {
2857 if (!vol->nullauth)
2858 return 0;
2859 break;
2860 }
2861
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002862 /* anything else takes username/password */
Jeff Layton04febab2012-01-17 16:09:15 -05002863 if (strncmp(ses->user_name,
2864 vol->username ? vol->username : "",
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04002865 CIFS_MAX_USERNAME_LEN))
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002866 return 0;
Jeff Layton08b37d52014-05-23 06:53:10 -04002867 if ((vol->username && strlen(vol->username) != 0) &&
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002868 ses->password != NULL &&
2869 strncmp(ses->password,
2870 vol->password ? vol->password : "",
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04002871 CIFS_MAX_PASSWORD_LEN))
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002872 return 0;
2873 }
2874 return 1;
2875}
2876
Aurelien Aptelb327a712018-01-24 13:46:10 +01002877/**
2878 * cifs_setup_ipc - helper to setup the IPC tcon for the session
2879 *
2880 * A new IPC connection is made and stored in the session
2881 * tcon_ipc. The IPC tcon has the same lifetime as the session.
2882 */
2883static int
2884cifs_setup_ipc(struct cifs_ses *ses, struct smb_vol *volume_info)
2885{
2886 int rc = 0, xid;
2887 struct cifs_tcon *tcon;
2888 struct nls_table *nls_codepage;
2889 char unc[SERVER_NAME_LENGTH + sizeof("//x/IPC$")] = {0};
2890 bool seal = false;
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10002891 struct TCP_Server_Info *server = ses->server;
Aurelien Aptelb327a712018-01-24 13:46:10 +01002892
2893 /*
2894 * If the mount request that resulted in the creation of the
2895 * session requires encryption, force IPC to be encrypted too.
2896 */
2897 if (volume_info->seal) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10002898 if (server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION)
Aurelien Aptelb327a712018-01-24 13:46:10 +01002899 seal = true;
2900 else {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10002901 cifs_server_dbg(VFS,
Aurelien Aptelb327a712018-01-24 13:46:10 +01002902 "IPC: server doesn't support encryption\n");
2903 return -EOPNOTSUPP;
2904 }
2905 }
2906
2907 tcon = tconInfoAlloc();
2908 if (tcon == NULL)
2909 return -ENOMEM;
2910
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10002911 scnprintf(unc, sizeof(unc), "\\\\%s\\IPC$", server->hostname);
Aurelien Aptelb327a712018-01-24 13:46:10 +01002912
2913 /* cannot fail */
2914 nls_codepage = load_nls_default();
2915
2916 xid = get_xid();
2917 tcon->ses = ses;
2918 tcon->ipc = true;
2919 tcon->seal = seal;
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10002920 rc = server->ops->tree_connect(xid, ses, unc, tcon, nls_codepage);
Aurelien Aptelb327a712018-01-24 13:46:10 +01002921 free_xid(xid);
2922
2923 if (rc) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10002924 cifs_server_dbg(VFS, "failed to connect to IPC (rc=%d)\n", rc);
Aurelien Aptelb327a712018-01-24 13:46:10 +01002925 tconInfoFree(tcon);
2926 goto out;
2927 }
2928
2929 cifs_dbg(FYI, "IPC tcon rc = %d ipc tid = %d\n", rc, tcon->tid);
2930
2931 ses->tcon_ipc = tcon;
2932out:
2933 unload_nls(nls_codepage);
2934 return rc;
2935}
2936
2937/**
2938 * cifs_free_ipc - helper to release the session IPC tcon
2939 *
2940 * Needs to be called everytime a session is destroyed
2941 */
2942static int
2943cifs_free_ipc(struct cifs_ses *ses)
2944{
2945 int rc = 0, xid;
2946 struct cifs_tcon *tcon = ses->tcon_ipc;
2947
2948 if (tcon == NULL)
2949 return 0;
2950
2951 if (ses->server->ops->tree_disconnect) {
2952 xid = get_xid();
2953 rc = ses->server->ops->tree_disconnect(xid, tcon);
2954 free_xid(xid);
2955 }
2956
2957 if (rc)
2958 cifs_dbg(FYI, "failed to disconnect IPC tcon (rc=%d)\n", rc);
2959
2960 tconInfoFree(tcon);
2961 ses->tcon_ipc = NULL;
2962 return rc;
2963}
2964
Steve French96daf2b2011-05-27 04:34:02 +00002965static struct cifs_ses *
Jeff Layton4ff67b72010-07-06 20:43:02 -04002966cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb_vol *vol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002967{
Steve French96daf2b2011-05-27 04:34:02 +00002968 struct cifs_ses *ses;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002969
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302970 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton4ff67b72010-07-06 20:43:02 -04002971 list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002972 if (ses->status == CifsExiting)
2973 continue;
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002974 if (!match_session(ses, vol))
2975 continue;
Jeff Layton14fbf502008-11-14 13:53:46 -05002976 ++ses->ses_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302977 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002978 return ses;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002979 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302980 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002981 return NULL;
2982}
2983
Paulo Alcantara (SUSE)50720102019-03-19 16:54:29 -03002984void cifs_put_smb_ses(struct cifs_ses *ses)
Jeff Layton14fbf502008-11-14 13:53:46 -05002985{
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002986 unsigned int rc, xid;
Jeff Layton14fbf502008-11-14 13:53:46 -05002987 struct TCP_Server_Info *server = ses->server;
2988
Joe Perchesf96637b2013-05-04 22:12:25 -05002989 cifs_dbg(FYI, "%s: ses_count=%d\n", __func__, ses->ses_count);
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002990
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302991 spin_lock(&cifs_tcp_ses_lock);
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002992 if (ses->status == CifsExiting) {
2993 spin_unlock(&cifs_tcp_ses_lock);
2994 return;
2995 }
Jeff Layton14fbf502008-11-14 13:53:46 -05002996 if (--ses->ses_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302997 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002998 return;
2999 }
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05003000 if (ses->status == CifsGood)
3001 ses->status = CifsExiting;
3002 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05003003
Aurelien Aptelb327a712018-01-24 13:46:10 +01003004 cifs_free_ipc(ses);
3005
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05003006 if (ses->status == CifsExiting && server->ops->logoff) {
3007 xid = get_xid();
3008 rc = server->ops->logoff(xid, ses);
3009 if (rc)
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10003010 cifs_server_dbg(VFS, "%s: Session Logoff failure rc=%d\n",
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05003011 __func__, rc);
3012 _free_xid(xid);
3013 }
3014
3015 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05003016 list_del_init(&ses->smb_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303017 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05003018
Jeff Layton14fbf502008-11-14 13:53:46 -05003019 sesInfoFree(ses);
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07003020 cifs_put_tcp_session(server, 0);
Jeff Layton14fbf502008-11-14 13:53:46 -05003021}
3022
Jeff Layton8a8798a2012-01-17 16:09:15 -05003023#ifdef CONFIG_KEYS
3024
Chen Gang057d6332013-07-19 09:01:36 +08003025/* strlen("cifs:a:") + CIFS_MAX_DOMAINNAME_LEN + 1 */
3026#define CIFSCREDS_DESC_SIZE (7 + CIFS_MAX_DOMAINNAME_LEN + 1)
Jeff Layton8a8798a2012-01-17 16:09:15 -05003027
3028/* Populate username and pw fields from keyring if possible */
3029static int
3030cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses)
3031{
3032 int rc = 0;
Ronnie Sahlbergf2aee322019-08-22 08:09:50 +10003033 int is_domain = 0;
David Howells146aa8b2015-10-21 14:04:48 +01003034 const char *delim, *payload;
3035 char *desc;
Jeff Layton8a8798a2012-01-17 16:09:15 -05003036 ssize_t len;
3037 struct key *key;
3038 struct TCP_Server_Info *server = ses->server;
3039 struct sockaddr_in *sa;
3040 struct sockaddr_in6 *sa6;
David Howells146aa8b2015-10-21 14:04:48 +01003041 const struct user_key_payload *upayload;
Jeff Layton8a8798a2012-01-17 16:09:15 -05003042
3043 desc = kmalloc(CIFSCREDS_DESC_SIZE, GFP_KERNEL);
3044 if (!desc)
3045 return -ENOMEM;
3046
3047 /* try to find an address key first */
3048 switch (server->dstaddr.ss_family) {
3049 case AF_INET:
3050 sa = (struct sockaddr_in *)&server->dstaddr;
3051 sprintf(desc, "cifs:a:%pI4", &sa->sin_addr.s_addr);
3052 break;
3053 case AF_INET6:
3054 sa6 = (struct sockaddr_in6 *)&server->dstaddr;
3055 sprintf(desc, "cifs:a:%pI6c", &sa6->sin6_addr.s6_addr);
3056 break;
3057 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05003058 cifs_dbg(FYI, "Bad ss_family (%hu)\n",
3059 server->dstaddr.ss_family);
Jeff Layton8a8798a2012-01-17 16:09:15 -05003060 rc = -EINVAL;
3061 goto out_err;
3062 }
3063
Joe Perchesf96637b2013-05-04 22:12:25 -05003064 cifs_dbg(FYI, "%s: desc=%s\n", __func__, desc);
Linus Torvalds028db3e2019-07-10 18:43:43 -07003065 key = request_key(&key_type_logon, desc, "");
Jeff Layton8a8798a2012-01-17 16:09:15 -05003066 if (IS_ERR(key)) {
3067 if (!ses->domainName) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003068 cifs_dbg(FYI, "domainName is NULL\n");
Jeff Layton8a8798a2012-01-17 16:09:15 -05003069 rc = PTR_ERR(key);
3070 goto out_err;
3071 }
3072
3073 /* didn't work, try to find a domain key */
3074 sprintf(desc, "cifs:d:%s", ses->domainName);
Joe Perchesf96637b2013-05-04 22:12:25 -05003075 cifs_dbg(FYI, "%s: desc=%s\n", __func__, desc);
Linus Torvalds028db3e2019-07-10 18:43:43 -07003076 key = request_key(&key_type_logon, desc, "");
Jeff Layton8a8798a2012-01-17 16:09:15 -05003077 if (IS_ERR(key)) {
3078 rc = PTR_ERR(key);
3079 goto out_err;
3080 }
Ronnie Sahlbergf2aee322019-08-22 08:09:50 +10003081 is_domain = 1;
Jeff Layton8a8798a2012-01-17 16:09:15 -05003082 }
3083
3084 down_read(&key->sem);
David Howells0837e492017-03-01 15:11:23 +00003085 upayload = user_key_payload_locked(key);
Jeff Layton8a8798a2012-01-17 16:09:15 -05003086 if (IS_ERR_OR_NULL(upayload)) {
Jeff Layton4edc53c2012-02-07 06:30:51 -05003087 rc = upayload ? PTR_ERR(upayload) : -EINVAL;
Jeff Layton8a8798a2012-01-17 16:09:15 -05003088 goto out_key_put;
3089 }
3090
3091 /* find first : in payload */
David Howells146aa8b2015-10-21 14:04:48 +01003092 payload = upayload->data;
Jeff Layton8a8798a2012-01-17 16:09:15 -05003093 delim = strnchr(payload, upayload->datalen, ':');
Joe Perchesf96637b2013-05-04 22:12:25 -05003094 cifs_dbg(FYI, "payload=%s\n", payload);
Jeff Layton8a8798a2012-01-17 16:09:15 -05003095 if (!delim) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003096 cifs_dbg(FYI, "Unable to find ':' in payload (datalen=%d)\n",
3097 upayload->datalen);
Jeff Layton8a8798a2012-01-17 16:09:15 -05003098 rc = -EINVAL;
3099 goto out_key_put;
3100 }
3101
3102 len = delim - payload;
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04003103 if (len > CIFS_MAX_USERNAME_LEN || len <= 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003104 cifs_dbg(FYI, "Bad value from username search (len=%zd)\n",
3105 len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05003106 rc = -EINVAL;
3107 goto out_key_put;
3108 }
3109
3110 vol->username = kstrndup(payload, len, GFP_KERNEL);
3111 if (!vol->username) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003112 cifs_dbg(FYI, "Unable to allocate %zd bytes for username\n",
3113 len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05003114 rc = -ENOMEM;
3115 goto out_key_put;
3116 }
Joe Perchesf96637b2013-05-04 22:12:25 -05003117 cifs_dbg(FYI, "%s: username=%s\n", __func__, vol->username);
Jeff Layton8a8798a2012-01-17 16:09:15 -05003118
3119 len = key->datalen - (len + 1);
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04003120 if (len > CIFS_MAX_PASSWORD_LEN || len <= 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003121 cifs_dbg(FYI, "Bad len for password search (len=%zd)\n", len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05003122 rc = -EINVAL;
3123 kfree(vol->username);
3124 vol->username = NULL;
3125 goto out_key_put;
3126 }
3127
3128 ++delim;
3129 vol->password = kstrndup(delim, len, GFP_KERNEL);
3130 if (!vol->password) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003131 cifs_dbg(FYI, "Unable to allocate %zd bytes for password\n",
3132 len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05003133 rc = -ENOMEM;
3134 kfree(vol->username);
3135 vol->username = NULL;
3136 goto out_key_put;
3137 }
3138
Ronnie Sahlbergf2aee322019-08-22 08:09:50 +10003139 /*
3140 * If we have a domain key then we must set the domainName in the
3141 * for the request.
3142 */
3143 if (is_domain && ses->domainName) {
3144 vol->domainname = kstrndup(ses->domainName,
3145 strlen(ses->domainName),
3146 GFP_KERNEL);
3147 if (!vol->domainname) {
3148 cifs_dbg(FYI, "Unable to allocate %zd bytes for "
3149 "domain\n", len);
3150 rc = -ENOMEM;
3151 kfree(vol->username);
3152 vol->username = NULL;
Dan Carpenter478228e2019-08-27 13:59:17 +03003153 kzfree(vol->password);
Ronnie Sahlbergf2aee322019-08-22 08:09:50 +10003154 vol->password = NULL;
3155 goto out_key_put;
3156 }
3157 }
3158
Jeff Layton8a8798a2012-01-17 16:09:15 -05003159out_key_put:
3160 up_read(&key->sem);
3161 key_put(key);
3162out_err:
3163 kfree(desc);
Joe Perchesf96637b2013-05-04 22:12:25 -05003164 cifs_dbg(FYI, "%s: returning %d\n", __func__, rc);
Jeff Layton8a8798a2012-01-17 16:09:15 -05003165 return rc;
3166}
3167#else /* ! CONFIG_KEYS */
3168static inline int
3169cifs_set_cifscreds(struct smb_vol *vol __attribute__((unused)),
3170 struct cifs_ses *ses __attribute__((unused)))
3171{
3172 return -ENOSYS;
3173}
3174#endif /* CONFIG_KEYS */
3175
Aurelien Aptel4a1360d2018-01-25 18:47:52 +01003176/**
3177 * cifs_get_smb_ses - get a session matching @volume_info data from @server
3178 *
3179 * This function assumes it is being called from cifs_mount() where we
3180 * already got a server reference (server refcount +1). See
3181 * cifs_get_tcon() for refcount explanations.
3182 */
Paulo Alcantara (SUSE)50720102019-03-19 16:54:29 -03003183struct cifs_ses *
Jeff Layton36988c72010-04-24 07:57:43 -04003184cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
3185{
Pavel Shilovsky286170a2012-05-25 10:43:58 +04003186 int rc = -ENOMEM;
3187 unsigned int xid;
Steve French96daf2b2011-05-27 04:34:02 +00003188 struct cifs_ses *ses;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003189 struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
3190 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
Jeff Layton36988c72010-04-24 07:57:43 -04003191
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003192 xid = get_xid();
Jeff Layton36988c72010-04-24 07:57:43 -04003193
Jeff Layton4ff67b72010-07-06 20:43:02 -04003194 ses = cifs_find_smb_ses(server, volume_info);
Jeff Layton36988c72010-04-24 07:57:43 -04003195 if (ses) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003196 cifs_dbg(FYI, "Existing smb sess found (status=%d)\n",
3197 ses->status);
Jeff Layton36988c72010-04-24 07:57:43 -04003198
Jeff Layton36988c72010-04-24 07:57:43 -04003199 mutex_lock(&ses->session_mutex);
Jeff Layton198b5682010-04-24 07:57:48 -04003200 rc = cifs_negotiate_protocol(xid, ses);
3201 if (rc) {
3202 mutex_unlock(&ses->session_mutex);
3203 /* problem -- put our ses reference */
3204 cifs_put_smb_ses(ses);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003205 free_xid(xid);
Jeff Layton198b5682010-04-24 07:57:48 -04003206 return ERR_PTR(rc);
3207 }
Jeff Layton36988c72010-04-24 07:57:43 -04003208 if (ses->need_reconnect) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003209 cifs_dbg(FYI, "Session needs reconnect\n");
Jeff Layton36988c72010-04-24 07:57:43 -04003210 rc = cifs_setup_session(xid, ses,
3211 volume_info->local_nls);
3212 if (rc) {
3213 mutex_unlock(&ses->session_mutex);
3214 /* problem -- put our reference */
3215 cifs_put_smb_ses(ses);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003216 free_xid(xid);
Jeff Layton36988c72010-04-24 07:57:43 -04003217 return ERR_PTR(rc);
3218 }
3219 }
3220 mutex_unlock(&ses->session_mutex);
Jeff Layton460cf342010-09-14 11:38:24 -04003221
3222 /* existing SMB ses has a server reference already */
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07003223 cifs_put_tcp_session(server, 0);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003224 free_xid(xid);
Jeff Layton36988c72010-04-24 07:57:43 -04003225 return ses;
3226 }
3227
Joe Perchesf96637b2013-05-04 22:12:25 -05003228 cifs_dbg(FYI, "Existing smb sess not found\n");
Jeff Layton36988c72010-04-24 07:57:43 -04003229 ses = sesInfoAlloc();
3230 if (ses == NULL)
3231 goto get_ses_fail;
3232
3233 /* new SMB session uses our server ref */
3234 ses->server = server;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003235 if (server->dstaddr.ss_family == AF_INET6)
3236 sprintf(ses->serverName, "%pI6", &addr6->sin6_addr);
Jeff Layton36988c72010-04-24 07:57:43 -04003237 else
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003238 sprintf(ses->serverName, "%pI4", &addr->sin_addr);
Jeff Layton36988c72010-04-24 07:57:43 -04003239
Steve French8727c8a2011-02-25 01:11:56 -06003240 if (volume_info->username) {
3241 ses->user_name = kstrdup(volume_info->username, GFP_KERNEL);
3242 if (!ses->user_name)
3243 goto get_ses_fail;
3244 }
Jeff Layton36988c72010-04-24 07:57:43 -04003245
3246 /* volume_info->password freed at unmount */
3247 if (volume_info->password) {
3248 ses->password = kstrdup(volume_info->password, GFP_KERNEL);
3249 if (!ses->password)
3250 goto get_ses_fail;
3251 }
3252 if (volume_info->domainname) {
Shirish Pargaonkard3686d52010-10-28 09:53:07 -05003253 ses->domainName = kstrdup(volume_info->domainname, GFP_KERNEL);
3254 if (!ses->domainName)
3255 goto get_ses_fail;
Jeff Layton36988c72010-04-24 07:57:43 -04003256 }
Germano Percossi39566442016-12-15 12:31:18 +05303257 if (volume_info->domainauto)
3258 ses->domainAuto = volume_info->domainauto;
Jeff Layton3e4b3e12010-07-19 18:00:17 -04003259 ses->cred_uid = volume_info->cred_uid;
Jeff Layton36988c72010-04-24 07:57:43 -04003260 ses->linux_uid = volume_info->linux_uid;
Steve Frenchd9b94202011-04-12 01:24:57 +00003261
Jeff Layton28e11bd2013-05-26 07:01:00 -04003262 ses->sectype = volume_info->sectype;
3263 ses->sign = volume_info->sign;
Jeff Layton36988c72010-04-24 07:57:43 -04003264 mutex_lock(&ses->session_mutex);
Jeff Layton198b5682010-04-24 07:57:48 -04003265 rc = cifs_negotiate_protocol(xid, ses);
3266 if (!rc)
3267 rc = cifs_setup_session(xid, ses, volume_info->local_nls);
Jeff Layton36988c72010-04-24 07:57:43 -04003268 mutex_unlock(&ses->session_mutex);
Steve Frenchc8e56f12010-09-08 21:10:58 +00003269 if (rc)
Jeff Layton36988c72010-04-24 07:57:43 -04003270 goto get_ses_fail;
3271
3272 /* success, put it on the list */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303273 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton36988c72010-04-24 07:57:43 -04003274 list_add(&ses->smb_ses_list, &server->smb_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303275 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton36988c72010-04-24 07:57:43 -04003276
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003277 free_xid(xid);
Aurelien Aptelb327a712018-01-24 13:46:10 +01003278
3279 cifs_setup_ipc(ses, volume_info);
3280
Jeff Layton36988c72010-04-24 07:57:43 -04003281 return ses;
3282
3283get_ses_fail:
3284 sesInfoFree(ses);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003285 free_xid(xid);
Jeff Layton36988c72010-04-24 07:57:43 -04003286 return ERR_PTR(rc);
3287}
3288
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003289static int match_tcon(struct cifs_tcon *tcon, struct smb_vol *volume_info)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00003290{
3291 if (tcon->tidStatus == CifsExiting)
3292 return 0;
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003293 if (strncmp(tcon->treeName, volume_info->UNC, MAX_TREE_SIZE))
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00003294 return 0;
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003295 if (tcon->seal != volume_info->seal)
3296 return 0;
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003297 if (tcon->snapshot_time != volume_info->snapshot_time)
3298 return 0;
Steve Frenchca567eb2019-03-29 16:31:07 -05003299 if (tcon->handle_timeout != volume_info->handle_timeout)
3300 return 0;
Steve French3e7a02d2019-09-11 21:46:20 -05003301 if (tcon->no_lease != volume_info->no_lease)
3302 return 0;
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00003303 return 1;
3304}
3305
Steve French96daf2b2011-05-27 04:34:02 +00003306static struct cifs_tcon *
Steve French8b217fe2016-11-11 22:36:20 -06003307cifs_find_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003308{
3309 struct list_head *tmp;
Steve French96daf2b2011-05-27 04:34:02 +00003310 struct cifs_tcon *tcon;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003311
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303312 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05003313 list_for_each(tmp, &ses->tcon_list) {
Steve French96daf2b2011-05-27 04:34:02 +00003314 tcon = list_entry(tmp, struct cifs_tcon, tcon_list);
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003315 if (!match_tcon(tcon, volume_info))
Jeff Laytonf1987b42008-11-15 11:12:47 -05003316 continue;
Jeff Laytonf1987b42008-11-15 11:12:47 -05003317 ++tcon->tc_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303318 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003319 return tcon;
3320 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303321 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003322 return NULL;
3323}
3324
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07003325void
Steve French96daf2b2011-05-27 04:34:02 +00003326cifs_put_tcon(struct cifs_tcon *tcon)
Jeff Laytonf1987b42008-11-15 11:12:47 -05003327{
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003328 unsigned int xid;
Aurelien Aptelb327a712018-01-24 13:46:10 +01003329 struct cifs_ses *ses;
Jeff Laytonf1987b42008-11-15 11:12:47 -05003330
Aurelien Aptelb327a712018-01-24 13:46:10 +01003331 /*
3332 * IPC tcon share the lifetime of their session and are
3333 * destroyed in the session put function
3334 */
3335 if (tcon == NULL || tcon->ipc)
3336 return;
3337
3338 ses = tcon->ses;
Joe Perchesf96637b2013-05-04 22:12:25 -05003339 cifs_dbg(FYI, "%s: tc_count=%d\n", __func__, tcon->tc_count);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303340 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05003341 if (--tcon->tc_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303342 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05003343 return;
3344 }
3345
3346 list_del_init(&tcon->tcon_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303347 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05003348
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003349 xid = get_xid();
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003350 if (ses->server->ops->tree_disconnect)
3351 ses->server->ops->tree_disconnect(xid, tcon);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003352 _free_xid(xid);
Jeff Laytonf1987b42008-11-15 11:12:47 -05003353
Suresh Jayaramand03382c2010-07-05 18:12:27 +05303354 cifs_fscache_release_super_cookie(tcon);
Steve French9f841592010-07-23 20:37:53 +00003355 tconInfoFree(tcon);
Jeff Laytonf1987b42008-11-15 11:12:47 -05003356 cifs_put_smb_ses(ses);
3357}
3358
Aurelien Aptel4a1360d2018-01-25 18:47:52 +01003359/**
3360 * cifs_get_tcon - get a tcon matching @volume_info data from @ses
3361 *
3362 * - tcon refcount is the number of mount points using the tcon.
3363 * - ses refcount is the number of tcon using the session.
3364 *
3365 * 1. This function assumes it is being called from cifs_mount() where
3366 * we already got a session reference (ses refcount +1).
3367 *
3368 * 2. Since we're in the context of adding a mount point, the end
3369 * result should be either:
3370 *
3371 * a) a new tcon already allocated with refcount=1 (1 mount point) and
3372 * its session refcount incremented (1 new tcon). This +1 was
3373 * already done in (1).
3374 *
3375 * b) an existing tcon with refcount+1 (add a mount point to it) and
3376 * identical ses refcount (no new tcon). Because of (1) we need to
3377 * decrement the ses refcount.
3378 */
Steve French96daf2b2011-05-27 04:34:02 +00003379static struct cifs_tcon *
3380cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
Jeff Laytond00c28d2010-04-24 07:57:44 -04003381{
3382 int rc, xid;
Steve French96daf2b2011-05-27 04:34:02 +00003383 struct cifs_tcon *tcon;
Jeff Laytond00c28d2010-04-24 07:57:44 -04003384
Steve French8b217fe2016-11-11 22:36:20 -06003385 tcon = cifs_find_tcon(ses, volume_info);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003386 if (tcon) {
Aurelien Aptel4a1360d2018-01-25 18:47:52 +01003387 /*
3388 * tcon has refcount already incremented but we need to
3389 * decrement extra ses reference gotten by caller (case b)
3390 */
Joe Perchesf96637b2013-05-04 22:12:25 -05003391 cifs_dbg(FYI, "Found match on UNC path\n");
Jeff Laytond00c28d2010-04-24 07:57:44 -04003392 cifs_put_smb_ses(ses);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003393 return tcon;
3394 }
3395
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003396 if (!ses->server->ops->tree_connect) {
3397 rc = -ENOSYS;
3398 goto out_fail;
3399 }
3400
Jeff Laytond00c28d2010-04-24 07:57:44 -04003401 tcon = tconInfoAlloc();
3402 if (tcon == NULL) {
3403 rc = -ENOMEM;
3404 goto out_fail;
3405 }
3406
Steve French8b217fe2016-11-11 22:36:20 -06003407 if (volume_info->snapshot_time) {
Steve French8b217fe2016-11-11 22:36:20 -06003408 if (ses->server->vals->protocol_id == 0) {
3409 cifs_dbg(VFS,
3410 "Use SMB2 or later for snapshot mount option\n");
3411 rc = -EOPNOTSUPP;
3412 goto out_fail;
3413 } else
3414 tcon->snapshot_time = volume_info->snapshot_time;
Steve French8b217fe2016-11-11 22:36:20 -06003415 }
3416
Steve Frenchca567eb2019-03-29 16:31:07 -05003417 if (volume_info->handle_timeout) {
3418 if (ses->server->vals->protocol_id == 0) {
3419 cifs_dbg(VFS,
3420 "Use SMB2.1 or later for handle timeout option\n");
3421 rc = -EOPNOTSUPP;
3422 goto out_fail;
3423 } else
3424 tcon->handle_timeout = volume_info->handle_timeout;
3425 }
3426
Jeff Laytond00c28d2010-04-24 07:57:44 -04003427 tcon->ses = ses;
3428 if (volume_info->password) {
3429 tcon->password = kstrdup(volume_info->password, GFP_KERNEL);
3430 if (!tcon->password) {
3431 rc = -ENOMEM;
3432 goto out_fail;
3433 }
3434 }
3435
Steve French23657ad2018-04-22 15:14:58 -05003436 if (volume_info->seal) {
3437 if (ses->server->vals->protocol_id == 0) {
3438 cifs_dbg(VFS,
3439 "SMB3 or later required for encryption\n");
3440 rc = -EOPNOTSUPP;
3441 goto out_fail;
3442 } else if (tcon->ses->server->capabilities &
3443 SMB2_GLOBAL_CAP_ENCRYPTION)
3444 tcon->seal = true;
3445 else {
3446 cifs_dbg(VFS, "Encryption is not supported on share\n");
3447 rc = -EOPNOTSUPP;
3448 goto out_fail;
3449 }
3450 }
3451
Steve French8505c8b2018-06-18 14:01:59 -05003452 if (volume_info->linux_ext) {
3453 if (ses->server->posix_ext_supported) {
Steve Frenchb3266142018-05-20 23:41:10 -05003454 tcon->posix_extensions = true;
Steve French2fbb5642018-06-12 12:11:31 -05003455 printk_once(KERN_WARNING
3456 "SMB3.11 POSIX Extensions are experimental\n");
Steve French8505c8b2018-06-18 14:01:59 -05003457 } else {
3458 cifs_dbg(VFS, "Server does not support mounting with posix SMB3.11 extensions.\n");
3459 rc = -EOPNOTSUPP;
3460 goto out_fail;
Steve French2fbb5642018-06-12 12:11:31 -05003461 }
Steve Frenchb3266142018-05-20 23:41:10 -05003462 }
Steve Frenchb3266142018-05-20 23:41:10 -05003463
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003464 /*
3465 * BB Do we need to wrap session_mutex around this TCon call and Unix
3466 * SetFS as we do on SessSetup and reconnect?
3467 */
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003468 xid = get_xid();
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003469 rc = ses->server->ops->tree_connect(xid, ses, volume_info->UNC, tcon,
3470 volume_info->local_nls);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003471 free_xid(xid);
Joe Perchesf96637b2013-05-04 22:12:25 -05003472 cifs_dbg(FYI, "Tcon rc = %d\n", rc);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003473 if (rc)
3474 goto out_fail;
3475
Steve Frenchb618f002015-11-03 09:15:03 -06003476 tcon->use_persistent = false;
3477 /* check if SMB2 or later, CIFS does not support persistent handles */
3478 if (volume_info->persistent) {
3479 if (ses->server->vals->protocol_id == 0) {
3480 cifs_dbg(VFS,
3481 "SMB3 or later required for persistent handles\n");
3482 rc = -EOPNOTSUPP;
3483 goto out_fail;
3484 } else if (ses->server->capabilities &
3485 SMB2_GLOBAL_CAP_PERSISTENT_HANDLES)
3486 tcon->use_persistent = true;
3487 else /* persistent handles requested but not supported */ {
3488 cifs_dbg(VFS,
3489 "Persistent handles not supported on share\n");
3490 rc = -EOPNOTSUPP;
3491 goto out_fail;
3492 }
3493 } else if ((tcon->capabilities & SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY)
3494 && (ses->server->capabilities & SMB2_GLOBAL_CAP_PERSISTENT_HANDLES)
3495 && (volume_info->nopersistent == false)) {
3496 cifs_dbg(FYI, "enabling persistent handles\n");
3497 tcon->use_persistent = true;
Steve French592fafe2015-11-03 10:08:53 -06003498 } else if (volume_info->resilient) {
3499 if (ses->server->vals->protocol_id == 0) {
3500 cifs_dbg(VFS,
3501 "SMB2.1 or later required for resilient handles\n");
3502 rc = -EOPNOTSUPP;
3503 goto out_fail;
3504 }
3505 tcon->use_resilient = true;
Steve Frenchb618f002015-11-03 09:15:03 -06003506 }
3507
Steve Frenchcae53f72019-09-03 17:49:46 -05003508 /* If the user really knows what they are doing they can override */
3509 if (tcon->share_flags & SMB2_SHAREFLAG_NO_CACHING) {
3510 if (volume_info->cache_ro)
3511 cifs_dbg(VFS, "cache=ro requested on mount but NO_CACHING flag set on share\n");
3512 else if (volume_info->cache_rw)
3513 cifs_dbg(VFS, "cache=singleclient requested on mount but NO_CACHING flag set on share\n");
3514 }
3515
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003516 /*
3517 * We can have only one retry value for a connection to a share so for
3518 * resources mounted more than once to the same server share the last
3519 * value passed in for the retry flag is used.
3520 */
Jeff Laytond00c28d2010-04-24 07:57:44 -04003521 tcon->retry = volume_info->retry;
3522 tcon->nocase = volume_info->nocase;
Steve French3d4ef9a2018-04-25 22:19:09 -05003523 tcon->nohandlecache = volume_info->nohandlecache;
Jeff Laytond00c28d2010-04-24 07:57:44 -04003524 tcon->local_lease = volume_info->local_lease;
Steve French3e7a02d2019-09-11 21:46:20 -05003525 tcon->no_lease = volume_info->no_lease;
Pavel Shilovsky233839b2012-09-19 06:22:45 -07003526 INIT_LIST_HEAD(&tcon->pending_opens);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003527
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303528 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003529 list_add(&tcon->tcon_list, &ses->tcon_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303530 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003531
Suresh Jayaramand03382c2010-07-05 18:12:27 +05303532 cifs_fscache_get_super_cookie(tcon);
3533
Jeff Laytond00c28d2010-04-24 07:57:44 -04003534 return tcon;
3535
3536out_fail:
3537 tconInfoFree(tcon);
3538 return ERR_PTR(rc);
3539}
3540
Jeff Layton9d002df2010-10-06 19:51:11 -04003541void
3542cifs_put_tlink(struct tcon_link *tlink)
3543{
3544 if (!tlink || IS_ERR(tlink))
3545 return;
3546
3547 if (!atomic_dec_and_test(&tlink->tl_count) ||
3548 test_bit(TCON_LINK_IN_TREE, &tlink->tl_flags)) {
3549 tlink->tl_time = jiffies;
3550 return;
3551 }
3552
3553 if (!IS_ERR(tlink_tcon(tlink)))
3554 cifs_put_tcon(tlink_tcon(tlink));
3555 kfree(tlink);
3556 return;
3557}
Jeff Laytond00c28d2010-04-24 07:57:44 -04003558
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003559static int
3560compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data)
3561{
3562 struct cifs_sb_info *old = CIFS_SB(sb);
3563 struct cifs_sb_info *new = mnt_data->cifs_sb;
Paulo Alcantara (SUSE)29fbeb72019-06-18 16:16:02 -03003564 unsigned int oldflags = old->mnt_cifs_flags & CIFS_MOUNT_MASK;
3565 unsigned int newflags = new->mnt_cifs_flags & CIFS_MOUNT_MASK;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003566
3567 if ((sb->s_flags & CIFS_MS_MASK) != (mnt_data->flags & CIFS_MS_MASK))
3568 return 0;
3569
Paulo Alcantara (SUSE)29fbeb72019-06-18 16:16:02 -03003570 if (old->mnt_cifs_serverino_autodisabled)
3571 newflags &= ~CIFS_MOUNT_SERVER_INUM;
3572
3573 if (oldflags != newflags)
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003574 return 0;
3575
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003576 /*
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003577 * We want to share sb only if we don't specify an r/wsize or
3578 * specified r/wsize is greater than or equal to existing one.
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003579 */
3580 if (new->wsize && new->wsize < old->wsize)
3581 return 0;
3582
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003583 if (new->rsize && new->rsize < old->rsize)
3584 return 0;
3585
Eric W. Biederman1f682332013-02-06 01:20:20 -08003586 if (!uid_eq(old->mnt_uid, new->mnt_uid) || !gid_eq(old->mnt_gid, new->mnt_gid))
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003587 return 0;
3588
3589 if (old->mnt_file_mode != new->mnt_file_mode ||
3590 old->mnt_dir_mode != new->mnt_dir_mode)
3591 return 0;
3592
3593 if (strcmp(old->local_nls->charset, new->local_nls->charset))
3594 return 0;
3595
3596 if (old->actimeo != new->actimeo)
3597 return 0;
3598
3599 return 1;
3600}
3601
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01003602static int
3603match_prepath(struct super_block *sb, struct cifs_mnt_data *mnt_data)
3604{
3605 struct cifs_sb_info *old = CIFS_SB(sb);
3606 struct cifs_sb_info *new = mnt_data->cifs_sb;
Sachin Prabhucd8c4292017-04-26 14:05:46 +01003607 bool old_set = old->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH;
3608 bool new_set = new->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH;
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01003609
Sachin Prabhucd8c4292017-04-26 14:05:46 +01003610 if (old_set && new_set && !strcmp(new->prepath, old->prepath))
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01003611 return 1;
Sachin Prabhucd8c4292017-04-26 14:05:46 +01003612 else if (!old_set && !new_set)
3613 return 1;
3614
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01003615 return 0;
3616}
3617
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003618int
3619cifs_match_super(struct super_block *sb, void *data)
3620{
3621 struct cifs_mnt_data *mnt_data = (struct cifs_mnt_data *)data;
3622 struct smb_vol *volume_info;
3623 struct cifs_sb_info *cifs_sb;
3624 struct TCP_Server_Info *tcp_srv;
Steve French96daf2b2011-05-27 04:34:02 +00003625 struct cifs_ses *ses;
3626 struct cifs_tcon *tcon;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003627 struct tcon_link *tlink;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003628 int rc = 0;
3629
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003630 spin_lock(&cifs_tcp_ses_lock);
3631 cifs_sb = CIFS_SB(sb);
3632 tlink = cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
3633 if (IS_ERR(tlink)) {
3634 spin_unlock(&cifs_tcp_ses_lock);
3635 return rc;
3636 }
3637 tcon = tlink_tcon(tlink);
3638 ses = tcon->ses;
3639 tcp_srv = ses->server;
3640
3641 volume_info = mnt_data->vol;
3642
Jeff Layton9fa114f2012-11-26 11:09:57 -05003643 if (!match_server(tcp_srv, volume_info) ||
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003644 !match_session(ses, volume_info) ||
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003645 !match_tcon(tcon, volume_info) ||
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01003646 !match_prepath(sb, mnt_data)) {
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003647 rc = 0;
3648 goto out;
3649 }
3650
3651 rc = compare_mount_options(sb, mnt_data);
3652out:
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003653 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf484b5d02011-07-11 10:16:34 -04003654 cifs_put_tlink(tlink);
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003655 return rc;
3656}
3657
Jeff Layton09e50d52008-07-23 10:11:19 -04003658#ifdef CONFIG_DEBUG_LOCK_ALLOC
3659static struct lock_class_key cifs_key[2];
3660static struct lock_class_key cifs_slock_key[2];
3661
3662static inline void
3663cifs_reclassify_socket4(struct socket *sock)
3664{
3665 struct sock *sk = sock->sk;
Hannes Frederic Sowafafc4e12016-04-08 15:11:27 +02003666 BUG_ON(!sock_allow_reclassification(sk));
Jeff Layton09e50d52008-07-23 10:11:19 -04003667 sock_lock_init_class_and_name(sk, "slock-AF_INET-CIFS",
3668 &cifs_slock_key[0], "sk_lock-AF_INET-CIFS", &cifs_key[0]);
3669}
3670
3671static inline void
3672cifs_reclassify_socket6(struct socket *sock)
3673{
3674 struct sock *sk = sock->sk;
Hannes Frederic Sowafafc4e12016-04-08 15:11:27 +02003675 BUG_ON(!sock_allow_reclassification(sk));
Jeff Layton09e50d52008-07-23 10:11:19 -04003676 sock_lock_init_class_and_name(sk, "slock-AF_INET6-CIFS",
3677 &cifs_slock_key[1], "sk_lock-AF_INET6-CIFS", &cifs_key[1]);
3678}
3679#else
3680static inline void
3681cifs_reclassify_socket4(struct socket *sock)
3682{
3683}
3684
3685static inline void
3686cifs_reclassify_socket6(struct socket *sock)
3687{
3688}
3689#endif
3690
Linus Torvalds1da177e2005-04-16 15:20:36 -07003691/* See RFC1001 section 14 on representation of Netbios names */
Steve French50c2f752007-07-13 00:33:32 +00003692static void rfc1002mangle(char *target, char *source, unsigned int length)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003693{
Steve French50c2f752007-07-13 00:33:32 +00003694 unsigned int i, j;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003695
Steve French50c2f752007-07-13 00:33:32 +00003696 for (i = 0, j = 0; i < (length); i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003697 /* mask a nibble at a time and encode */
3698 target[j] = 'A' + (0x0F & (source[i] >> 4));
3699 target[j+1] = 'A' + (0x0F & source[i]);
Steve French50c2f752007-07-13 00:33:32 +00003700 j += 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003701 }
3702
3703}
3704
Ben Greear3eb9a882010-09-01 17:06:02 -07003705static int
3706bind_socket(struct TCP_Server_Info *server)
3707{
3708 int rc = 0;
3709 if (server->srcaddr.ss_family != AF_UNSPEC) {
3710 /* Bind to the specified local IP address */
3711 struct socket *socket = server->ssocket;
3712 rc = socket->ops->bind(socket,
3713 (struct sockaddr *) &server->srcaddr,
3714 sizeof(server->srcaddr));
3715 if (rc < 0) {
3716 struct sockaddr_in *saddr4;
3717 struct sockaddr_in6 *saddr6;
3718 saddr4 = (struct sockaddr_in *)&server->srcaddr;
3719 saddr6 = (struct sockaddr_in6 *)&server->srcaddr;
3720 if (saddr6->sin6_family == AF_INET6)
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10003721 cifs_server_dbg(VFS, "Failed to bind to: %pI6c, error: %d\n",
Joe Perchesf96637b2013-05-04 22:12:25 -05003722 &saddr6->sin6_addr, rc);
Ben Greear3eb9a882010-09-01 17:06:02 -07003723 else
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10003724 cifs_server_dbg(VFS, "Failed to bind to: %pI4, error: %d\n",
Joe Perchesf96637b2013-05-04 22:12:25 -05003725 &saddr4->sin_addr.s_addr, rc);
Ben Greear3eb9a882010-09-01 17:06:02 -07003726 }
3727 }
3728 return rc;
3729}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003730
3731static int
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003732ip_rfc1001_connect(struct TCP_Server_Info *server)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003733{
3734 int rc = 0;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003735 /*
3736 * some servers require RFC1001 sessinit before sending
3737 * negprot - BB check reconnection in case where second
3738 * sessinit is sent but no second negprot
3739 */
3740 struct rfc1002_session_packet *ses_init_buf;
3741 struct smb_hdr *smb_buf;
3742 ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet),
3743 GFP_KERNEL);
3744 if (ses_init_buf) {
3745 ses_init_buf->trailer.session_req.called_len = 32;
3746
Colin Ian King997152f2016-01-25 16:25:54 +00003747 if (server->server_RFC1001_name[0] != 0)
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003748 rfc1002mangle(ses_init_buf->trailer.
3749 session_req.called_name,
3750 server->server_RFC1001_name,
3751 RFC1001_NAME_LEN_WITH_NULL);
3752 else
3753 rfc1002mangle(ses_init_buf->trailer.
3754 session_req.called_name,
3755 DEFAULT_CIFS_CALLED_NAME,
3756 RFC1001_NAME_LEN_WITH_NULL);
3757
3758 ses_init_buf->trailer.session_req.calling_len = 32;
3759
3760 /*
3761 * calling name ends in null (byte 16) from old smb
3762 * convention.
3763 */
Steve Frenchc85c35f2015-03-27 01:15:02 -05003764 if (server->workstation_RFC1001_name[0] != 0)
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003765 rfc1002mangle(ses_init_buf->trailer.
3766 session_req.calling_name,
3767 server->workstation_RFC1001_name,
3768 RFC1001_NAME_LEN_WITH_NULL);
3769 else
3770 rfc1002mangle(ses_init_buf->trailer.
3771 session_req.calling_name,
3772 "LINUX_CIFS_CLNT",
3773 RFC1001_NAME_LEN_WITH_NULL);
3774
3775 ses_init_buf->trailer.session_req.scope1 = 0;
3776 ses_init_buf->trailer.session_req.scope2 = 0;
3777 smb_buf = (struct smb_hdr *)ses_init_buf;
3778
3779 /* sizeof RFC1002_SESSION_REQUEST with no scope */
Steve Frenchbe8e3b02011-04-29 05:40:20 +00003780 smb_buf->smb_buf_length = cpu_to_be32(0x81000044);
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003781 rc = smb_send(server, smb_buf, 0x44);
3782 kfree(ses_init_buf);
3783 /*
3784 * RFC1001 layer in at least one server
3785 * requires very short break before negprot
3786 * presumably because not expecting negprot
3787 * to follow so fast. This is a simple
3788 * solution that works without
3789 * complicating the code and causes no
3790 * significant slowing down on mount
3791 * for everyone else
3792 */
3793 usleep_range(1000, 2000);
3794 }
3795 /*
3796 * else the negprot may still work without this
3797 * even though malloc failed
3798 */
3799
3800 return rc;
3801}
3802
3803static int
3804generic_ip_connect(struct TCP_Server_Info *server)
3805{
3806 int rc = 0;
Steve French6da97912011-03-13 18:55:55 +00003807 __be16 sport;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003808 int slen, sfamily;
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003809 struct socket *socket = server->ssocket;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003810 struct sockaddr *saddr;
3811
3812 saddr = (struct sockaddr *) &server->dstaddr;
3813
3814 if (server->dstaddr.ss_family == AF_INET6) {
3815 sport = ((struct sockaddr_in6 *) saddr)->sin6_port;
3816 slen = sizeof(struct sockaddr_in6);
3817 sfamily = AF_INET6;
3818 } else {
3819 sport = ((struct sockaddr_in *) saddr)->sin_port;
3820 slen = sizeof(struct sockaddr_in);
3821 sfamily = AF_INET;
3822 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003823
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003824 if (socket == NULL) {
Rob Landleyf1d0c992011-01-22 15:44:05 -06003825 rc = __sock_create(cifs_net_ns(server), sfamily, SOCK_STREAM,
3826 IPPROTO_TCP, &socket, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003827 if (rc < 0) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10003828 cifs_server_dbg(VFS, "Error %d creating socket\n", rc);
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003829 server->ssocket = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003830 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003831 }
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003832
3833 /* BB other socket options to set KEEPALIVE, NODELAY? */
Joe Perchesf96637b2013-05-04 22:12:25 -05003834 cifs_dbg(FYI, "Socket created\n");
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003835 server->ssocket = socket;
3836 socket->sk->sk_allocation = GFP_NOFS;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003837 if (sfamily == AF_INET6)
3838 cifs_reclassify_socket6(socket);
3839 else
3840 cifs_reclassify_socket4(socket);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003841 }
3842
Ben Greear3eb9a882010-09-01 17:06:02 -07003843 rc = bind_socket(server);
3844 if (rc < 0)
3845 return rc;
3846
Jeff Laytond5c56052008-12-01 18:42:33 -05003847 /*
3848 * Eventually check for other socket options to change from
3849 * the default. sock_setsockopt not used because it expects
3850 * user space buffer
3851 */
3852 socket->sk->sk_rcvtimeo = 7 * HZ;
Steve Frenchda505c32009-01-19 03:49:35 +00003853 socket->sk->sk_sndtimeo = 5 * HZ;
Steve French6a5fa2362010-01-01 01:28:43 +00003854
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003855 /* make the bufsizes depend on wsize/rsize and max requests */
3856 if (server->noautotune) {
3857 if (socket->sk->sk_sndbuf < (200 * 1024))
3858 socket->sk->sk_sndbuf = 200 * 1024;
3859 if (socket->sk->sk_rcvbuf < (140 * 1024))
3860 socket->sk->sk_rcvbuf = 140 * 1024;
3861 }
3862
Steve French6a5fa2362010-01-01 01:28:43 +00003863 if (server->tcp_nodelay) {
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003864 int val = 1;
Steve French6a5fa2362010-01-01 01:28:43 +00003865 rc = kernel_setsockopt(socket, SOL_TCP, TCP_NODELAY,
3866 (char *)&val, sizeof(val));
3867 if (rc)
Joe Perchesf96637b2013-05-04 22:12:25 -05003868 cifs_dbg(FYI, "set TCP_NODELAY socket option error %d\n",
3869 rc);
Steve French6a5fa2362010-01-01 01:28:43 +00003870 }
3871
Joe Perchesf96637b2013-05-04 22:12:25 -05003872 cifs_dbg(FYI, "sndbuf %d rcvbuf %d rcvtimeo 0x%lx\n",
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003873 socket->sk->sk_sndbuf,
3874 socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo);
3875
Jeff Laytonee1b3ea2011-06-21 07:18:26 -04003876 rc = socket->ops->connect(socket, saddr, slen, 0);
3877 if (rc < 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003878 cifs_dbg(FYI, "Error %d connecting to server\n", rc);
Jeff Laytonee1b3ea2011-06-21 07:18:26 -04003879 sock_release(socket);
3880 server->ssocket = NULL;
3881 return rc;
3882 }
3883
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003884 if (sport == htons(RFC1001_PORT))
3885 rc = ip_rfc1001_connect(server);
Steve French50c2f752007-07-13 00:33:32 +00003886
Linus Torvalds1da177e2005-04-16 15:20:36 -07003887 return rc;
3888}
3889
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003890static int
3891ip_connect(struct TCP_Server_Info *server)
3892{
Steve French6da97912011-03-13 18:55:55 +00003893 __be16 *sport;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003894 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
3895 struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
3896
3897 if (server->dstaddr.ss_family == AF_INET6)
3898 sport = &addr6->sin6_port;
3899 else
3900 sport = &addr->sin_port;
3901
3902 if (*sport == 0) {
3903 int rc;
3904
3905 /* try with 445 port at first */
3906 *sport = htons(CIFS_PORT);
3907
3908 rc = generic_ip_connect(server);
3909 if (rc >= 0)
3910 return rc;
3911
3912 /* if it failed, try with 139 port */
3913 *sport = htons(RFC1001_PORT);
3914 }
3915
3916 return generic_ip_connect(server);
3917}
3918
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003919void reset_cifs_unix_caps(unsigned int xid, struct cifs_tcon *tcon,
Al Viro2c6292a2011-06-17 09:05:48 -04003920 struct cifs_sb_info *cifs_sb, struct smb_vol *vol_info)
Steve French8af18972007-02-14 04:42:51 +00003921{
3922 /* if we are reconnecting then should we check to see if
3923 * any requested capabilities changed locally e.g. via
3924 * remount but we can not do much about it here
3925 * if they have (even if we could detect it by the following)
3926 * Perhaps we could add a backpointer to array of sb from tcon
3927 * or if we change to make all sb to same share the same
3928 * sb as NFS - then we only have one backpointer to sb.
3929 * What if we wanted to mount the server share twice once with
3930 * and once without posixacls or posix paths? */
3931 __u64 saved_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
Steve French50c2f752007-07-13 00:33:32 +00003932
Steve Frenchc18c8422007-07-18 23:21:09 +00003933 if (vol_info && vol_info->no_linux_ext) {
3934 tcon->fsUnixInfo.Capability = 0;
3935 tcon->unix_ext = 0; /* Unix Extensions disabled */
Joe Perchesf96637b2013-05-04 22:12:25 -05003936 cifs_dbg(FYI, "Linux protocol extensions disabled\n");
Steve Frenchc18c8422007-07-18 23:21:09 +00003937 return;
3938 } else if (vol_info)
3939 tcon->unix_ext = 1; /* Unix Extensions supported */
3940
3941 if (tcon->unix_ext == 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003942 cifs_dbg(FYI, "Unix extensions disabled so not set on reconnect\n");
Steve Frenchc18c8422007-07-18 23:21:09 +00003943 return;
3944 }
Steve French50c2f752007-07-13 00:33:32 +00003945
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003946 if (!CIFSSMBQFSUnixInfo(xid, tcon)) {
Steve French8af18972007-02-14 04:42:51 +00003947 __u64 cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
Joe Perchesf96637b2013-05-04 22:12:25 -05003948 cifs_dbg(FYI, "unix caps which server supports %lld\n", cap);
Steve French8af18972007-02-14 04:42:51 +00003949 /* check for reconnect case in which we do not
3950 want to change the mount behavior if we can avoid it */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003951 if (vol_info == NULL) {
Steve French50c2f752007-07-13 00:33:32 +00003952 /* turn off POSIX ACL and PATHNAMES if not set
Steve French8af18972007-02-14 04:42:51 +00003953 originally at mount time */
3954 if ((saved_cap & CIFS_UNIX_POSIX_ACL_CAP) == 0)
3955 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
Igor Mammedov11b6d642008-02-15 19:06:04 +00003956 if ((saved_cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
3957 if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003958 cifs_dbg(VFS, "POSIXPATH support change\n");
Steve French8af18972007-02-14 04:42:51 +00003959 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
Igor Mammedov11b6d642008-02-15 19:06:04 +00003960 } else if ((cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003961 cifs_dbg(VFS, "possible reconnect error\n");
3962 cifs_dbg(VFS, "server disabled POSIX path support\n");
Igor Mammedov11b6d642008-02-15 19:06:04 +00003963 }
Steve French8af18972007-02-14 04:42:51 +00003964 }
Steve French50c2f752007-07-13 00:33:32 +00003965
Steve French6848b732011-05-26 18:38:54 +00003966 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003967 cifs_dbg(VFS, "per-share encryption not supported yet\n");
Steve French6848b732011-05-26 18:38:54 +00003968
Steve French8af18972007-02-14 04:42:51 +00003969 cap &= CIFS_UNIX_CAP_MASK;
Steve French75865f8c2007-06-24 18:30:48 +00003970 if (vol_info && vol_info->no_psx_acl)
Steve French8af18972007-02-14 04:42:51 +00003971 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
Steve French75865f8c2007-06-24 18:30:48 +00003972 else if (CIFS_UNIX_POSIX_ACL_CAP & cap) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003973 cifs_dbg(FYI, "negotiated posix acl support\n");
Al Viro2c6292a2011-06-17 09:05:48 -04003974 if (cifs_sb)
3975 cifs_sb->mnt_cifs_flags |=
3976 CIFS_MOUNT_POSIXACL;
Steve French8af18972007-02-14 04:42:51 +00003977 }
3978
Steve French75865f8c2007-06-24 18:30:48 +00003979 if (vol_info && vol_info->posix_paths == 0)
Steve French8af18972007-02-14 04:42:51 +00003980 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
Steve French75865f8c2007-06-24 18:30:48 +00003981 else if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003982 cifs_dbg(FYI, "negotiate posix pathnames\n");
Al Viro2c6292a2011-06-17 09:05:48 -04003983 if (cifs_sb)
3984 cifs_sb->mnt_cifs_flags |=
Steve French8af18972007-02-14 04:42:51 +00003985 CIFS_MOUNT_POSIX_PATHS;
3986 }
Steve French50c2f752007-07-13 00:33:32 +00003987
Joe Perchesf96637b2013-05-04 22:12:25 -05003988 cifs_dbg(FYI, "Negotiate caps 0x%x\n", (int)cap);
Steve French8af18972007-02-14 04:42:51 +00003989#ifdef CONFIG_CIFS_DEBUG2
Steve French75865f8c2007-06-24 18:30:48 +00003990 if (cap & CIFS_UNIX_FCNTL_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003991 cifs_dbg(FYI, "FCNTL cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003992 if (cap & CIFS_UNIX_EXTATTR_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003993 cifs_dbg(FYI, "EXTATTR cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003994 if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003995 cifs_dbg(FYI, "POSIX path cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003996 if (cap & CIFS_UNIX_XATTR_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003997 cifs_dbg(FYI, "XATTR cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00003998 if (cap & CIFS_UNIX_POSIX_ACL_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003999 cifs_dbg(FYI, "POSIX ACL cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00004000 if (cap & CIFS_UNIX_LARGE_READ_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004001 cifs_dbg(FYI, "very large read cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00004002 if (cap & CIFS_UNIX_LARGE_WRITE_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004003 cifs_dbg(FYI, "very large write cap\n");
Steve French6848b732011-05-26 18:38:54 +00004004 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004005 cifs_dbg(FYI, "transport encryption cap\n");
Steve French6848b732011-05-26 18:38:54 +00004006 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004007 cifs_dbg(FYI, "mandatory transport encryption cap\n");
Steve French8af18972007-02-14 04:42:51 +00004008#endif /* CIFS_DEBUG2 */
4009 if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
Steve French442aa312007-09-24 20:25:46 +00004010 if (vol_info == NULL) {
Joe Perchesf96637b2013-05-04 22:12:25 -05004011 cifs_dbg(FYI, "resetting capabilities failed\n");
Steve French442aa312007-09-24 20:25:46 +00004012 } else
Joe Perchesf96637b2013-05-04 22:12:25 -05004013 cifs_dbg(VFS, "Negotiating Unix capabilities with the server failed. Consider mounting with the Unix Extensions disabled if problems are found by specifying the nounix mount option.\n");
Steve French5a44b312007-09-20 15:16:24 +00004014
Steve French8af18972007-02-14 04:42:51 +00004015 }
4016 }
4017}
4018
Sachin Prabhu4214ebf2016-07-29 22:38:19 +01004019int cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004020 struct cifs_sb_info *cifs_sb)
Jeff Laytonb1c8d2b2008-10-22 13:57:07 -04004021{
Jeff Layton2de970f2010-10-06 19:51:12 -04004022 INIT_DELAYED_WORK(&cifs_sb->prune_tlinks, cifs_prune_tlinks);
4023
Al Viro2ced6f62011-06-17 09:20:04 -04004024 spin_lock_init(&cifs_sb->tlink_tree_lock);
4025 cifs_sb->tlink_tree = RB_ROOT;
4026
Steve Frenche8506d22019-02-28 21:32:15 -06004027 cifs_sb->bsize = pvolume_info->bsize;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04004028 /*
Jeff Layton5eba8ab2011-10-19 15:30:26 -04004029 * Temporarily set r/wsize for matching superblock. If we end up using
4030 * new sb then client will later negotiate it downward if needed.
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04004031 */
Jeff Layton5eba8ab2011-10-19 15:30:26 -04004032 cifs_sb->rsize = pvolume_info->rsize;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04004033 cifs_sb->wsize = pvolume_info->wsize;
4034
Steve French3b795212008-11-13 19:45:32 +00004035 cifs_sb->mnt_uid = pvolume_info->linux_uid;
4036 cifs_sb->mnt_gid = pvolume_info->linux_gid;
4037 cifs_sb->mnt_file_mode = pvolume_info->file_mode;
4038 cifs_sb->mnt_dir_mode = pvolume_info->dir_mode;
Joe Perchesf96637b2013-05-04 22:12:25 -05004039 cifs_dbg(FYI, "file mode: 0x%hx dir mode: 0x%hx\n",
4040 cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode);
Steve French3b795212008-11-13 19:45:32 +00004041
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05304042 cifs_sb->actimeo = pvolume_info->actimeo;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004043 cifs_sb->local_nls = pvolume_info->local_nls;
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05304044
Aurelien Aptel83930722018-09-20 18:10:25 -07004045 if (pvolume_info->nodfs)
4046 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_DFS;
Steve French3b795212008-11-13 19:45:32 +00004047 if (pvolume_info->noperm)
4048 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
4049 if (pvolume_info->setuids)
4050 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
Steve French95932652016-09-23 01:36:34 -05004051 if (pvolume_info->setuidfromacl)
4052 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UID_FROM_ACL;
Steve French3b795212008-11-13 19:45:32 +00004053 if (pvolume_info->server_ino)
4054 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
4055 if (pvolume_info->remap)
Steve French2baa2682014-09-27 02:19:01 -05004056 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SFM_CHR;
4057 if (pvolume_info->sfu_remap)
Steve French3b795212008-11-13 19:45:32 +00004058 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
4059 if (pvolume_info->no_xattr)
4060 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
4061 if (pvolume_info->sfu_emul)
4062 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
4063 if (pvolume_info->nobrl)
4064 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
Steve French3d4ef9a2018-04-25 22:19:09 -05004065 if (pvolume_info->nohandlecache)
4066 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_HANDLE_CACHE;
Steve Frenchbe652442009-02-23 15:21:59 +00004067 if (pvolume_info->nostrictsync)
Steve French4717bed2009-02-24 14:44:19 +00004068 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOSSYNC;
Steve French13a6e422008-12-02 17:24:33 +00004069 if (pvolume_info->mand_lock)
4070 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOPOSIXBRL;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00004071 if (pvolume_info->rwpidforward)
4072 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RWPIDFORWARD;
Steve French412094a2019-06-24 02:01:42 -05004073 if (pvolume_info->mode_ace)
4074 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MODE_FROM_SID;
Steve French3b795212008-11-13 19:45:32 +00004075 if (pvolume_info->cifs_acl)
4076 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01004077 if (pvolume_info->backupuid_specified) {
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05004078 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPUID;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01004079 cifs_sb->mnt_backupuid = pvolume_info->backupuid;
4080 }
4081 if (pvolume_info->backupgid_specified) {
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05004082 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPGID;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01004083 cifs_sb->mnt_backupgid = pvolume_info->backupgid;
4084 }
Steve French3b795212008-11-13 19:45:32 +00004085 if (pvolume_info->override_uid)
4086 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID;
4087 if (pvolume_info->override_gid)
4088 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;
4089 if (pvolume_info->dynperm)
4090 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM;
Suresh Jayaramanfa1df752010-07-05 18:13:36 +05304091 if (pvolume_info->fsc)
4092 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_FSCACHE;
Jeff Layton0eb8a132010-10-06 19:51:12 -04004093 if (pvolume_info->multiuser)
4094 cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_MULTIUSER |
4095 CIFS_MOUNT_NO_PERM);
Pavel Shilovskyd39454f2011-01-24 14:16:35 -05004096 if (pvolume_info->strict_io)
4097 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_STRICT_IO;
Steve French3b795212008-11-13 19:45:32 +00004098 if (pvolume_info->direct_io) {
Joe Perchesf96637b2013-05-04 22:12:25 -05004099 cifs_dbg(FYI, "mounting share using direct i/o\n");
Steve French3b795212008-11-13 19:45:32 +00004100 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
4101 }
Steve French83bbfa72019-08-27 23:58:54 -05004102 if (pvolume_info->cache_ro) {
4103 cifs_dbg(VFS, "mounting share with read only caching. Ensure that the share will not be modified while in use.\n");
4104 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RO_CACHE;
Steve French41e033f2019-08-30 02:12:41 -05004105 } else if (pvolume_info->cache_rw) {
4106 cifs_dbg(VFS, "mounting share in single client RW caching mode. Ensure that no other systems will be accessing the share.\n");
4107 cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_RO_CACHE |
4108 CIFS_MOUNT_RW_CACHE);
Steve French83bbfa72019-08-27 23:58:54 -05004109 }
Stefan Metzmacher736a33202010-07-30 14:56:00 +02004110 if (pvolume_info->mfsymlinks) {
4111 if (pvolume_info->sfu_emul) {
Steve Frenchdb8b6312014-09-22 05:13:55 -05004112 /*
4113 * Our SFU ("Services for Unix" emulation does not allow
4114 * creating symlinks but does allow reading existing SFU
4115 * symlinks (it does allow both creating and reading SFU
4116 * style mknod and FIFOs though). When "mfsymlinks" and
4117 * "sfu" are both enabled at the same time, it allows
4118 * reading both types of symlinks, but will only create
4119 * them with mfsymlinks format. This allows better
4120 * Apple compatibility (probably better for Samba too)
4121 * while still recognizing old Windows style symlinks.
4122 */
4123 cifs_dbg(VFS, "mount options mfsymlinks and sfu both enabled\n");
Stefan Metzmacher736a33202010-07-30 14:56:00 +02004124 }
Steve Frenchdb8b6312014-09-22 05:13:55 -05004125 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MF_SYMLINKS;
Stefan Metzmacher736a33202010-07-30 14:56:00 +02004126 }
Steve French3b795212008-11-13 19:45:32 +00004127
4128 if ((pvolume_info->cifs_acl) && (pvolume_info->dynperm))
Joe Perchesf96637b2013-05-04 22:12:25 -05004129 cifs_dbg(VFS, "mount option dynperm ignored if cifsacl mount option supported\n");
Sachin Prabhu4214ebf2016-07-29 22:38:19 +01004130
4131 if (pvolume_info->prepath) {
4132 cifs_sb->prepath = kstrdup(pvolume_info->prepath, GFP_KERNEL);
4133 if (cifs_sb->prepath == NULL)
4134 return -ENOMEM;
4135 }
4136
4137 return 0;
Jeff Laytonb1c8d2b2008-10-22 13:57:07 -04004138}
4139
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004140void
4141cifs_cleanup_volume_info_contents(struct smb_vol *volume_info)
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004142{
Sean Finneyb9468452011-04-11 13:19:32 +00004143 kfree(volume_info->username);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004144 kzfree(volume_info->password);
Jesper Juhl95c75452011-08-27 18:58:34 +02004145 kfree(volume_info->UNC);
Sean Finneyb9468452011-04-11 13:19:32 +00004146 kfree(volume_info->domainname);
4147 kfree(volume_info->iocharset);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004148 kfree(volume_info->prepath);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004149}
4150
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04004151void
4152cifs_cleanup_volume_info(struct smb_vol *volume_info)
4153{
4154 if (!volume_info)
4155 return;
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004156 cifs_cleanup_volume_info_contents(volume_info);
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04004157 kfree(volume_info);
4158}
4159
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004160/* Release all succeed connections */
4161static inline void mount_put_conns(struct cifs_sb_info *cifs_sb,
4162 unsigned int xid,
4163 struct TCP_Server_Info *server,
4164 struct cifs_ses *ses, struct cifs_tcon *tcon)
4165{
4166 int rc = 0;
4167
4168 if (tcon)
4169 cifs_put_tcon(tcon);
4170 else if (ses)
4171 cifs_put_smb_ses(ses);
4172 else if (server)
4173 cifs_put_tcp_session(server, 0);
4174 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_POSIX_PATHS;
4175 free_xid(xid);
4176}
4177
4178/* Get connections for tcp, ses and tcon */
4179static int mount_get_conns(struct smb_vol *vol, struct cifs_sb_info *cifs_sb,
4180 unsigned int *xid,
4181 struct TCP_Server_Info **nserver,
4182 struct cifs_ses **nses, struct cifs_tcon **ntcon)
4183{
4184 int rc = 0;
4185 struct TCP_Server_Info *server;
4186 struct cifs_ses *ses;
4187 struct cifs_tcon *tcon;
4188
4189 *nserver = NULL;
4190 *nses = NULL;
4191 *ntcon = NULL;
4192
4193 *xid = get_xid();
4194
4195 /* get a reference to a tcp session */
4196 server = cifs_get_tcp_session(vol);
4197 if (IS_ERR(server)) {
4198 rc = PTR_ERR(server);
4199 return rc;
4200 }
4201
4202 *nserver = server;
4203
4204 if ((vol->max_credits < 20) || (vol->max_credits > 60000))
4205 server->max_credits = SMB2_MAX_CREDITS_AVAILABLE;
4206 else
4207 server->max_credits = vol->max_credits;
4208
4209 /* get a reference to a SMB session */
4210 ses = cifs_get_smb_ses(server, vol);
4211 if (IS_ERR(ses)) {
4212 rc = PTR_ERR(ses);
4213 return rc;
4214 }
4215
4216 *nses = ses;
4217
4218 if ((vol->persistent == true) && (!(ses->server->capabilities &
4219 SMB2_GLOBAL_CAP_PERSISTENT_HANDLES))) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10004220 cifs_server_dbg(VFS, "persistent handles not supported by server\n");
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004221 return -EOPNOTSUPP;
4222 }
4223
4224 /* search for existing tcon to this server share */
4225 tcon = cifs_get_tcon(ses, vol);
4226 if (IS_ERR(tcon)) {
4227 rc = PTR_ERR(tcon);
4228 return rc;
4229 }
4230
4231 *ntcon = tcon;
4232
4233 /* if new SMB3.11 POSIX extensions are supported do not remap / and \ */
4234 if (tcon->posix_extensions)
4235 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS;
4236
4237 /* tell server which Unix caps we support */
4238 if (cap_unix(tcon->ses)) {
4239 /*
4240 * reset of caps checks mount to see if unix extensions disabled
4241 * for just this mount.
4242 */
4243 reset_cifs_unix_caps(*xid, tcon, cifs_sb, vol);
4244 if ((tcon->ses->server->tcpStatus == CifsNeedReconnect) &&
4245 (le64_to_cpu(tcon->fsUnixInfo.Capability) &
4246 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP))
4247 return -EACCES;
4248 } else
4249 tcon->unix_ext = 0; /* server does not support them */
4250
4251 /* do not care if a following call succeed - informational */
Steve French1981eba2019-08-29 22:33:38 -05004252 if (!tcon->pipe && server->ops->qfs_tcon) {
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004253 server->ops->qfs_tcon(*xid, tcon);
Steve French1981eba2019-08-29 22:33:38 -05004254 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RO_CACHE) {
4255 if (tcon->fsDevInfo.DeviceCharacteristics &
4256 FILE_READ_ONLY_DEVICE)
4257 cifs_dbg(VFS, "mounted to read only share\n");
Steve French41e033f2019-08-30 02:12:41 -05004258 else if ((cifs_sb->mnt_cifs_flags &
4259 CIFS_MOUNT_RW_CACHE) == 0)
Steve French1981eba2019-08-29 22:33:38 -05004260 cifs_dbg(VFS, "read only mount of RW share\n");
Steve French41e033f2019-08-30 02:12:41 -05004261 /* no need to log a RW mount of a typical RW share */
Steve French1981eba2019-08-29 22:33:38 -05004262 }
4263 }
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004264
4265 cifs_sb->wsize = server->ops->negotiate_wsize(tcon, vol);
4266 cifs_sb->rsize = server->ops->negotiate_rsize(tcon, vol);
4267
4268 return 0;
4269}
4270
4271static int mount_setup_tlink(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses,
4272 struct cifs_tcon *tcon)
4273{
4274 struct tcon_link *tlink;
4275
4276 /* hang the tcon off of the superblock */
4277 tlink = kzalloc(sizeof(*tlink), GFP_KERNEL);
4278 if (tlink == NULL)
4279 return -ENOMEM;
4280
4281 tlink->tl_uid = ses->linux_uid;
4282 tlink->tl_tcon = tcon;
4283 tlink->tl_time = jiffies;
4284 set_bit(TCON_LINK_MASTER, &tlink->tl_flags);
4285 set_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
4286
4287 cifs_sb->master_tlink = tlink;
4288 spin_lock(&cifs_sb->tlink_tree_lock);
4289 tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
4290 spin_unlock(&cifs_sb->tlink_tree_lock);
4291
4292 queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
4293 TLINK_IDLE_EXPIRE);
4294 return 0;
4295}
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04004296
Steve French2d6d5892009-04-09 00:36:44 +00004297#ifdef CONFIG_CIFS_DFS_UPCALL
Steve French6d3ea7e2012-11-28 22:34:41 -06004298/*
4299 * cifs_build_path_to_root returns full path to root when we do not have an
4300 * exiting connection (tcon)
4301 */
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004302static char *
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04004303build_unc_path_to_root(const struct smb_vol *vol,
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004304 const struct cifs_sb_info *cifs_sb, bool useppath)
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004305{
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04004306 char *full_path, *pos;
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004307 unsigned int pplen = useppath && vol->prepath ?
4308 strlen(vol->prepath) + 1 : 0;
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04004309 unsigned int unc_len = strnlen(vol->UNC, MAX_TREE_SIZE + 1);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004310
Ronnie Sahlberg340625e2019-08-27 09:30:14 +10004311 if (unc_len > MAX_TREE_SIZE)
4312 return ERR_PTR(-EINVAL);
4313
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04004314 full_path = kmalloc(unc_len + pplen + 1, GFP_KERNEL);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004315 if (full_path == NULL)
4316 return ERR_PTR(-ENOMEM);
4317
Ronnie Sahlberg340625e2019-08-27 09:30:14 +10004318 memcpy(full_path, vol->UNC, unc_len);
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04004319 pos = full_path + unc_len;
4320
4321 if (pplen) {
Jeff Layton1fc29ba2013-05-31 10:00:18 -04004322 *pos = CIFS_DIR_SEP(cifs_sb);
Ronnie Sahlberg340625e2019-08-27 09:30:14 +10004323 memcpy(pos + 1, vol->prepath, pplen);
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04004324 pos += pplen;
4325 }
4326
4327 *pos = '\0'; /* add trailing null */
Steve Frenchf87d39d2011-05-27 03:50:55 +00004328 convert_delimiter(full_path, CIFS_DIR_SEP(cifs_sb));
Joe Perchesf96637b2013-05-04 22:12:25 -05004329 cifs_dbg(FYI, "%s: full_path=%s\n", __func__, full_path);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004330 return full_path;
4331}
Sean Finneydd613942011-04-11 13:19:30 +00004332
Paulo Alcantara1c780222018-11-14 16:24:03 -02004333/**
4334 * expand_dfs_referral - Perform a dfs referral query and update the cifs_sb
4335 *
Sean Finneydd613942011-04-11 13:19:30 +00004336 *
Sean Finney046462a2011-04-11 13:19:33 +00004337 * If a referral is found, cifs_sb->mountdata will be (re-)allocated
4338 * to a string containing updated options for the submount. Otherwise it
4339 * will be left untouched.
Sean Finneydd613942011-04-11 13:19:30 +00004340 *
4341 * Returns the rc from get_dfs_path to the caller, which can be used to
4342 * determine whether there were referrals.
4343 */
4344static int
Pavel Shilovskyb669f332012-05-27 20:21:53 +04004345expand_dfs_referral(const unsigned int xid, struct cifs_ses *ses,
Sean Finneydd613942011-04-11 13:19:30 +00004346 struct smb_vol *volume_info, struct cifs_sb_info *cifs_sb,
Sean Finney046462a2011-04-11 13:19:33 +00004347 int check_prefix)
Sean Finneydd613942011-04-11 13:19:30 +00004348{
4349 int rc;
Paulo Alcantara1c780222018-11-14 16:24:03 -02004350 struct dfs_info3_param referral = {0};
Sean Finneydd613942011-04-11 13:19:30 +00004351 char *full_path = NULL, *ref_path = NULL, *mdata = NULL;
4352
Aurelien Aptel83930722018-09-20 18:10:25 -07004353 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS)
4354 return -EREMOTE;
4355
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004356 full_path = build_unc_path_to_root(volume_info, cifs_sb, true);
Sean Finneydd613942011-04-11 13:19:30 +00004357 if (IS_ERR(full_path))
4358 return PTR_ERR(full_path);
4359
4360 /* For DFS paths, skip the first '\' of the UNC */
4361 ref_path = check_prefix ? full_path + 1 : volume_info->UNC + 1;
4362
Paulo Alcantara1c780222018-11-14 16:24:03 -02004363 rc = dfs_cache_find(xid, ses, cifs_sb->local_nls, cifs_remap(cifs_sb),
4364 ref_path, &referral, NULL);
4365 if (!rc) {
Sean Finneydd613942011-04-11 13:19:30 +00004366 char *fake_devname = NULL;
4367
4368 mdata = cifs_compose_mount_options(cifs_sb->mountdata,
Paulo Alcantara1c780222018-11-14 16:24:03 -02004369 full_path + 1, &referral,
Sean Finneydd613942011-04-11 13:19:30 +00004370 &fake_devname);
Paulo Alcantara1c780222018-11-14 16:24:03 -02004371 free_dfs_info_param(&referral);
Sean Finney046462a2011-04-11 13:19:33 +00004372
Sean Finneydd613942011-04-11 13:19:30 +00004373 if (IS_ERR(mdata)) {
4374 rc = PTR_ERR(mdata);
4375 mdata = NULL;
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04004376 } else {
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004377 cifs_cleanup_volume_info_contents(volume_info);
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04004378 rc = cifs_setup_volume_info(volume_info, mdata,
Paulo Alcantara1c780222018-11-14 16:24:03 -02004379 fake_devname, false);
Sean Finneydd613942011-04-11 13:19:30 +00004380 }
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04004381 kfree(fake_devname);
4382 kfree(cifs_sb->mountdata);
Sean Finney046462a2011-04-11 13:19:33 +00004383 cifs_sb->mountdata = mdata;
Sean Finneydd613942011-04-11 13:19:30 +00004384 }
4385 kfree(full_path);
4386 return rc;
4387}
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004388
4389static inline int get_next_dfs_tgt(const char *path,
4390 struct dfs_cache_tgt_list *tgt_list,
4391 struct dfs_cache_tgt_iterator **tgt_it)
4392{
4393 if (!*tgt_it)
4394 *tgt_it = dfs_cache_get_tgt_iterator(tgt_list);
4395 else
4396 *tgt_it = dfs_cache_get_next_tgt(tgt_list, *tgt_it);
4397 return !*tgt_it ? -EHOSTDOWN : 0;
4398}
4399
4400static int update_vol_info(const struct dfs_cache_tgt_iterator *tgt_it,
4401 struct smb_vol *fake_vol, struct smb_vol *vol)
4402{
4403 const char *tgt = dfs_cache_get_tgt_name(tgt_it);
4404 int len = strlen(tgt) + 2;
4405 char *new_unc;
4406
4407 new_unc = kmalloc(len, GFP_KERNEL);
4408 if (!new_unc)
4409 return -ENOMEM;
Ronnie Sahlberg74ea5f92019-02-09 09:51:11 +10004410 scnprintf(new_unc, len, "\\%s", tgt);
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004411
4412 kfree(vol->UNC);
4413 vol->UNC = new_unc;
4414
4415 if (fake_vol->prepath) {
4416 kfree(vol->prepath);
4417 vol->prepath = fake_vol->prepath;
4418 fake_vol->prepath = NULL;
4419 }
4420 memcpy(&vol->dstaddr, &fake_vol->dstaddr, sizeof(vol->dstaddr));
4421
4422 return 0;
4423}
4424
4425static int setup_dfs_tgt_conn(const char *path,
4426 const struct dfs_cache_tgt_iterator *tgt_it,
4427 struct cifs_sb_info *cifs_sb,
4428 struct smb_vol *vol,
4429 unsigned int *xid,
4430 struct TCP_Server_Info **server,
4431 struct cifs_ses **ses,
4432 struct cifs_tcon **tcon)
4433{
4434 int rc;
4435 struct dfs_info3_param ref = {0};
4436 char *mdata = NULL, *fake_devname = NULL;
4437 struct smb_vol fake_vol = {0};
4438
4439 cifs_dbg(FYI, "%s: dfs path: %s\n", __func__, path);
4440
4441 rc = dfs_cache_get_tgt_referral(path, tgt_it, &ref);
4442 if (rc)
4443 return rc;
4444
4445 mdata = cifs_compose_mount_options(cifs_sb->mountdata, path, &ref,
4446 &fake_devname);
4447 free_dfs_info_param(&ref);
4448
4449 if (IS_ERR(mdata)) {
4450 rc = PTR_ERR(mdata);
4451 mdata = NULL;
4452 } else {
4453 cifs_dbg(FYI, "%s: fake_devname: %s\n", __func__, fake_devname);
4454 rc = cifs_setup_volume_info(&fake_vol, mdata, fake_devname,
4455 false);
4456 }
4457 kfree(mdata);
4458 kfree(fake_devname);
4459
4460 if (!rc) {
4461 /*
4462 * We use a 'fake_vol' here because we need pass it down to the
4463 * mount_{get,put} functions to test connection against new DFS
4464 * targets.
4465 */
4466 mount_put_conns(cifs_sb, *xid, *server, *ses, *tcon);
4467 rc = mount_get_conns(&fake_vol, cifs_sb, xid, server, ses,
4468 tcon);
4469 if (!rc) {
4470 /*
4471 * We were able to connect to new target server.
4472 * Update current volume info with new target server.
4473 */
4474 rc = update_vol_info(tgt_it, &fake_vol, vol);
4475 }
4476 }
4477 cifs_cleanup_volume_info_contents(&fake_vol);
4478 return rc;
4479}
4480
4481static int mount_do_dfs_failover(const char *path,
4482 struct cifs_sb_info *cifs_sb,
4483 struct smb_vol *vol,
4484 struct cifs_ses *root_ses,
4485 unsigned int *xid,
4486 struct TCP_Server_Info **server,
4487 struct cifs_ses **ses,
4488 struct cifs_tcon **tcon)
4489{
4490 int rc;
4491 struct dfs_cache_tgt_list tgt_list;
4492 struct dfs_cache_tgt_iterator *tgt_it = NULL;
4493
4494 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS)
4495 return -EOPNOTSUPP;
4496
4497 rc = dfs_cache_noreq_find(path, NULL, &tgt_list);
4498 if (rc)
4499 return rc;
4500
4501 for (;;) {
4502 /* Get next DFS target server - if any */
4503 rc = get_next_dfs_tgt(path, &tgt_list, &tgt_it);
4504 if (rc)
4505 break;
4506 /* Connect to next DFS target */
4507 rc = setup_dfs_tgt_conn(path, tgt_it, cifs_sb, vol, xid, server,
4508 ses, tcon);
4509 if (!rc || rc == -EACCES || rc == -EOPNOTSUPP)
4510 break;
4511 }
4512 if (!rc) {
4513 /*
4514 * Update DFS target hint in DFS referral cache with the target
4515 * server we successfully reconnected to.
4516 */
4517 rc = dfs_cache_update_tgthint(*xid, root_ses ? root_ses : *ses,
4518 cifs_sb->local_nls,
4519 cifs_remap(cifs_sb), path,
4520 tgt_it);
4521 }
4522 dfs_cache_free_tgts(&tgt_list);
4523 return rc;
4524}
Steve French2d6d5892009-04-09 00:36:44 +00004525#endif
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004526
Paulo Alcantara (SUSE)50720102019-03-19 16:54:29 -03004527int
Jeff Layton04db79b2011-07-06 08:10:38 -04004528cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
Steve Frenchc7c137b2018-06-06 17:59:29 -05004529 const char *devname, bool is_smb3)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004530{
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004531 int rc = 0;
Sean Finneydd613942011-04-11 13:19:30 +00004532
Steve Frenchc7c137b2018-06-06 17:59:29 -05004533 if (cifs_parse_mount_options(mount_data, devname, volume_info, is_smb3))
Jeff Layton04db79b2011-07-06 08:10:38 -04004534 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004535
Jeff Layton7586b762008-12-01 18:41:49 -05004536 if (volume_info->nullauth) {
Joe Perchesf96637b2013-05-04 22:12:25 -05004537 cifs_dbg(FYI, "Anonymous login\n");
Jeff Layton04febab2012-01-17 16:09:15 -05004538 kfree(volume_info->username);
4539 volume_info->username = NULL;
Jeff Layton7586b762008-12-01 18:41:49 -05004540 } else if (volume_info->username) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004541 /* BB fixme parse for domain name here */
Joe Perchesf96637b2013-05-04 22:12:25 -05004542 cifs_dbg(FYI, "Username: %s\n", volume_info->username);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004543 } else {
Joe Perchesf96637b2013-05-04 22:12:25 -05004544 cifs_dbg(VFS, "No username specified\n");
Steve French50c2f752007-07-13 00:33:32 +00004545 /* In userspace mount helper we can get user name from alternate
4546 locations such as env variables and files on disk */
Jeff Layton04db79b2011-07-06 08:10:38 -04004547 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004548 }
4549
Linus Torvalds1da177e2005-04-16 15:20:36 -07004550 /* this is needed for ASCII cp to Unicode converts */
Jeff Layton7586b762008-12-01 18:41:49 -05004551 if (volume_info->iocharset == NULL) {
Jeff Laytona5fc4ce2010-04-24 07:57:42 -04004552 /* load_nls_default cannot return null */
4553 volume_info->local_nls = load_nls_default();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004554 } else {
Jeff Laytona5fc4ce2010-04-24 07:57:42 -04004555 volume_info->local_nls = load_nls(volume_info->iocharset);
4556 if (volume_info->local_nls == NULL) {
Joe Perchesf96637b2013-05-04 22:12:25 -05004557 cifs_dbg(VFS, "CIFS mount error: iocharset %s not found\n",
Joe Perchesb6b38f72010-04-21 03:50:45 +00004558 volume_info->iocharset);
Jeff Layton04db79b2011-07-06 08:10:38 -04004559 return -ELIBACC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004560 }
4561 }
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004562
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004563 return rc;
Jeff Layton04db79b2011-07-06 08:10:38 -04004564}
4565
4566struct smb_vol *
Steve Frenchc7c137b2018-06-06 17:59:29 -05004567cifs_get_volume_info(char *mount_data, const char *devname, bool is_smb3)
Jeff Layton04db79b2011-07-06 08:10:38 -04004568{
4569 int rc;
4570 struct smb_vol *volume_info;
4571
Jeff Layton6ee95422012-11-26 11:09:57 -05004572 volume_info = kmalloc(sizeof(struct smb_vol), GFP_KERNEL);
Jeff Layton04db79b2011-07-06 08:10:38 -04004573 if (!volume_info)
4574 return ERR_PTR(-ENOMEM);
4575
Steve Frenchc7c137b2018-06-06 17:59:29 -05004576 rc = cifs_setup_volume_info(volume_info, mount_data, devname, is_smb3);
Jeff Layton04db79b2011-07-06 08:10:38 -04004577 if (rc) {
4578 cifs_cleanup_volume_info(volume_info);
4579 volume_info = ERR_PTR(rc);
4580 }
4581
4582 return volume_info;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004583}
4584
Aurelien Aptela6b50582016-05-25 19:59:09 +02004585static int
4586cifs_are_all_path_components_accessible(struct TCP_Server_Info *server,
4587 unsigned int xid,
4588 struct cifs_tcon *tcon,
4589 struct cifs_sb_info *cifs_sb,
Ronnie Sahlbergce465bf2019-07-11 13:46:58 +10004590 char *full_path,
4591 int added_treename)
Aurelien Aptela6b50582016-05-25 19:59:09 +02004592{
4593 int rc;
4594 char *s;
4595 char sep, tmp;
Ronnie Sahlbergce465bf2019-07-11 13:46:58 +10004596 int skip = added_treename ? 1 : 0;
Aurelien Aptela6b50582016-05-25 19:59:09 +02004597
4598 sep = CIFS_DIR_SEP(cifs_sb);
4599 s = full_path;
4600
4601 rc = server->ops->is_path_accessible(xid, tcon, cifs_sb, "");
4602 while (rc == 0) {
4603 /* skip separators */
4604 while (*s == sep)
4605 s++;
4606 if (!*s)
4607 break;
4608 /* next separator */
4609 while (*s && *s != sep)
4610 s++;
Ronnie Sahlbergce465bf2019-07-11 13:46:58 +10004611 /*
4612 * if the treename is added, we then have to skip the first
4613 * part within the separators
4614 */
4615 if (skip) {
4616 skip = 0;
4617 continue;
4618 }
Aurelien Aptela6b50582016-05-25 19:59:09 +02004619 /*
4620 * temporarily null-terminate the path at the end of
4621 * the current component
4622 */
4623 tmp = *s;
4624 *s = 0;
4625 rc = server->ops->is_path_accessible(xid, tcon, cifs_sb,
4626 full_path);
4627 *s = tmp;
4628 }
4629 return rc;
4630}
4631
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004632/*
4633 * Check if path is remote (e.g. a DFS share). Return -EREMOTE if it is,
4634 * otherwise 0.
4635 */
4636static int is_path_remote(struct cifs_sb_info *cifs_sb, struct smb_vol *vol,
4637 const unsigned int xid,
4638 struct TCP_Server_Info *server,
4639 struct cifs_tcon *tcon)
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004640{
Jeff Layton1daaae82012-03-21 06:30:40 -04004641 int rc;
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004642 char *full_path;
4643
4644 if (!server->ops->is_path_accessible)
4645 return -EOPNOTSUPP;
4646
4647 /*
4648 * cifs_build_path_to_root works only when we have a valid tcon
4649 */
4650 full_path = cifs_build_path_to_root(vol, cifs_sb, tcon,
4651 tcon->Flags & SMB_SHARE_IS_IN_DFS);
4652 if (full_path == NULL)
4653 return -ENOMEM;
4654
4655 cifs_dbg(FYI, "%s: full_path: %s\n", __func__, full_path);
4656
4657 rc = server->ops->is_path_accessible(xid, tcon, cifs_sb,
4658 full_path);
4659 if (rc != 0 && rc != -EREMOTE) {
4660 kfree(full_path);
4661 return rc;
4662 }
4663
4664 if (rc != -EREMOTE) {
4665 rc = cifs_are_all_path_components_accessible(server, xid, tcon,
Ronnie Sahlbergce465bf2019-07-11 13:46:58 +10004666 cifs_sb, full_path, tcon->Flags & SMB_SHARE_IS_IN_DFS);
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004667 if (rc != 0) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10004668 cifs_server_dbg(VFS, "cannot query dirs between root and final path, "
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004669 "enabling CIFS_MOUNT_USE_PREFIX_PATH\n");
4670 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
4671 rc = 0;
4672 }
4673 }
4674
4675 kfree(full_path);
4676 return rc;
4677}
4678
4679#ifdef CONFIG_CIFS_DFS_UPCALL
4680int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *vol)
4681{
4682 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04004683 unsigned int xid;
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04004684 struct cifs_ses *ses;
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004685 struct cifs_tcon *root_tcon = NULL;
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004686 struct cifs_tcon *tcon = NULL;
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04004687 struct TCP_Server_Info *server;
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004688 char *root_path = NULL, *full_path = NULL;
Paulo Alcantara (SUSE)50720102019-03-19 16:54:29 -03004689 char *old_mountdata, *origin_mountdata = NULL;
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004690 int count;
Al Virodd854462011-06-17 08:24:42 -04004691
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004692 rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses, &tcon);
4693 if (!rc && tcon) {
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004694 /* If not a standalone DFS root, then check if path is remote */
4695 rc = dfs_cache_find(xid, ses, cifs_sb->local_nls,
4696 cifs_remap(cifs_sb), vol->UNC + 1, NULL,
4697 NULL);
4698 if (rc) {
4699 rc = is_path_remote(cifs_sb, vol, xid, server, tcon);
4700 if (!rc)
4701 goto out;
4702 if (rc != -EREMOTE)
4703 goto error;
4704 }
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004705 }
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004706 /*
4707 * If first DFS target server went offline and we failed to connect it,
4708 * server and ses pointers are NULL at this point, though we still have
4709 * chance to get a cached DFS referral in expand_dfs_referral() and
4710 * retry next target available in it.
4711 *
4712 * If a NULL ses ptr is passed to dfs_cache_find(), a lookup will be
4713 * performed against DFS path and *no* requests will be sent to server
4714 * for any new DFS referrals. Hence it's safe to skip checking whether
4715 * server or ses ptr is NULL.
4716 */
4717 if (rc == -EACCES || rc == -EOPNOTSUPP)
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004718 goto error;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004719
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004720 root_path = build_unc_path_to_root(vol, cifs_sb, false);
4721 if (IS_ERR(root_path)) {
4722 rc = PTR_ERR(root_path);
4723 root_path = NULL;
4724 goto error;
4725 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004726
Paulo Alcantara93d5cb52018-11-14 17:13:25 -02004727 full_path = build_unc_path_to_root(vol, cifs_sb, true);
4728 if (IS_ERR(full_path)) {
4729 rc = PTR_ERR(full_path);
4730 full_path = NULL;
4731 goto error;
4732 }
Sean Finneyc1508ca2011-04-11 13:19:31 +00004733 /*
4734 * Perform an unconditional check for whether there are DFS
4735 * referrals for this path without prefix, to provide support
4736 * for DFS referrals from w2k8 servers which don't seem to respond
4737 * with PATH_NOT_COVERED to requests that include the prefix.
4738 * Chase the referral if found, otherwise continue normally.
4739 */
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004740 old_mountdata = cifs_sb->mountdata;
4741 (void)expand_dfs_referral(xid, ses, vol, cifs_sb, false);
Sean Finneyc1508ca2011-04-11 13:19:31 +00004742
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004743 if (cifs_sb->mountdata == NULL) {
4744 rc = -ENOENT;
4745 goto error;
4746 }
4747
Paulo Alcantara (SUSE)50720102019-03-19 16:54:29 -03004748 /* Save DFS root volume information for DFS refresh worker */
4749 origin_mountdata = kstrndup(cifs_sb->mountdata,
4750 strlen(cifs_sb->mountdata), GFP_KERNEL);
4751 if (!origin_mountdata) {
4752 rc = -ENOMEM;
4753 goto error;
4754 }
4755
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004756 if (cifs_sb->mountdata != old_mountdata) {
4757 /* If we were redirected, reconnect to new target server */
4758 mount_put_conns(cifs_sb, xid, server, ses, tcon);
4759 rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses, &tcon);
4760 }
4761 if (rc) {
4762 if (rc == -EACCES || rc == -EOPNOTSUPP)
4763 goto error;
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004764 /* Perform DFS failover to any other DFS targets */
4765 rc = mount_do_dfs_failover(root_path + 1, cifs_sb, vol, NULL,
4766 &xid, &server, &ses, &tcon);
4767 if (rc)
4768 goto error;
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004769 }
4770
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004771 kfree(root_path);
4772 root_path = build_unc_path_to_root(vol, cifs_sb, false);
4773 if (IS_ERR(root_path)) {
4774 rc = PTR_ERR(root_path);
4775 root_path = NULL;
4776 goto error;
4777 }
4778 /* Cache out resolved root server */
4779 (void)dfs_cache_find(xid, ses, cifs_sb->local_nls, cifs_remap(cifs_sb),
4780 root_path + 1, NULL, NULL);
4781 /*
4782 * Save root tcon for additional DFS requests to update or create a new
4783 * DFS cache entry, or even perform DFS failover.
4784 */
4785 spin_lock(&cifs_tcp_ses_lock);
4786 tcon->tc_count++;
4787 tcon->dfs_path = root_path;
4788 root_path = NULL;
4789 tcon->remap = cifs_remap(cifs_sb);
4790 spin_unlock(&cifs_tcp_ses_lock);
4791
4792 root_tcon = tcon;
4793
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004794 for (count = 1; ;) {
4795 if (!rc && tcon) {
4796 rc = is_path_remote(cifs_sb, vol, xid, server, tcon);
4797 if (!rc || rc != -EREMOTE)
4798 break;
Pavel Shilovsky68889f22012-05-25 14:40:22 +04004799 }
Steve French6d3ea7e2012-11-28 22:34:41 -06004800 /*
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004801 * BB: when we implement proper loop detection,
4802 * we will remove this check. But now we need it
4803 * to prevent an indefinite loop if 'DFS tree' is
4804 * misconfigured (i.e. has loops).
Steve French6d3ea7e2012-11-28 22:34:41 -06004805 */
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004806 if (count++ > MAX_NESTED_LINKS) {
Igor Mammedov5c2503a2009-04-21 19:31:05 +04004807 rc = -ELOOP;
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004808 break;
Igor Mammedov5c2503a2009-04-21 19:31:05 +04004809 }
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004810
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004811 kfree(full_path);
4812 full_path = build_unc_path_to_root(vol, cifs_sb, true);
4813 if (IS_ERR(full_path)) {
4814 rc = PTR_ERR(full_path);
4815 full_path = NULL;
4816 break;
4817 }
4818
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004819 old_mountdata = cifs_sb->mountdata;
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004820 rc = expand_dfs_referral(xid, root_tcon->ses, vol, cifs_sb,
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004821 true);
4822 if (rc)
4823 break;
Jeff Layton7b91e262009-07-23 15:22:30 -04004824
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004825 if (cifs_sb->mountdata != old_mountdata) {
4826 mount_put_conns(cifs_sb, xid, server, ses, tcon);
4827 rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses,
4828 &tcon);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004829 }
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004830 if (rc) {
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004831 if (rc == -EACCES || rc == -EOPNOTSUPP)
4832 break;
4833 /* Perform DFS failover to any other DFS targets */
4834 rc = mount_do_dfs_failover(full_path + 1, cifs_sb, vol,
4835 root_tcon->ses, &xid,
4836 &server, &ses, &tcon);
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004837 if (rc == -EACCES || rc == -EOPNOTSUPP || !server ||
4838 !ses)
4839 goto error;
4840 }
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004841 }
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004842 cifs_put_tcon(root_tcon);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004843
Jeff Layton9d002df2010-10-06 19:51:11 -04004844 if (rc)
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004845 goto error;
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004846
Paulo Alcantara93d5cb52018-11-14 17:13:25 -02004847 spin_lock(&cifs_tcp_ses_lock);
4848 if (!tcon->dfs_path) {
4849 /* Save full path in new tcon to do failover when reconnecting tcons */
4850 tcon->dfs_path = full_path;
4851 full_path = NULL;
4852 tcon->remap = cifs_remap(cifs_sb);
4853 }
4854 cifs_sb->origin_fullpath = kstrndup(tcon->dfs_path,
YueHaibing2f0a6172018-12-18 01:34:39 +00004855 strlen(tcon->dfs_path),
4856 GFP_ATOMIC);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -02004857 if (!cifs_sb->origin_fullpath) {
4858 spin_unlock(&cifs_tcp_ses_lock);
4859 rc = -ENOMEM;
4860 goto error;
4861 }
4862 spin_unlock(&cifs_tcp_ses_lock);
4863
Paulo Alcantara (SUSE)50720102019-03-19 16:54:29 -03004864 rc = dfs_cache_add_vol(origin_mountdata, vol, cifs_sb->origin_fullpath);
Paulo Alcantarae511d312018-11-14 17:16:44 -02004865 if (rc) {
4866 kfree(cifs_sb->origin_fullpath);
4867 goto error;
4868 }
Aurelien Aptel5fc7fcd2018-11-16 16:13:25 +01004869 /*
4870 * After reconnecting to a different server, unique ids won't
4871 * match anymore, so we disable serverino. This prevents
4872 * dentry revalidation to think the dentry are stale (ESTALE).
4873 */
4874 cifs_autodisable_serverino(cifs_sb);
Jeff Layton70fe7dc2007-11-16 22:21:07 +00004875out:
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04004876 free_xid(xid);
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004877 return mount_setup_tlink(cifs_sb, ses, tcon);
4878
4879error:
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004880 kfree(full_path);
4881 kfree(root_path);
Paulo Alcantara (SUSE)50720102019-03-19 16:54:29 -03004882 kfree(origin_mountdata);
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004883 mount_put_conns(cifs_sb, xid, server, ses, tcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004884 return rc;
4885}
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004886#else
4887int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *vol)
4888{
4889 int rc = 0;
4890 unsigned int xid;
4891 struct cifs_ses *ses;
4892 struct cifs_tcon *tcon;
4893 struct TCP_Server_Info *server;
4894
4895 rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses, &tcon);
4896 if (rc)
4897 goto error;
4898
4899 if (tcon) {
4900 rc = is_path_remote(cifs_sb, vol, xid, server, tcon);
4901 if (rc == -EREMOTE)
4902 rc = -EOPNOTSUPP;
4903 if (rc)
4904 goto error;
4905 }
4906
4907 free_xid(xid);
4908
4909 return mount_setup_tlink(cifs_sb, ses, tcon);
4910
4911error:
4912 mount_put_conns(cifs_sb, xid, server, ses, tcon);
4913 return rc;
4914}
4915#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07004916
Jeff Layton8d1bca32011-06-11 21:17:10 -04004917/*
Aurelien Aptelb327a712018-01-24 13:46:10 +01004918 * Issue a TREE_CONNECT request.
Jeff Layton8d1bca32011-06-11 21:17:10 -04004919 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004920int
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04004921CIFSTCon(const unsigned int xid, struct cifs_ses *ses,
Steve French96daf2b2011-05-27 04:34:02 +00004922 const char *tree, struct cifs_tcon *tcon,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004923 const struct nls_table *nls_codepage)
4924{
4925 struct smb_hdr *smb_buffer;
4926 struct smb_hdr *smb_buffer_response;
4927 TCONX_REQ *pSMB;
4928 TCONX_RSP *pSMBr;
4929 unsigned char *bcc_ptr;
4930 int rc = 0;
Jeff Layton690c5222011-01-20 13:36:51 -05004931 int length;
4932 __u16 bytes_left, count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004933
4934 if (ses == NULL)
4935 return -EIO;
4936
4937 smb_buffer = cifs_buf_get();
Steve Frenchca43e3b2009-09-01 17:20:50 +00004938 if (smb_buffer == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004939 return -ENOMEM;
Steve Frenchca43e3b2009-09-01 17:20:50 +00004940
Linus Torvalds1da177e2005-04-16 15:20:36 -07004941 smb_buffer_response = smb_buffer;
4942
4943 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
4944 NULL /*no tid */ , 4 /*wct */ );
Steve French1982c342005-08-17 12:38:22 -07004945
Pavel Shilovsky88257362012-05-23 14:01:59 +04004946 smb_buffer->Mid = get_next_mid(ses->server);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004947 smb_buffer->Uid = ses->Suid;
4948 pSMB = (TCONX_REQ *) smb_buffer;
4949 pSMBr = (TCONX_RSP *) smb_buffer_response;
4950
4951 pSMB->AndXCommand = 0xFF;
4952 pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004953 bcc_ptr = &pSMB->Password[0];
Aurelien Aptelb327a712018-01-24 13:46:10 +01004954 if (tcon->pipe || (ses->server->sec_mode & SECMODE_USER)) {
Steve Frencheeac8042006-01-13 21:34:58 -08004955 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
Steve French7c7b25b2006-06-01 19:20:10 +00004956 *bcc_ptr = 0; /* password is null byte */
Steve Frencheeac8042006-01-13 21:34:58 -08004957 bcc_ptr++; /* skip password */
Steve French7c7b25b2006-06-01 19:20:10 +00004958 /* already aligned so no need to do it below */
Steve Frencheeac8042006-01-13 21:34:58 -08004959 } else {
Shirish Pargaonkar540b2e32011-01-18 22:33:54 -06004960 pSMB->PasswordLength = cpu_to_le16(CIFS_AUTH_RESP_SIZE);
Steve Frencheeac8042006-01-13 21:34:58 -08004961 /* BB FIXME add code to fail this if NTLMv2 or Kerberos
4962 specified as required (when that support is added to
4963 the vfs in the future) as only NTLM or the much
Steve French7c7b25b2006-06-01 19:20:10 +00004964 weaker LANMAN (which we do not send by default) is accepted
Steve Frencheeac8042006-01-13 21:34:58 -08004965 by Samba (not sure whether other servers allow
4966 NTLMv2 password here) */
Steve French7c7b25b2006-06-01 19:20:10 +00004967#ifdef CONFIG_CIFS_WEAK_PW_HASH
Jeff Layton04912d62010-04-24 07:57:45 -04004968 if ((global_secflags & CIFSSEC_MAY_LANMAN) &&
Jeff Layton3f618222013-06-12 19:52:14 -05004969 (ses->sectype == LANMAN))
Shirish Pargaonkard3ba50b2010-10-27 15:20:36 -05004970 calc_lanman_hash(tcon->password, ses->server->cryptkey,
Steve French96daf2b2011-05-27 04:34:02 +00004971 ses->server->sec_mode &
Jeff Layton4e53a3f2008-12-05 20:41:21 -05004972 SECMODE_PW_ENCRYPT ? true : false,
4973 bcc_ptr);
Steve French7c7b25b2006-06-01 19:20:10 +00004974 else
4975#endif /* CIFS_WEAK_PW_HASH */
Shirish Pargaonkaree2c9252011-01-27 09:58:04 -06004976 rc = SMBNTencrypt(tcon->password, ses->server->cryptkey,
Shirish Pargaonkar9ef59922011-10-20 13:21:59 -05004977 bcc_ptr, nls_codepage);
Steve Frenchf3a31a22015-03-26 19:23:20 -05004978 if (rc) {
4979 cifs_dbg(FYI, "%s Can't generate NTLM rsp. Error: %d\n",
4980 __func__, rc);
4981 cifs_buf_release(smb_buffer);
4982 return rc;
4983 }
Steve Frencheeac8042006-01-13 21:34:58 -08004984
Shirish Pargaonkar540b2e32011-01-18 22:33:54 -06004985 bcc_ptr += CIFS_AUTH_RESP_SIZE;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00004986 if (ses->capabilities & CAP_UNICODE) {
Steve French7c7b25b2006-06-01 19:20:10 +00004987 /* must align unicode strings */
4988 *bcc_ptr = 0; /* null byte password */
4989 bcc_ptr++;
4990 }
Steve Frencheeac8042006-01-13 21:34:58 -08004991 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004992
Jeff Layton38d77c52013-05-26 07:01:00 -04004993 if (ses->server->sign)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004994 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
4995
4996 if (ses->capabilities & CAP_STATUS32) {
4997 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
4998 }
4999 if (ses->capabilities & CAP_DFS) {
5000 smb_buffer->Flags2 |= SMBFLG2_DFS;
5001 }
5002 if (ses->capabilities & CAP_UNICODE) {
5003 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
5004 length =
Steve Frenchacbbb762012-01-18 22:32:33 -06005005 cifs_strtoUTF16((__le16 *) bcc_ptr, tree,
Steve French50c2f752007-07-13 00:33:32 +00005006 6 /* max utf8 char length in bytes */ *
Steve Frencha878fb22006-05-30 18:04:19 +00005007 (/* server len*/ + 256 /* share len */), nls_codepage);
5008 bcc_ptr += 2 * length; /* convert num 16 bit words to bytes */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005009 bcc_ptr += 2; /* skip trailing null */
5010 } else { /* ASCII */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005011 strcpy(bcc_ptr, tree);
5012 bcc_ptr += strlen(tree) + 1;
5013 }
5014 strcpy(bcc_ptr, "?????");
5015 bcc_ptr += strlen("?????");
5016 bcc_ptr += 1;
5017 count = bcc_ptr - &pSMB->Password[0];
Steve Frenchbe8e3b02011-04-29 05:40:20 +00005018 pSMB->hdr.smb_buf_length = cpu_to_be32(be32_to_cpu(
5019 pSMB->hdr.smb_buf_length) + count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005020 pSMB->ByteCount = cpu_to_le16(count);
5021
Steve French133672e2007-11-13 22:41:37 +00005022 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length,
Jeff Layton77499812011-01-11 07:24:23 -05005023 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005024
Linus Torvalds1da177e2005-04-16 15:20:36 -07005025 /* above now done in SendReceive */
Aurelien Aptelb327a712018-01-24 13:46:10 +01005026 if (rc == 0) {
Steve French0e0d2cf2009-05-01 05:27:32 +00005027 bool is_unicode;
5028
Linus Torvalds1da177e2005-04-16 15:20:36 -07005029 tcon->tidStatus = CifsGood;
Steve French3b795212008-11-13 19:45:32 +00005030 tcon->need_reconnect = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005031 tcon->tid = smb_buffer_response->Tid;
5032 bcc_ptr = pByteArea(smb_buffer_response);
Jeff Layton690c5222011-01-20 13:36:51 -05005033 bytes_left = get_bcc(smb_buffer_response);
Jeff Laytoncc20c032009-04-30 07:16:21 -04005034 length = strnlen(bcc_ptr, bytes_left - 2);
Steve French0e0d2cf2009-05-01 05:27:32 +00005035 if (smb_buffer->Flags2 & SMBFLG2_UNICODE)
5036 is_unicode = true;
5037 else
5038 is_unicode = false;
5039
Jeff Laytoncc20c032009-04-30 07:16:21 -04005040
Steve French50c2f752007-07-13 00:33:32 +00005041 /* skip service field (NB: this field is always ASCII) */
Steve French7f8ed422007-09-28 22:28:55 +00005042 if (length == 3) {
5043 if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') &&
5044 (bcc_ptr[2] == 'C')) {
Joe Perchesf96637b2013-05-04 22:12:25 -05005045 cifs_dbg(FYI, "IPC connection\n");
Aurelien Aptelb327a712018-01-24 13:46:10 +01005046 tcon->ipc = true;
5047 tcon->pipe = true;
Steve French7f8ed422007-09-28 22:28:55 +00005048 }
5049 } else if (length == 2) {
5050 if ((bcc_ptr[0] == 'A') && (bcc_ptr[1] == ':')) {
5051 /* the most common case */
Joe Perchesf96637b2013-05-04 22:12:25 -05005052 cifs_dbg(FYI, "disk share connection\n");
Steve French7f8ed422007-09-28 22:28:55 +00005053 }
5054 }
Steve French50c2f752007-07-13 00:33:32 +00005055 bcc_ptr += length + 1;
Jeff Laytoncc20c032009-04-30 07:16:21 -04005056 bytes_left -= (length + 1);
Zhao Hongjiang46b51d02013-06-24 01:57:47 -05005057 strlcpy(tcon->treeName, tree, sizeof(tcon->treeName));
Jeff Laytoncc20c032009-04-30 07:16:21 -04005058
5059 /* mostly informational -- no need to fail on error here */
Jeff Layton90a98b22009-07-20 13:40:52 -04005060 kfree(tcon->nativeFileSystem);
Steve Frenchacbbb762012-01-18 22:32:33 -06005061 tcon->nativeFileSystem = cifs_strndup_from_utf16(bcc_ptr,
Steve French0e0d2cf2009-05-01 05:27:32 +00005062 bytes_left, is_unicode,
Jeff Laytoncc20c032009-04-30 07:16:21 -04005063 nls_codepage);
5064
Joe Perchesf96637b2013-05-04 22:12:25 -05005065 cifs_dbg(FYI, "nativeFileSystem=%s\n", tcon->nativeFileSystem);
Jeff Laytoncc20c032009-04-30 07:16:21 -04005066
Steve Frenchfb8c4b12007-07-10 01:16:18 +00005067 if ((smb_buffer_response->WordCount == 3) ||
Steve French1a4e15a2006-10-12 21:33:51 +00005068 (smb_buffer_response->WordCount == 7))
5069 /* field is in same location */
Steve French39798772006-05-31 22:40:51 +00005070 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
5071 else
5072 tcon->Flags = 0;
Joe Perchesf96637b2013-05-04 22:12:25 -05005073 cifs_dbg(FYI, "Tcon flags: 0x%x\n", tcon->Flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005074 }
5075
Mariusz Kozlowskia8a11d32007-10-03 16:41:24 +00005076 cifs_buf_release(smb_buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005077 return rc;
5078}
5079
Al Viro2e32cf52013-10-03 12:53:37 -04005080static void delayed_free(struct rcu_head *p)
5081{
5082 struct cifs_sb_info *sbi = container_of(p, struct cifs_sb_info, rcu);
5083 unload_nls(sbi->local_nls);
5084 kfree(sbi);
5085}
5086
Al Viro2a9b9952011-06-17 09:27:16 -04005087void
5088cifs_umount(struct cifs_sb_info *cifs_sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005089{
Jeff Laytonb647c352010-10-28 11:16:44 -04005090 struct rb_root *root = &cifs_sb->tlink_tree;
5091 struct rb_node *node;
5092 struct tcon_link *tlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005093
Jeff Layton2de970f2010-10-06 19:51:12 -04005094 cancel_delayed_work_sync(&cifs_sb->prune_tlinks);
5095
Jeff Laytonb647c352010-10-28 11:16:44 -04005096 spin_lock(&cifs_sb->tlink_tree_lock);
5097 while ((node = rb_first(root))) {
5098 tlink = rb_entry(node, struct tcon_link, tl_rbnode);
5099 cifs_get_tlink(tlink);
5100 clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
5101 rb_erase(node, root);
Steve French50c2f752007-07-13 00:33:32 +00005102
Jeff Laytonb647c352010-10-28 11:16:44 -04005103 spin_unlock(&cifs_sb->tlink_tree_lock);
5104 cifs_put_tlink(tlink);
5105 spin_lock(&cifs_sb->tlink_tree_lock);
5106 }
5107 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04005108
Al Virod757d712011-06-17 09:42:43 -04005109 kfree(cifs_sb->mountdata);
Aurelien Aptela6b50582016-05-25 19:59:09 +02005110 kfree(cifs_sb->prepath);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -02005111#ifdef CONFIG_CIFS_DFS_UPCALL
Paulo Alcantarae511d312018-11-14 17:16:44 -02005112 dfs_cache_del_vol(cifs_sb->origin_fullpath);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -02005113 kfree(cifs_sb->origin_fullpath);
5114#endif
Al Viro2e32cf52013-10-03 12:53:37 -04005115 call_rcu(&cifs_sb->rcu, delayed_free);
Steve French50c2f752007-07-13 00:33:32 +00005116}
Linus Torvalds1da177e2005-04-16 15:20:36 -07005117
Pavel Shilovsky286170a2012-05-25 10:43:58 +04005118int
5119cifs_negotiate_protocol(const unsigned int xid, struct cifs_ses *ses)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005120{
5121 int rc = 0;
Jeff Layton198b5682010-04-24 07:57:48 -04005122 struct TCP_Server_Info *server = ses->server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005123
Pavel Shilovsky286170a2012-05-25 10:43:58 +04005124 if (!server->ops->need_neg || !server->ops->negotiate)
5125 return -ENOSYS;
5126
Jeff Layton198b5682010-04-24 07:57:48 -04005127 /* only send once per connect */
Pavel Shilovsky286170a2012-05-25 10:43:58 +04005128 if (!server->ops->need_neg(server))
Jeff Layton198b5682010-04-24 07:57:48 -04005129 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005130
Pavel Shilovsky286170a2012-05-25 10:43:58 +04005131 rc = server->ops->negotiate(xid, ses);
Jeff Layton198b5682010-04-24 07:57:48 -04005132 if (rc == 0) {
5133 spin_lock(&GlobalMid_Lock);
Jeff Layton7fdbaa12011-06-10 16:14:57 -04005134 if (server->tcpStatus == CifsNeedNegotiate)
Jeff Layton198b5682010-04-24 07:57:48 -04005135 server->tcpStatus = CifsGood;
5136 else
5137 rc = -EHOSTDOWN;
5138 spin_unlock(&GlobalMid_Lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005139 }
Steve French26b994f2008-08-06 05:11:33 +00005140
Jeff Layton198b5682010-04-24 07:57:48 -04005141 return rc;
5142}
Steve French26b994f2008-08-06 05:11:33 +00005143
Pavel Shilovsky58c45c52012-05-25 10:54:49 +04005144int
5145cifs_setup_session(const unsigned int xid, struct cifs_ses *ses,
5146 struct nls_table *nls_info)
Jeff Layton198b5682010-04-24 07:57:48 -04005147{
Pavel Shilovsky58c45c52012-05-25 10:54:49 +04005148 int rc = -ENOSYS;
Jeff Layton198b5682010-04-24 07:57:48 -04005149 struct TCP_Server_Info *server = ses->server;
5150
Jeff Layton198b5682010-04-24 07:57:48 -04005151 ses->capabilities = server->capabilities;
Steve French26b994f2008-08-06 05:11:33 +00005152 if (linuxExtEnabled == 0)
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04005153 ses->capabilities &= (~server->vals->cap_unix);
Steve French20418ac2009-04-30 16:13:32 +00005154
Joe Perchesf96637b2013-05-04 22:12:25 -05005155 cifs_dbg(FYI, "Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d\n",
Steve French96daf2b2011-05-27 04:34:02 +00005156 server->sec_mode, server->capabilities, server->timeAdj);
Jeff Laytoncb7691b2008-08-18 15:41:05 -04005157
Shu Wangf5c4ba82017-09-08 18:48:33 +08005158 if (ses->auth_key.response) {
Steve French2a182872018-03-29 12:16:34 -05005159 cifs_dbg(FYI, "Free previous auth_key.response = %p\n",
Shu Wangf5c4ba82017-09-08 18:48:33 +08005160 ses->auth_key.response);
5161 kfree(ses->auth_key.response);
5162 ses->auth_key.response = NULL;
5163 ses->auth_key.len = 0;
5164 }
5165
Pavel Shilovsky58c45c52012-05-25 10:54:49 +04005166 if (server->ops->sess_setup)
5167 rc = server->ops->sess_setup(xid, ses, nls_info);
5168
Shirish Pargaonkard4e63bd2013-08-29 08:35:09 -05005169 if (rc)
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10005170 cifs_server_dbg(VFS, "Send error in SessSetup = %d\n", rc);
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05005171
Linus Torvalds1da177e2005-04-16 15:20:36 -07005172 return rc;
5173}
5174
Jeff Layton8a8798a2012-01-17 16:09:15 -05005175static int
5176cifs_set_vol_auth(struct smb_vol *vol, struct cifs_ses *ses)
5177{
Jeff Layton3f618222013-06-12 19:52:14 -05005178 vol->sectype = ses->sectype;
5179
5180 /* krb5 is special, since we don't need username or pw */
5181 if (vol->sectype == Kerberos)
Jeff Layton8a8798a2012-01-17 16:09:15 -05005182 return 0;
Jeff Layton8a8798a2012-01-17 16:09:15 -05005183
5184 return cifs_set_cifscreds(vol, ses);
5185}
5186
Steve French96daf2b2011-05-27 04:34:02 +00005187static struct cifs_tcon *
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08005188cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid)
Jeff Layton9d002df2010-10-06 19:51:11 -04005189{
Jeff Layton8a8798a2012-01-17 16:09:15 -05005190 int rc;
Steve French96daf2b2011-05-27 04:34:02 +00005191 struct cifs_tcon *master_tcon = cifs_sb_master_tcon(cifs_sb);
5192 struct cifs_ses *ses;
5193 struct cifs_tcon *tcon = NULL;
Jeff Layton9d002df2010-10-06 19:51:11 -04005194 struct smb_vol *vol_info;
Jeff Layton9d002df2010-10-06 19:51:11 -04005195
5196 vol_info = kzalloc(sizeof(*vol_info), GFP_KERNEL);
Dan Carpenter803ab972012-01-24 11:39:22 +03005197 if (vol_info == NULL)
5198 return ERR_PTR(-ENOMEM);
Jeff Layton9d002df2010-10-06 19:51:11 -04005199
Jeff Layton9d002df2010-10-06 19:51:11 -04005200 vol_info->local_nls = cifs_sb->local_nls;
5201 vol_info->linux_uid = fsuid;
5202 vol_info->cred_uid = fsuid;
5203 vol_info->UNC = master_tcon->treeName;
5204 vol_info->retry = master_tcon->retry;
5205 vol_info->nocase = master_tcon->nocase;
Steve French3d4ef9a2018-04-25 22:19:09 -05005206 vol_info->nohandlecache = master_tcon->nohandlecache;
Jeff Layton9d002df2010-10-06 19:51:11 -04005207 vol_info->local_lease = master_tcon->local_lease;
5208 vol_info->no_linux_ext = !master_tcon->unix_ext;
Jeff Layton28e11bd2013-05-26 07:01:00 -04005209 vol_info->sectype = master_tcon->ses->sectype;
5210 vol_info->sign = master_tcon->ses->sign;
Jeff Layton9d002df2010-10-06 19:51:11 -04005211
Jeff Layton8a8798a2012-01-17 16:09:15 -05005212 rc = cifs_set_vol_auth(vol_info, master_tcon->ses);
5213 if (rc) {
5214 tcon = ERR_PTR(rc);
5215 goto out;
5216 }
Jeff Layton9d002df2010-10-06 19:51:11 -04005217
5218 /* get a reference for the same TCP session */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05305219 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04005220 ++master_tcon->ses->server->srv_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05305221 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04005222
5223 ses = cifs_get_smb_ses(master_tcon->ses->server, vol_info);
5224 if (IS_ERR(ses)) {
Steve French96daf2b2011-05-27 04:34:02 +00005225 tcon = (struct cifs_tcon *)ses;
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07005226 cifs_put_tcp_session(master_tcon->ses->server, 0);
Jeff Layton9d002df2010-10-06 19:51:11 -04005227 goto out;
5228 }
5229
5230 tcon = cifs_get_tcon(ses, vol_info);
5231 if (IS_ERR(tcon)) {
5232 cifs_put_smb_ses(ses);
5233 goto out;
5234 }
5235
Steve Frenchce558b02018-05-31 19:16:54 -05005236 /* if new SMB3.11 POSIX extensions are supported do not remap / and \ */
5237 if (tcon->posix_extensions)
5238 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS;
Steve French0fdfef92018-06-28 19:30:23 -05005239
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04005240 if (cap_unix(ses))
Jeff Layton9d002df2010-10-06 19:51:11 -04005241 reset_cifs_unix_caps(0, tcon, NULL, vol_info);
Steve Frenchb3266142018-05-20 23:41:10 -05005242
Jeff Layton9d002df2010-10-06 19:51:11 -04005243out:
Jeff Layton8a8798a2012-01-17 16:09:15 -05005244 kfree(vol_info->username);
Aurelien Aptel97f4b722018-01-25 15:59:39 +01005245 kzfree(vol_info->password);
Jeff Layton9d002df2010-10-06 19:51:11 -04005246 kfree(vol_info);
5247
5248 return tcon;
5249}
5250
Steve French96daf2b2011-05-27 04:34:02 +00005251struct cifs_tcon *
Jeff Layton9d002df2010-10-06 19:51:11 -04005252cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb)
5253{
5254 return tlink_tcon(cifs_sb_master_tlink(cifs_sb));
5255}
5256
Jeff Laytonb647c352010-10-28 11:16:44 -04005257/* find and return a tlink with given uid */
5258static struct tcon_link *
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08005259tlink_rb_search(struct rb_root *root, kuid_t uid)
Jeff Laytonb647c352010-10-28 11:16:44 -04005260{
5261 struct rb_node *node = root->rb_node;
5262 struct tcon_link *tlink;
5263
5264 while (node) {
5265 tlink = rb_entry(node, struct tcon_link, tl_rbnode);
5266
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08005267 if (uid_gt(tlink->tl_uid, uid))
Jeff Laytonb647c352010-10-28 11:16:44 -04005268 node = node->rb_left;
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08005269 else if (uid_lt(tlink->tl_uid, uid))
Jeff Laytonb647c352010-10-28 11:16:44 -04005270 node = node->rb_right;
5271 else
5272 return tlink;
5273 }
5274 return NULL;
5275}
5276
5277/* insert a tcon_link into the tree */
5278static void
5279tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink)
5280{
5281 struct rb_node **new = &(root->rb_node), *parent = NULL;
5282 struct tcon_link *tlink;
5283
5284 while (*new) {
5285 tlink = rb_entry(*new, struct tcon_link, tl_rbnode);
5286 parent = *new;
5287
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08005288 if (uid_gt(tlink->tl_uid, new_tlink->tl_uid))
Jeff Laytonb647c352010-10-28 11:16:44 -04005289 new = &((*new)->rb_left);
5290 else
5291 new = &((*new)->rb_right);
5292 }
5293
5294 rb_link_node(&new_tlink->tl_rbnode, parent, new);
5295 rb_insert_color(&new_tlink->tl_rbnode, root);
5296}
5297
Jeff Layton9d002df2010-10-06 19:51:11 -04005298/*
5299 * Find or construct an appropriate tcon given a cifs_sb and the fsuid of the
5300 * current task.
5301 *
5302 * If the superblock doesn't refer to a multiuser mount, then just return
5303 * the master tcon for the mount.
5304 *
Suresh Jayaraman6ef933a2010-11-03 10:53:49 +05305305 * First, search the rbtree for an existing tcon for this fsuid. If one
Jeff Layton9d002df2010-10-06 19:51:11 -04005306 * exists, then check to see if it's pending construction. If it is then wait
5307 * for construction to complete. Once it's no longer pending, check to see if
5308 * it failed and either return an error or retry construction, depending on
5309 * the timeout.
5310 *
5311 * If one doesn't exist then insert a new tcon_link struct into the tree and
5312 * try to construct a new one.
5313 */
5314struct tcon_link *
5315cifs_sb_tlink(struct cifs_sb_info *cifs_sb)
5316{
5317 int ret;
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08005318 kuid_t fsuid = current_fsuid();
Jeff Layton9d002df2010-10-06 19:51:11 -04005319 struct tcon_link *tlink, *newtlink;
5320
5321 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
5322 return cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
5323
5324 spin_lock(&cifs_sb->tlink_tree_lock);
Jeff Laytonb647c352010-10-28 11:16:44 -04005325 tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
Jeff Layton9d002df2010-10-06 19:51:11 -04005326 if (tlink)
5327 cifs_get_tlink(tlink);
5328 spin_unlock(&cifs_sb->tlink_tree_lock);
5329
5330 if (tlink == NULL) {
5331 newtlink = kzalloc(sizeof(*tlink), GFP_KERNEL);
5332 if (newtlink == NULL)
5333 return ERR_PTR(-ENOMEM);
Jeff Laytonb647c352010-10-28 11:16:44 -04005334 newtlink->tl_uid = fsuid;
Jeff Layton9d002df2010-10-06 19:51:11 -04005335 newtlink->tl_tcon = ERR_PTR(-EACCES);
5336 set_bit(TCON_LINK_PENDING, &newtlink->tl_flags);
5337 set_bit(TCON_LINK_IN_TREE, &newtlink->tl_flags);
5338 cifs_get_tlink(newtlink);
5339
Jeff Layton9d002df2010-10-06 19:51:11 -04005340 spin_lock(&cifs_sb->tlink_tree_lock);
5341 /* was one inserted after previous search? */
Jeff Laytonb647c352010-10-28 11:16:44 -04005342 tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
Jeff Layton9d002df2010-10-06 19:51:11 -04005343 if (tlink) {
5344 cifs_get_tlink(tlink);
5345 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04005346 kfree(newtlink);
5347 goto wait_for_construction;
5348 }
Jeff Layton9d002df2010-10-06 19:51:11 -04005349 tlink = newtlink;
Jeff Laytonb647c352010-10-28 11:16:44 -04005350 tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
5351 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04005352 } else {
5353wait_for_construction:
5354 ret = wait_on_bit(&tlink->tl_flags, TCON_LINK_PENDING,
Jeff Layton9d002df2010-10-06 19:51:11 -04005355 TASK_INTERRUPTIBLE);
5356 if (ret) {
5357 cifs_put_tlink(tlink);
NeilBrown74316202014-07-07 15:16:04 +10005358 return ERR_PTR(-ERESTARTSYS);
Jeff Layton9d002df2010-10-06 19:51:11 -04005359 }
5360
5361 /* if it's good, return it */
5362 if (!IS_ERR(tlink->tl_tcon))
5363 return tlink;
5364
5365 /* return error if we tried this already recently */
5366 if (time_before(jiffies, tlink->tl_time + TLINK_ERROR_EXPIRE)) {
5367 cifs_put_tlink(tlink);
5368 return ERR_PTR(-EACCES);
5369 }
5370
5371 if (test_and_set_bit(TCON_LINK_PENDING, &tlink->tl_flags))
5372 goto wait_for_construction;
5373 }
5374
5375 tlink->tl_tcon = cifs_construct_tcon(cifs_sb, fsuid);
5376 clear_bit(TCON_LINK_PENDING, &tlink->tl_flags);
5377 wake_up_bit(&tlink->tl_flags, TCON_LINK_PENDING);
5378
5379 if (IS_ERR(tlink->tl_tcon)) {
5380 cifs_put_tlink(tlink);
5381 return ERR_PTR(-EACCES);
5382 }
5383
5384 return tlink;
5385}
Jeff Layton2de970f2010-10-06 19:51:12 -04005386
5387/*
5388 * periodic workqueue job that scans tcon_tree for a superblock and closes
5389 * out tcons.
5390 */
5391static void
5392cifs_prune_tlinks(struct work_struct *work)
5393{
5394 struct cifs_sb_info *cifs_sb = container_of(work, struct cifs_sb_info,
5395 prune_tlinks.work);
Jeff Laytonb647c352010-10-28 11:16:44 -04005396 struct rb_root *root = &cifs_sb->tlink_tree;
Colin Ian King37e12f52018-01-17 09:52:39 +00005397 struct rb_node *node;
Jeff Laytonb647c352010-10-28 11:16:44 -04005398 struct rb_node *tmp;
5399 struct tcon_link *tlink;
Jeff Layton2de970f2010-10-06 19:51:12 -04005400
Jeff Laytonb647c352010-10-28 11:16:44 -04005401 /*
5402 * Because we drop the spinlock in the loop in order to put the tlink
5403 * it's not guarded against removal of links from the tree. The only
5404 * places that remove entries from the tree are this function and
5405 * umounts. Because this function is non-reentrant and is canceled
5406 * before umount can proceed, this is safe.
5407 */
5408 spin_lock(&cifs_sb->tlink_tree_lock);
5409 node = rb_first(root);
5410 while (node != NULL) {
5411 tmp = node;
5412 node = rb_next(tmp);
5413 tlink = rb_entry(tmp, struct tcon_link, tl_rbnode);
5414
5415 if (test_bit(TCON_LINK_MASTER, &tlink->tl_flags) ||
5416 atomic_read(&tlink->tl_count) != 0 ||
5417 time_after(tlink->tl_time + TLINK_IDLE_EXPIRE, jiffies))
5418 continue;
5419
5420 cifs_get_tlink(tlink);
5421 clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
5422 rb_erase(tmp, root);
5423
Jeff Layton2de970f2010-10-06 19:51:12 -04005424 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Laytonb647c352010-10-28 11:16:44 -04005425 cifs_put_tlink(tlink);
5426 spin_lock(&cifs_sb->tlink_tree_lock);
5427 }
5428 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton2de970f2010-10-06 19:51:12 -04005429
Jeff Laytonda472fc2012-03-23 14:40:53 -04005430 queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
Jeff Layton2de970f2010-10-06 19:51:12 -04005431 TLINK_IDLE_EXPIRE);
5432}