blob: ccaa8bad336f9d7e2b67cb1364a4ca4b6f1718d4 [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,
Paulo Alcantara (SUSE)8eecd1c2019-07-16 19:04:50 -030099 Opt_domainauto, Opt_rdma, Opt_modesid, Opt_rootfs,
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" },
Paulo Alcantara (SUSE)8eecd1c2019-07-16 19:04:50 -0300269 { Opt_rootfs, "rootfs" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400270
271 { Opt_err, NULL }
272};
273
274enum {
275 Opt_sec_krb5, Opt_sec_krb5i, Opt_sec_krb5p,
276 Opt_sec_ntlmsspi, Opt_sec_ntlmssp,
Jeff Layton76596242012-07-23 20:34:17 -0400277 Opt_ntlm, Opt_sec_ntlmi, Opt_sec_ntlmv2,
278 Opt_sec_ntlmv2i, Opt_sec_lanman,
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400279 Opt_sec_none,
280
281 Opt_sec_err
282};
283
284static const match_table_t cifs_secflavor_tokens = {
285 { Opt_sec_krb5, "krb5" },
286 { Opt_sec_krb5i, "krb5i" },
287 { Opt_sec_krb5p, "krb5p" },
288 { Opt_sec_ntlmsspi, "ntlmsspi" },
289 { Opt_sec_ntlmssp, "ntlmssp" },
290 { Opt_ntlm, "ntlm" },
291 { Opt_sec_ntlmi, "ntlmi" },
Jeff Layton76596242012-07-23 20:34:17 -0400292 { Opt_sec_ntlmv2, "nontlm" },
293 { Opt_sec_ntlmv2, "ntlmv2" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400294 { Opt_sec_ntlmv2i, "ntlmv2i" },
Sachin Prabhu8830d7e2012-03-23 14:40:56 -0400295 { Opt_sec_lanman, "lanman" },
296 { Opt_sec_none, "none" },
297
298 { Opt_sec_err, NULL }
299};
300
Jeff Layton15b6a472012-05-16 07:50:15 -0400301/* cache flavors */
302enum {
303 Opt_cache_loose,
304 Opt_cache_strict,
305 Opt_cache_none,
Steve French83bbfa72019-08-27 23:58:54 -0500306 Opt_cache_ro,
Steve French41e033f2019-08-30 02:12:41 -0500307 Opt_cache_rw,
Jeff Layton15b6a472012-05-16 07:50:15 -0400308 Opt_cache_err
309};
310
311static const match_table_t cifs_cacheflavor_tokens = {
312 { Opt_cache_loose, "loose" },
313 { Opt_cache_strict, "strict" },
314 { Opt_cache_none, "none" },
Steve French83bbfa72019-08-27 23:58:54 -0500315 { Opt_cache_ro, "ro" },
Steve French41e033f2019-08-30 02:12:41 -0500316 { Opt_cache_rw, "singleclient" },
Jeff Layton15b6a472012-05-16 07:50:15 -0400317 { Opt_cache_err, NULL }
318};
319
Jeff Layton23db65f2012-05-15 12:20:51 -0400320static const match_table_t cifs_smb_version_tokens = {
321 { Smb_1, SMB1_VERSION_STRING },
Steve Frenchdd446b12012-11-28 23:21:06 -0600322 { Smb_20, SMB20_VERSION_STRING},
Steve French1080ef72011-02-24 18:07:19 +0000323 { Smb_21, SMB21_VERSION_STRING },
Steve Frenche4aa25e2012-10-01 12:26:22 -0500324 { Smb_30, SMB30_VERSION_STRING },
Steve French20b6d8b2013-06-12 22:48:41 -0500325 { Smb_302, SMB302_VERSION_STRING },
Kenneth D'souza4a3b38a2018-11-17 10:33:30 +0530326 { Smb_302, ALT_SMB302_VERSION_STRING },
Steve French5f7fbf72014-12-17 22:52:58 -0600327 { Smb_311, SMB311_VERSION_STRING },
Steve Frenchaab18932015-06-23 23:37:11 -0500328 { Smb_311, ALT_SMB311_VERSION_STRING },
Steve French9764c022017-09-17 10:41:35 -0500329 { Smb_3any, SMB3ANY_VERSION_STRING },
330 { Smb_default, SMBDEFAULT_VERSION_STRING },
Steve French5f7fbf72014-12-17 22:52:58 -0600331 { Smb_version_err, NULL }
Jeff Layton23db65f2012-05-15 12:20:51 -0400332};
333
Pavel Shilovskya9f1b852010-12-13 19:08:35 +0300334static int ip_connect(struct TCP_Server_Info *server);
335static int generic_ip_connect(struct TCP_Server_Info *server);
Jeff Laytonb647c352010-10-28 11:16:44 -0400336static void tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink);
Jeff Layton2de970f2010-10-06 19:51:12 -0400337static void cifs_prune_tlinks(struct work_struct *work);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200338static char *extract_hostname(const char *unc);
339
Paulo Alcantara28eb24f2018-11-20 15:16:36 -0200340/*
341 * Resolve hostname and set ip addr in tcp ses. Useful for hostnames that may
342 * get their ip addresses changed at some point.
343 *
344 * This should be called with server->srv_mutex held.
345 */
346#ifdef CONFIG_CIFS_DFS_UPCALL
347static int reconn_set_ipaddr(struct TCP_Server_Info *server)
348{
349 int rc;
350 int len;
351 char *unc, *ipaddr = NULL;
352
353 if (!server->hostname)
354 return -EINVAL;
355
356 len = strlen(server->hostname) + 3;
357
358 unc = kmalloc(len, GFP_KERNEL);
359 if (!unc) {
360 cifs_dbg(FYI, "%s: failed to create UNC path\n", __func__);
361 return -ENOMEM;
362 }
Ronnie Sahlberg74ea5f92019-02-09 09:51:11 +1000363 scnprintf(unc, len, "\\\\%s", server->hostname);
Paulo Alcantara28eb24f2018-11-20 15:16:36 -0200364
365 rc = dns_resolve_server_name_to_ip(unc, &ipaddr);
366 kfree(unc);
367
368 if (rc < 0) {
369 cifs_dbg(FYI, "%s: failed to resolve server part of %s to IP: %d\n",
370 __func__, server->hostname, rc);
371 return rc;
372 }
373
374 rc = cifs_convert_address((struct sockaddr *)&server->dstaddr, ipaddr,
375 strlen(ipaddr));
376 kfree(ipaddr);
377
378 return !rc ? -1 : 0;
379}
380#else
381static inline int reconn_set_ipaddr(struct TCP_Server_Info *server)
382{
383 return 0;
384}
385#endif
386
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200387#ifdef CONFIG_CIFS_DFS_UPCALL
388struct super_cb_data {
389 struct TCP_Server_Info *server;
390 struct cifs_sb_info *cifs_sb;
391};
392
393/* These functions must be called with server->srv_mutex held */
394
395static void super_cb(struct super_block *sb, void *arg)
396{
397 struct super_cb_data *d = arg;
398 struct cifs_sb_info *cifs_sb;
399 struct cifs_tcon *tcon;
400
401 if (d->cifs_sb)
402 return;
403
404 cifs_sb = CIFS_SB(sb);
405 tcon = cifs_sb_master_tcon(cifs_sb);
406 if (tcon->ses->server == d->server)
407 d->cifs_sb = cifs_sb;
408}
409
410static inline struct cifs_sb_info *
411find_super_by_tcp(struct TCP_Server_Info *server)
412{
413 struct super_cb_data d = {
414 .server = server,
415 .cifs_sb = NULL,
416 };
417
418 iterate_supers_type(&cifs_fs_type, super_cb, &d);
419 return d.cifs_sb ? d.cifs_sb : ERR_PTR(-ENOENT);
420}
421
422static void reconn_inval_dfs_target(struct TCP_Server_Info *server,
423 struct cifs_sb_info *cifs_sb,
424 struct dfs_cache_tgt_list *tgt_list,
425 struct dfs_cache_tgt_iterator **tgt_it)
426{
427 const char *name;
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200428
429 if (!cifs_sb || !cifs_sb->origin_fullpath || !tgt_list ||
430 !server->nr_targets)
431 return;
432
433 if (!*tgt_it) {
434 *tgt_it = dfs_cache_get_tgt_iterator(tgt_list);
435 } else {
436 *tgt_it = dfs_cache_get_next_tgt(tgt_list, *tgt_it);
437 if (!*tgt_it)
438 *tgt_it = dfs_cache_get_tgt_iterator(tgt_list);
439 }
440
441 cifs_dbg(FYI, "%s: UNC: %s\n", __func__, cifs_sb->origin_fullpath);
442
443 name = dfs_cache_get_tgt_name(*tgt_it);
444
445 kfree(server->hostname);
446
447 server->hostname = extract_hostname(name);
Dan Carpenter84288172019-01-05 15:25:29 +0300448 if (IS_ERR(server->hostname)) {
449 cifs_dbg(FYI,
450 "%s: failed to extract hostname from target: %ld\n",
451 __func__, PTR_ERR(server->hostname));
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200452 }
453}
454
455static inline int reconn_setup_dfs_targets(struct cifs_sb_info *cifs_sb,
456 struct dfs_cache_tgt_list *tl,
457 struct dfs_cache_tgt_iterator **it)
458{
459 if (!cifs_sb->origin_fullpath)
460 return -EOPNOTSUPP;
461 return dfs_cache_noreq_find(cifs_sb->origin_fullpath + 1, NULL, tl);
462}
463#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700464
Jeff Laytond5c56052008-12-01 18:42:33 -0500465/*
466 * cifs tcp session reconnection
467 *
468 * mark tcp session as reconnecting so temporarily locked
469 * mark all smb sessions as reconnecting for tcp session
470 * reconnect tcp session
471 * wake up waiters on reconnection? - (not needed currently)
472 */
Pavel Shilovsky28ea5292012-05-23 16:18:00 +0400473int
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474cifs_reconnect(struct TCP_Server_Info *server)
475{
476 int rc = 0;
Jeff Laytonf1987b42008-11-15 11:12:47 -0500477 struct list_head *tmp, *tmp2;
Steve French96daf2b2011-05-27 04:34:02 +0000478 struct cifs_ses *ses;
479 struct cifs_tcon *tcon;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000480 struct mid_q_entry *mid_entry;
Jeff Layton3c1105d2011-05-22 07:09:13 -0400481 struct list_head retry_list;
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200482#ifdef CONFIG_CIFS_DFS_UPCALL
Paulo Alcantara23324402018-11-20 14:37:18 -0200483 struct cifs_sb_info *cifs_sb = NULL;
484 struct dfs_cache_tgt_list tgt_list = {0};
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200485 struct dfs_cache_tgt_iterator *tgt_it = NULL;
486#endif
Steve French50c2f752007-07-13 00:33:32 +0000487
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488 spin_lock(&GlobalMid_Lock);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200489 server->nr_targets = 1;
490#ifdef CONFIG_CIFS_DFS_UPCALL
Ronnie Sahlberg61cabc72019-06-14 13:02:29 +1000491 spin_unlock(&GlobalMid_Lock);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200492 cifs_sb = find_super_by_tcp(server);
493 if (IS_ERR(cifs_sb)) {
494 rc = PTR_ERR(cifs_sb);
495 cifs_dbg(FYI, "%s: will not do DFS failover: rc = %d\n",
496 __func__, rc);
497 cifs_sb = NULL;
498 } else {
499 rc = reconn_setup_dfs_targets(cifs_sb, &tgt_list, &tgt_it);
Steve French55a7f002019-01-01 17:19:45 -0600500 if (rc && (rc != -EOPNOTSUPP)) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000501 cifs_server_dbg(VFS, "%s: no target servers for DFS failover\n",
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200502 __func__);
503 } else {
504 server->nr_targets = dfs_cache_get_nr_tgts(&tgt_list);
505 }
506 }
507 cifs_dbg(FYI, "%s: will retry %d target(s)\n", __func__,
508 server->nr_targets);
Ronnie Sahlberg61cabc72019-06-14 13:02:29 +1000509 spin_lock(&GlobalMid_Lock);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200510#endif
Jeff Layton469ee612008-10-16 18:46:39 +0000511 if (server->tcpStatus == CifsExiting) {
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000512 /* the demux thread will exit normally
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513 next time through the loop */
514 spin_unlock(&GlobalMid_Lock);
515 return rc;
516 } else
517 server->tcpStatus = CifsNeedReconnect;
518 spin_unlock(&GlobalMid_Lock);
519 server->maxBuf = 0;
Pavel Shilovskyaa24d1e2011-12-27 16:23:34 +0400520 server->max_read = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700521
Steve French6e4d3bb2018-09-22 11:25:04 -0500522 cifs_dbg(FYI, "Mark tcp session as need reconnect\n");
Steve Frenchbf1fdeb2018-07-30 19:23:09 -0500523 trace_smb3_reconnect(server->CurrentMid, server->hostname);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700524
525 /* before reconnecting the tcp session, mark the smb session (uid)
526 and the tid bad so they are not used until reconnected */
Joe Perchesf96637b2013-05-04 22:12:25 -0500527 cifs_dbg(FYI, "%s: marking sessions and tcons for reconnect\n",
528 __func__);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +0530529 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -0500530 list_for_each(tmp, &server->smb_ses_list) {
Steve French96daf2b2011-05-27 04:34:02 +0000531 ses = list_entry(tmp, struct cifs_ses, smb_ses_list);
Jeff Layton14fbf502008-11-14 13:53:46 -0500532 ses->need_reconnect = true;
Jeff Laytonf1987b42008-11-15 11:12:47 -0500533 list_for_each(tmp2, &ses->tcon_list) {
Steve French96daf2b2011-05-27 04:34:02 +0000534 tcon = list_entry(tmp2, struct cifs_tcon, tcon_list);
Jeff Laytonf1987b42008-11-15 11:12:47 -0500535 tcon->need_reconnect = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700536 }
Aurelien Aptelb327a712018-01-24 13:46:10 +0100537 if (ses->tcon_ipc)
538 ses->tcon_ipc->need_reconnect = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700539 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +0530540 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500541
Linus Torvalds1da177e2005-04-16 15:20:36 -0700542 /* do not want to be sending data on a socket we are freeing */
Joe Perchesf96637b2013-05-04 22:12:25 -0500543 cifs_dbg(FYI, "%s: tearing down socket\n", __func__);
Jeff Layton72ca5452008-12-01 07:09:36 -0500544 mutex_lock(&server->srv_mutex);
Long Li1d2a4f52019-05-13 21:01:28 -0700545 if (server->ssocket) {
546 cifs_dbg(FYI, "State: 0x%x Flags: 0x%lx\n",
547 server->ssocket->state, server->ssocket->flags);
548 kernel_sock_shutdown(server->ssocket, SHUT_WR);
549 cifs_dbg(FYI, "Post shutdown state: 0x%x Flags: 0x%lx\n",
550 server->ssocket->state, server->ssocket->flags);
551 sock_release(server->ssocket);
552 server->ssocket = NULL;
553 }
554 server->sequence_number = 0;
555 server->session_estab = false;
556 kfree(server->session_key.response);
557 server->session_key.response = NULL;
558 server->session_key.len = 0;
559 server->lstrp = jiffies;
Long Li214bab42019-04-05 21:36:35 +0000560
561 /* mark submitted MIDs for retry and issue callback */
562 INIT_LIST_HEAD(&retry_list);
563 cifs_dbg(FYI, "%s: moving mids to private list\n", __func__);
564 spin_lock(&GlobalMid_Lock);
565 list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
566 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Pavel Shilovskyabe57072019-10-22 08:41:42 -0700567 kref_get(&mid_entry->refcount);
Long Li214bab42019-04-05 21:36:35 +0000568 if (mid_entry->mid_state == MID_REQUEST_SUBMITTED)
569 mid_entry->mid_state = MID_RETRY_NEEDED;
570 list_move(&mid_entry->qhead, &retry_list);
Pavel Shilovskyabe57072019-10-22 08:41:42 -0700571 mid_entry->mid_flags |= MID_DELETED;
Long Li214bab42019-04-05 21:36:35 +0000572 }
573 spin_unlock(&GlobalMid_Lock);
Long Li1d2a4f52019-05-13 21:01:28 -0700574 mutex_unlock(&server->srv_mutex);
Long Li214bab42019-04-05 21:36:35 +0000575
576 cifs_dbg(FYI, "%s: issuing mid callbacks\n", __func__);
577 list_for_each_safe(tmp, tmp2, &retry_list) {
578 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
579 list_del_init(&mid_entry->qhead);
580 mid_entry->callback(mid_entry);
Pavel Shilovskyabe57072019-10-22 08:41:42 -0700581 cifs_mid_q_entry_release(mid_entry);
Long Li214bab42019-04-05 21:36:35 +0000582 }
583
Long Li1d2a4f52019-05-13 21:01:28 -0700584 if (cifs_rdma_enabled(server)) {
585 mutex_lock(&server->srv_mutex);
Long Li050b8c32019-04-04 11:35:42 -0500586 smbd_destroy(server);
Long Li1d2a4f52019-05-13 21:01:28 -0700587 mutex_unlock(&server->srv_mutex);
588 }
Jeff Layton3c1105d2011-05-22 07:09:13 -0400589
Jeff Layton7fdbaa12011-06-10 16:14:57 -0400590 do {
Steve French6c3d8902006-07-31 22:46:20 +0000591 try_to_freeze();
Pavel Shilovskya9f1b852010-12-13 19:08:35 +0300592
Jeff Layton73e216a2013-09-05 08:38:10 -0400593 mutex_lock(&server->srv_mutex);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200594 /*
595 * Set up next DFS target server (if any) for reconnect. If DFS
596 * feature is disabled, then we will retry last server we
597 * connected to before.
598 */
Long Li781a8052017-11-22 17:38:36 -0700599 if (cifs_rdma_enabled(server))
600 rc = smbd_reconnect(server);
601 else
602 rc = generic_ip_connect(server);
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000603 if (rc) {
Joe Perchesf96637b2013-05-04 22:12:25 -0500604 cifs_dbg(FYI, "reconnect error %d\n", rc);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200605#ifdef CONFIG_CIFS_DFS_UPCALL
606 reconn_inval_dfs_target(server, cifs_sb, &tgt_list,
607 &tgt_it);
608#endif
Paulo Alcantara28eb24f2018-11-20 15:16:36 -0200609 rc = reconn_set_ipaddr(server);
610 if (rc) {
611 cifs_dbg(FYI, "%s: failed to resolve hostname: %d\n",
612 __func__, rc);
613 }
Federico Sauter4afe2602015-03-17 17:45:28 +0100614 mutex_unlock(&server->srv_mutex);
Steve French0cb766a2005-04-28 22:41:11 -0700615 msleep(3000);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700616 } else {
617 atomic_inc(&tcpSesReconnectCount);
Pavel Shilovsky335b7b62019-01-16 11:12:41 -0800618 set_credits(server, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619 spin_lock(&GlobalMid_Lock);
Jeff Layton469ee612008-10-16 18:46:39 +0000620 if (server->tcpStatus != CifsExiting)
Steve Frenchfd88ce92011-04-12 01:01:14 +0000621 server->tcpStatus = CifsNeedNegotiate;
Steve Frenchfb8c4b12007-07-10 01:16:18 +0000622 spin_unlock(&GlobalMid_Lock);
Federico Sauter4afe2602015-03-17 17:45:28 +0100623 mutex_unlock(&server->srv_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700624 }
Jeff Layton7fdbaa12011-06-10 16:14:57 -0400625 } while (server->tcpStatus == CifsNeedReconnect);
Jeff Layton2b84a36c2011-01-11 07:24:21 -0500626
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200627#ifdef CONFIG_CIFS_DFS_UPCALL
628 if (tgt_it) {
629 rc = dfs_cache_noreq_update_tgthint(cifs_sb->origin_fullpath + 1,
630 tgt_it);
631 if (rc) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000632 cifs_server_dbg(VFS, "%s: failed to update DFS target hint: rc = %d\n",
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200633 __func__, rc);
634 }
635 rc = dfs_cache_update_vol(cifs_sb->origin_fullpath, server);
636 if (rc) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000637 cifs_server_dbg(VFS, "%s: failed to update vol info in DFS cache: rc = %d\n",
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200638 __func__, rc);
639 }
Paulo Alcantara23324402018-11-20 14:37:18 -0200640 dfs_cache_free_tgts(&tgt_list);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200641 }
Paulo Alcantara93d5cb52018-11-14 17:13:25 -0200642#endif
Sachin Prabhub8c60012016-10-20 19:52:24 -0400643 if (server->tcpStatus == CifsNeedNegotiate)
644 mod_delayed_work(cifsiod_wq, &server->echo, 0);
645
Linus Torvalds1da177e2005-04-16 15:20:36 -0700646 return rc;
647}
648
Jeff Laytonc74093b2011-01-11 07:24:23 -0500649static void
650cifs_echo_request(struct work_struct *work)
651{
652 int rc;
653 struct TCP_Server_Info *server = container_of(work,
654 struct TCP_Server_Info, echo.work);
Sachin Prabhub8c60012016-10-20 19:52:24 -0400655 unsigned long echo_interval;
Jeff Laytonc74093b2011-01-11 07:24:23 -0500656
Jeff Layton247ec9b2011-02-04 17:09:50 -0500657 /*
Sachin Prabhub8c60012016-10-20 19:52:24 -0400658 * If we need to renegotiate, set echo interval to zero to
659 * immediately call echo service where we can renegotiate.
660 */
661 if (server->tcpStatus == CifsNeedNegotiate)
662 echo_interval = 0;
663 else
664 echo_interval = server->echo_interval;
665
666 /*
667 * We cannot send an echo if it is disabled.
668 * Also, no need to ping if we got a response recently.
Jeff Layton247ec9b2011-02-04 17:09:50 -0500669 */
Steve French4fcd1812016-06-22 20:12:05 -0500670
671 if (server->tcpStatus == CifsNeedReconnect ||
Sachin Prabhub8c60012016-10-20 19:52:24 -0400672 server->tcpStatus == CifsExiting ||
673 server->tcpStatus == CifsNew ||
Pavel Shilovskyf6d76172012-05-25 14:47:16 +0400674 (server->ops->can_echo && !server->ops->can_echo(server)) ||
Steve Frenchadfeb3e2015-12-18 12:31:36 -0600675 time_before(jiffies, server->lstrp + echo_interval - HZ))
Jeff Laytonc74093b2011-01-11 07:24:23 -0500676 goto requeue_echo;
677
Pavel Shilovskyf6d76172012-05-25 14:47:16 +0400678 rc = server->ops->echo ? server->ops->echo(server) : -ENOSYS;
Jeff Laytonc74093b2011-01-11 07:24:23 -0500679 if (rc)
Joe Perchesf96637b2013-05-04 22:12:25 -0500680 cifs_dbg(FYI, "Unable to send echo request to server: %s\n",
681 server->hostname);
Jeff Laytonc74093b2011-01-11 07:24:23 -0500682
683requeue_echo:
Sachin Prabhub8c60012016-10-20 19:52:24 -0400684 queue_delayed_work(cifsiod_wq, &server->echo, server->echo_interval);
Jeff Laytonc74093b2011-01-11 07:24:23 -0500685}
686
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400687static bool
Jeff Layton2a37ef92011-10-19 15:29:23 -0400688allocate_buffers(struct TCP_Server_Info *server)
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400689{
Jeff Layton2a37ef92011-10-19 15:29:23 -0400690 if (!server->bigbuf) {
691 server->bigbuf = (char *)cifs_buf_get();
692 if (!server->bigbuf) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000693 cifs_server_dbg(VFS, "No memory for large SMB response\n");
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400694 msleep(3000);
695 /* retry will check if exiting */
696 return false;
697 }
Jeff Layton2a37ef92011-10-19 15:29:23 -0400698 } else if (server->large_buf) {
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400699 /* we are reusing a dirty large buf, clear its start */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400700 memset(server->bigbuf, 0, HEADER_SIZE(server));
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400701 }
702
Jeff Layton2a37ef92011-10-19 15:29:23 -0400703 if (!server->smallbuf) {
704 server->smallbuf = (char *)cifs_small_buf_get();
705 if (!server->smallbuf) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000706 cifs_server_dbg(VFS, "No memory for SMB response\n");
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400707 msleep(1000);
708 /* retry will check if exiting */
709 return false;
710 }
711 /* beginning of smb buffer is cleared in our buf_get */
712 } else {
713 /* if existing small buf clear beginning */
Pavel Shilovsky1887f602012-05-17 12:45:31 +0400714 memset(server->smallbuf, 0, HEADER_SIZE(server));
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400715 }
716
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +0400717 return true;
718}
719
Jeff Laytonba749e62011-10-11 06:41:32 -0400720static bool
721server_unresponsive(struct TCP_Server_Info *server)
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400722{
Pavel Shilovsky6dae51a2012-02-21 16:50:23 +0300723 /*
Ronnie Sahlbergf2caf902019-07-06 06:52:46 +1000724 * We need to wait 3 echo intervals to make sure we handle such
Pavel Shilovsky6dae51a2012-02-21 16:50:23 +0300725 * situations right:
726 * 1s client sends a normal SMB request
Ronnie Sahlbergbecc2ba2019-07-24 11:43:49 +1000727 * 2s client gets a response
Pavel Shilovsky6dae51a2012-02-21 16:50:23 +0300728 * 30s echo workqueue job pops, and decides we got a response recently
729 * and don't need to send another
730 * ...
731 * 65s kernel_recvmsg times out, and we see that we haven't gotten
732 * a response in >60s.
733 */
Samuel Cabrero76e75272017-07-11 12:44:39 +0200734 if ((server->tcpStatus == CifsGood ||
735 server->tcpStatus == CifsNeedNegotiate) &&
Ronnie Sahlbergf2caf902019-07-06 06:52:46 +1000736 time_after(jiffies, server->lstrp + 3 * server->echo_interval)) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000737 cifs_server_dbg(VFS, "has not responded in %lu seconds. Reconnecting...\n",
738 (3 * server->echo_interval) / HZ);
Jeff Laytonba749e62011-10-11 06:41:32 -0400739 cifs_reconnect(server);
740 wake_up(&server->response_q);
741 return true;
742 }
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400743
Jeff Laytonba749e62011-10-11 06:41:32 -0400744 return false;
745}
746
Pavel Shilovskyef68e832019-01-18 17:25:36 -0800747static inline bool
748zero_credits(struct TCP_Server_Info *server)
749{
750 int val;
751
752 spin_lock(&server->req_lock);
753 val = server->credits + server->echo_credits + server->oplock_credits;
754 if (server->in_flight == 0 && val == 0) {
755 spin_unlock(&server->req_lock);
756 return true;
757 }
758 spin_unlock(&server->req_lock);
759 return false;
760}
761
Al Viro71335662016-01-09 19:54:50 -0500762static int
763cifs_readv_from_socket(struct TCP_Server_Info *server, struct msghdr *smb_msg)
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400764{
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400765 int length = 0;
766 int total_read;
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400767
Al Viro71335662016-01-09 19:54:50 -0500768 smb_msg->msg_control = NULL;
769 smb_msg->msg_controllen = 0;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400770
Al Viro71335662016-01-09 19:54:50 -0500771 for (total_read = 0; msg_data_left(smb_msg); total_read += length) {
Jeff Layton95edcff2011-12-01 20:22:41 -0500772 try_to_freeze();
773
Pavel Shilovskyef68e832019-01-18 17:25:36 -0800774 /* reconnect if no credits and no requests in flight */
775 if (zero_credits(server)) {
776 cifs_reconnect(server);
777 return -ECONNABORTED;
778 }
779
Al Viro71335662016-01-09 19:54:50 -0500780 if (server_unresponsive(server))
781 return -ECONNABORTED;
Long Li2fef1372017-11-22 17:38:41 -0700782 if (cifs_rdma_enabled(server) && server->smbd_conn)
783 length = smbd_recv(server->smbd_conn, smb_msg);
784 else
785 length = sock_recvmsg(server->ssocket, smb_msg, 0);
Al Viro71335662016-01-09 19:54:50 -0500786
787 if (server->tcpStatus == CifsExiting)
788 return -ESHUTDOWN;
789
790 if (server->tcpStatus == CifsNeedReconnect) {
791 cifs_reconnect(server);
792 return -ECONNABORTED;
Jeff Laytonba749e62011-10-11 06:41:32 -0400793 }
794
Al Viro71335662016-01-09 19:54:50 -0500795 if (length == -ERESTARTSYS ||
796 length == -EAGAIN ||
797 length == -EINTR) {
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400798 /*
799 * Minimum sleep to prevent looping, allowing socket
800 * to clear and app threads to set tcpStatus
801 * CifsNeedReconnect if server hung.
802 */
803 usleep_range(1000, 2000);
804 length = 0;
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400805 continue;
Al Viro71335662016-01-09 19:54:50 -0500806 }
807
808 if (length <= 0) {
Al Viro09aab882015-11-13 03:00:17 -0500809 cifs_dbg(FYI, "Received no data or error: %d\n", length);
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400810 cifs_reconnect(server);
Al Viro71335662016-01-09 19:54:50 -0500811 return -ECONNABORTED;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400812 }
813 }
Jeff Laytona52c1eb2011-10-11 06:41:32 -0400814 return total_read;
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400815}
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400816
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400817int
818cifs_read_from_socket(struct TCP_Server_Info *server, char *buf,
819 unsigned int to_read)
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400820{
Al Viro71335662016-01-09 19:54:50 -0500821 struct msghdr smb_msg;
822 struct kvec iov = {.iov_base = buf, .iov_len = to_read};
David Howellsaa563d72018-10-20 00:57:56 +0100823 iov_iter_kvec(&smb_msg.msg_iter, READ, &iov, 1, to_read);
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400824
Al Viro71335662016-01-09 19:54:50 -0500825 return cifs_readv_from_socket(server, &smb_msg);
826}
Jeff Layton42c4dfc2011-10-19 15:28:17 -0400827
Al Viro71335662016-01-09 19:54:50 -0500828int
829cifs_read_page_from_socket(struct TCP_Server_Info *server, struct page *page,
Long Li1dbe3462018-05-30 12:47:55 -0700830 unsigned int page_offset, unsigned int to_read)
Al Viro71335662016-01-09 19:54:50 -0500831{
832 struct msghdr smb_msg;
Long Li1dbe3462018-05-30 12:47:55 -0700833 struct bio_vec bv = {
834 .bv_page = page, .bv_len = to_read, .bv_offset = page_offset};
David Howellsaa563d72018-10-20 00:57:56 +0100835 iov_iter_bvec(&smb_msg.msg_iter, READ, &bv, 1, to_read);
Al Viro71335662016-01-09 19:54:50 -0500836 return cifs_readv_from_socket(server, &smb_msg);
Pavel Shilovskye7015fb2011-08-01 13:19:41 +0400837}
838
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400839static bool
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400840is_smb_response(struct TCP_Server_Info *server, unsigned char type)
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400841{
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400842 /*
843 * The first byte big endian of the length field,
844 * is actually not part of the length but the type
845 * with the most common, zero, as regular data.
846 */
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400847 switch (type) {
848 case RFC1002_SESSION_MESSAGE:
849 /* Regular SMB response */
850 return true;
851 case RFC1002_SESSION_KEEP_ALIVE:
Joe Perchesf96637b2013-05-04 22:12:25 -0500852 cifs_dbg(FYI, "RFC 1002 session keep alive\n");
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400853 break;
854 case RFC1002_POSITIVE_SESSION_RESPONSE:
Joe Perchesf96637b2013-05-04 22:12:25 -0500855 cifs_dbg(FYI, "RFC 1002 positive session response\n");
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400856 break;
857 case RFC1002_NEGATIVE_SESSION_RESPONSE:
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400858 /*
859 * We get this from Windows 98 instead of an error on
860 * SMB negprot response.
861 */
Joe Perchesf96637b2013-05-04 22:12:25 -0500862 cifs_dbg(FYI, "RFC 1002 negative session response\n");
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400863 /* give server a second to clean up */
864 msleep(1000);
865 /*
866 * Always try 445 first on reconnect since we get NACK
867 * on some if we ever connected to port 139 (the NACK
868 * is since we do not begin with RFC1001 session
869 * initialize frame).
870 */
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400871 cifs_set_port((struct sockaddr *)&server->dstaddr, CIFS_PORT);
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400872 cifs_reconnect(server);
873 wake_up(&server->response_q);
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400874 break;
875 default:
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +1000876 cifs_server_dbg(VFS, "RFC 1002 unknown response type 0x%x\n", type);
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400877 cifs_reconnect(server);
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400878 }
879
Jeff Laytonfe11e4c2011-10-11 06:41:32 -0400880 return false;
Pavel Shilovsky98bac622011-08-01 13:19:42 +0400881}
882
Jeff Laytone28bc5b2011-10-19 15:30:07 -0400883void
884dequeue_mid(struct mid_q_entry *mid, bool malformed)
Jeff Laytonea1f4502011-10-19 15:29:05 -0400885{
886#ifdef CONFIG_CIFS_STATS2
887 mid->when_received = jiffies;
888#endif
889 spin_lock(&GlobalMid_Lock);
890 if (!malformed)
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400891 mid->mid_state = MID_RESPONSE_RECEIVED;
Jeff Laytonea1f4502011-10-19 15:29:05 -0400892 else
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400893 mid->mid_state = MID_RESPONSE_MALFORMED;
Ronnie Sahlbergddf83af2018-08-30 10:12:59 +1000894 /*
895 * Trying to handle/dequeue a mid after the send_recv()
896 * function has finished processing it is a bug.
897 */
898 if (mid->mid_flags & MID_DELETED)
899 printk_once(KERN_WARNING
900 "trying to dequeue a deleted mid\n");
Pavel Shilovskyabe57072019-10-22 08:41:42 -0700901 else {
Ronnie Sahlbergddf83af2018-08-30 10:12:59 +1000902 list_del_init(&mid->qhead);
Pavel Shilovskyabe57072019-10-22 08:41:42 -0700903 mid->mid_flags |= MID_DELETED;
904 }
Jeff Laytonea1f4502011-10-19 15:29:05 -0400905 spin_unlock(&GlobalMid_Lock);
906}
907
Jeff Laytonc8054eb2011-10-19 15:29:31 -0400908static void
909handle_mid(struct mid_q_entry *mid, struct TCP_Server_Info *server,
Pavel Shilovskyd4e48542012-03-23 14:28:02 -0400910 char *buf, int malformed)
Jeff Laytonea1f4502011-10-19 15:29:05 -0400911{
Pavel Shilovsky316cf942012-05-23 14:31:03 +0400912 if (server->ops->check_trans2 &&
913 server->ops->check_trans2(mid, server, buf, malformed))
Jeff Laytonc8054eb2011-10-19 15:29:31 -0400914 return;
Jeff Laytonea1f4502011-10-19 15:29:05 -0400915 mid->resp_buf = buf;
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400916 mid->large_buf = server->large_buf;
Jeff Layton2a37ef92011-10-19 15:29:23 -0400917 /* Was previous buf put in mpx struct for multi-rsp? */
918 if (!mid->multiRsp) {
919 /* smb buffer will be freed by user thread */
920 if (server->large_buf)
921 server->bigbuf = NULL;
922 else
923 server->smallbuf = NULL;
924 }
Jeff Laytonffc00e22011-10-19 15:29:13 -0400925 dequeue_mid(mid, malformed);
Pavel Shilovskyad69bae2011-08-01 13:19:43 +0400926}
927
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400928static void clean_demultiplex_info(struct TCP_Server_Info *server)
929{
930 int length;
931
932 /* take it off the list, if it's not already */
933 spin_lock(&cifs_tcp_ses_lock);
934 list_del_init(&server->tcp_ses_list);
935 spin_unlock(&cifs_tcp_ses_lock);
936
937 spin_lock(&GlobalMid_Lock);
938 server->tcpStatus = CifsExiting;
939 spin_unlock(&GlobalMid_Lock);
940 wake_up_all(&server->response_q);
941
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +0400942 /* check if we have blocked requests that need to free */
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +0300943 spin_lock(&server->req_lock);
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +0400944 if (server->credits <= 0)
945 server->credits = 1;
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +0300946 spin_unlock(&server->req_lock);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400947 /*
948 * Although there should not be any requests blocked on this queue it
949 * can not hurt to be paranoid and try to wake up requests that may
950 * haven been blocked when more than 50 at time were on the wire to the
951 * same server - they now will see the session is in exit state and get
952 * out of SendReceive.
953 */
954 wake_up_all(&server->request_q);
955 /* give those requests time to exit */
956 msleep(125);
Long Li050b8c32019-04-04 11:35:42 -0500957 if (cifs_rdma_enabled(server))
958 smbd_destroy(server);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400959 if (server->ssocket) {
960 sock_release(server->ssocket);
961 server->ssocket = NULL;
962 }
963
964 if (!list_empty(&server->pending_mid_q)) {
965 struct list_head dispose_list;
966 struct mid_q_entry *mid_entry;
967 struct list_head *tmp, *tmp2;
968
969 INIT_LIST_HEAD(&dispose_list);
970 spin_lock(&GlobalMid_Lock);
971 list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
972 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Joe Perchesf96637b2013-05-04 22:12:25 -0500973 cifs_dbg(FYI, "Clearing mid 0x%llx\n", mid_entry->mid);
Pavel Shilovskyabe57072019-10-22 08:41:42 -0700974 kref_get(&mid_entry->refcount);
Pavel Shilovsky7c9421e2012-03-23 14:28:03 -0400975 mid_entry->mid_state = MID_SHUTDOWN;
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400976 list_move(&mid_entry->qhead, &dispose_list);
Pavel Shilovskyabe57072019-10-22 08:41:42 -0700977 mid_entry->mid_flags |= MID_DELETED;
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400978 }
979 spin_unlock(&GlobalMid_Lock);
980
981 /* now walk dispose list and issue callbacks */
982 list_for_each_safe(tmp, tmp2, &dispose_list) {
983 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
Joe Perchesf96637b2013-05-04 22:12:25 -0500984 cifs_dbg(FYI, "Callback mid 0x%llx\n", mid_entry->mid);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400985 list_del_init(&mid_entry->qhead);
986 mid_entry->callback(mid_entry);
Pavel Shilovskyabe57072019-10-22 08:41:42 -0700987 cifs_mid_q_entry_release(mid_entry);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +0400988 }
989 /* 1/8th of sec is more than enough time for them to exit */
990 msleep(125);
991 }
992
993 if (!list_empty(&server->pending_mid_q)) {
994 /*
995 * mpx threads have not exited yet give them at least the smb
996 * send timeout time for long ops.
997 *
998 * Due to delays on oplock break requests, we need to wait at
999 * least 45 seconds before giving up on a request getting a
1000 * response and going ahead and killing cifsd.
1001 */
Joe Perchesf96637b2013-05-04 22:12:25 -05001002 cifs_dbg(FYI, "Wait for exit from demultiplex thread\n");
Pavel Shilovsky762dfd12011-08-01 13:19:44 +04001003 msleep(46000);
1004 /*
1005 * If threads still have not exited they are probably never
1006 * coming home not much else we can do but free the memory.
1007 */
1008 }
1009
1010 kfree(server->hostname);
1011 kfree(server);
1012
1013 length = atomic_dec_return(&tcpSesAllocCount);
1014 if (length > 0)
David Rientjes11d83362015-04-14 15:48:21 -07001015 mempool_resize(cifs_req_poolp, length + cifs_min_rcv);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +04001016}
1017
Pavel Shilovskye7015fb2011-08-01 13:19:41 +04001018static int
Jeff Laytone9097ab2011-10-19 15:29:40 -04001019standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1020{
1021 int length;
1022 char *buf = server->smallbuf;
Ronnie Sahlberg2e964672018-04-09 18:06:26 +10001023 unsigned int pdu_length = server->pdu_size;
Jeff Laytone9097ab2011-10-19 15:29:40 -04001024
1025 /* make sure this will fit in a large buffer */
Ronnie Sahlberg93012bf2018-03-31 11:45:31 +11001026 if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server) -
1027 server->vals->header_preamble_size) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10001028 cifs_server_dbg(VFS, "SMB response too long (%u bytes)\n", pdu_length);
Jeff Laytone9097ab2011-10-19 15:29:40 -04001029 cifs_reconnect(server);
1030 wake_up(&server->response_q);
Pavel Shilovsky3fabaa22014-07-10 09:55:52 +04001031 return -ECONNABORTED;
Jeff Laytone9097ab2011-10-19 15:29:40 -04001032 }
1033
1034 /* switch to large buffer if too big for a small one */
1035 if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) {
1036 server->large_buf = true;
Pavel Shilovskyd4e48542012-03-23 14:28:02 -04001037 memcpy(server->bigbuf, buf, server->total_read);
Jeff Laytone9097ab2011-10-19 15:29:40 -04001038 buf = server->bigbuf;
Jeff Laytone9097ab2011-10-19 15:29:40 -04001039 }
1040
1041 /* now read the rest */
Pavel Shilovsky1887f602012-05-17 12:45:31 +04001042 length = cifs_read_from_socket(server, buf + HEADER_SIZE(server) - 1,
Ronnie Sahlberg93012bf2018-03-31 11:45:31 +11001043 pdu_length - HEADER_SIZE(server) + 1
1044 + server->vals->header_preamble_size);
1045
Jeff Laytone9097ab2011-10-19 15:29:40 -04001046 if (length < 0)
1047 return length;
1048 server->total_read += length;
1049
Pavel Shilovskyd4e48542012-03-23 14:28:02 -04001050 dump_smb(buf, server->total_read);
Jeff Laytone9097ab2011-10-19 15:29:40 -04001051
Pavel Shilovsky4326ed22016-11-17 15:24:46 -08001052 return cifs_handle_standard(server, mid);
1053}
1054
1055int
1056cifs_handle_standard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1057{
1058 char *buf = server->large_buf ? server->bigbuf : server->smallbuf;
1059 int length;
1060
Jeff Laytone9097ab2011-10-19 15:29:40 -04001061 /*
1062 * We know that we received enough to get to the MID as we
1063 * checked the pdu_length earlier. Now check to see
1064 * if the rest of the header is OK. We borrow the length
1065 * var for the rest of the loop to avoid a new stack var.
1066 *
1067 * 48 bytes is enough to display the header and a little bit
1068 * into the payload for debugging purposes.
1069 */
Steve French373512e2015-12-18 13:05:30 -06001070 length = server->ops->check_message(buf, server->total_read, server);
Jeff Laytone9097ab2011-10-19 15:29:40 -04001071 if (length != 0)
1072 cifs_dump_mem("Bad SMB: ", buf,
1073 min_t(unsigned int, server->total_read, 48));
1074
Pavel Shilovsky511c54a2017-07-08 14:32:00 -07001075 if (server->ops->is_session_expired &&
1076 server->ops->is_session_expired(buf)) {
1077 cifs_reconnect(server);
1078 wake_up(&server->response_q);
1079 return -1;
1080 }
1081
Pavel Shilovsky2e44b282012-09-18 16:20:33 -07001082 if (server->ops->is_status_pending &&
Pavel Shilovsky66265f12019-01-23 17:11:16 -08001083 server->ops->is_status_pending(buf, server))
Pavel Shilovsky2e44b282012-09-18 16:20:33 -07001084 return -1;
1085
Jeff Laytonff4fa4a2012-02-07 06:31:05 -05001086 if (!mid)
1087 return length;
Jeff Laytone9097ab2011-10-19 15:29:40 -04001088
Pavel Shilovskyd4e48542012-03-23 14:28:02 -04001089 handle_mid(mid, server, buf, length);
Jeff Laytonff4fa4a2012-02-07 06:31:05 -05001090 return 0;
Jeff Laytone9097ab2011-10-19 15:29:40 -04001091}
1092
Ronnie Sahlbergeca00452019-02-05 12:56:44 +10001093static void
1094smb2_add_credits_from_hdr(char *buffer, struct TCP_Server_Info *server)
1095{
1096 struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buffer;
1097
1098 /*
1099 * SMB1 does not use credits.
1100 */
1101 if (server->vals->header_preamble_size)
1102 return;
1103
1104 if (shdr->CreditRequest) {
1105 spin_lock(&server->req_lock);
1106 server->credits += le16_to_cpu(shdr->CreditRequest);
1107 spin_unlock(&server->req_lock);
1108 wake_up(&server->request_q);
1109 }
1110}
1111
1112
Jeff Laytone9097ab2011-10-19 15:29:40 -04001113static int
Al Viro7c97c202011-06-21 08:51:28 -04001114cifs_demultiplex_thread(void *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001115{
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001116 int i, num_mids, length;
Al Viro7c97c202011-06-21 08:51:28 -04001117 struct TCP_Server_Info *server = p;
Jeff Layton2a37ef92011-10-19 15:29:23 -04001118 unsigned int pdu_length;
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001119 unsigned int next_offset;
Jeff Layton2a37ef92011-10-19 15:29:23 -04001120 char *buf = NULL;
Steve Frencha5c3e1c2014-09-16 04:16:19 -05001121 struct task_struct *task_to_wake = NULL;
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001122 struct mid_q_entry *mids[MAX_COMPOUND];
1123 char *bufs[MAX_COMPOUND];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001124
Linus Torvalds1da177e2005-04-16 15:20:36 -07001125 current->flags |= PF_MEMALLOC;
Joe Perchesf96637b2013-05-04 22:12:25 -05001126 cifs_dbg(FYI, "Demultiplex PID: %d\n", task_pid_nr(current));
Jeff Layton93d0ec82008-08-02 08:00:48 -04001127
1128 length = atomic_inc_return(&tcpSesAllocCount);
1129 if (length > 1)
David Rientjes11d83362015-04-14 15:48:21 -07001130 mempool_resize(cifs_req_poolp, length + cifs_min_rcv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001131
Rafael J. Wysocki83144182007-07-17 04:03:35 -07001132 set_freezable();
Eric W. Biederman33da8e72019-08-16 12:33:54 -05001133 allow_kernel_signal(SIGKILL);
Jeff Layton469ee612008-10-16 18:46:39 +00001134 while (server->tcpStatus != CifsExiting) {
Steve Frenchede13272005-08-30 20:10:14 -07001135 if (try_to_freeze())
1136 continue;
Steve Frenchb8643e12005-04-28 22:41:07 -07001137
Jeff Layton2a37ef92011-10-19 15:29:23 -04001138 if (!allocate_buffers(server))
Pavel Shilovsky3d9c2472011-08-01 13:19:40 +04001139 continue;
Steve Frenchb8643e12005-04-28 22:41:07 -07001140
Jeff Layton2a37ef92011-10-19 15:29:23 -04001141 server->large_buf = false;
Jeff Layton2a37ef92011-10-19 15:29:23 -04001142 buf = server->smallbuf;
Steve Frenchf01d5e12007-08-30 21:13:31 +00001143 pdu_length = 4; /* enough to get RFC1001 header */
Steve Frenchfda35942011-01-20 18:06:34 +00001144
Jeff Laytone28bc5b2011-10-19 15:30:07 -04001145 length = cifs_read_from_socket(server, buf, pdu_length);
Jeff Laytona52c1eb2011-10-11 06:41:32 -04001146 if (length < 0)
Steve Frenchfda35942011-01-20 18:06:34 +00001147 continue;
Ronnie Sahlberg977b6172018-06-01 10:53:02 +10001148
1149 if (server->vals->header_preamble_size == 0)
1150 server->total_read = 0;
1151 else
1152 server->total_read = length;
Steve French67010fb2005-04-28 22:41:09 -07001153
Pavel Shilovsky98bac622011-08-01 13:19:42 +04001154 /*
1155 * The right amount was read from socket - 4 bytes,
1156 * so we can now interpret the length field.
1157 */
Pavel Shilovskyd4e48542012-03-23 14:28:02 -04001158 pdu_length = get_rfc1002_length(buf);
Steve French46810cb2005-04-28 22:41:09 -07001159
Joe Perchesf96637b2013-05-04 22:12:25 -05001160 cifs_dbg(FYI, "RFC1002 header 0x%x\n", pdu_length);
Jeff Laytonfe11e4c2011-10-11 06:41:32 -04001161 if (!is_smb_response(server, buf[0]))
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001162 continue;
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001163next_pdu:
1164 server->pdu_size = pdu_length;
Steve Frenche4eb2952005-04-28 22:41:09 -07001165
Jeff Layton89482a52011-10-19 15:28:57 -04001166 /* make sure we have enough to get to the MID */
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001167 if (server->pdu_size < HEADER_SIZE(server) - 1 -
Ronnie Sahlberg93012bf2018-03-31 11:45:31 +11001168 server->vals->header_preamble_size) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10001169 cifs_server_dbg(VFS, "SMB response too short (%u bytes)\n",
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001170 server->pdu_size);
Jeff Layton89482a52011-10-19 15:28:57 -04001171 cifs_reconnect(server);
1172 wake_up(&server->response_q);
1173 continue;
Steve Frenche4eb2952005-04-28 22:41:09 -07001174 }
Pavel Shilovskye7015fb2011-08-01 13:19:41 +04001175
Jeff Layton89482a52011-10-19 15:28:57 -04001176 /* read down to the MID */
Ronnie Sahlberg93012bf2018-03-31 11:45:31 +11001177 length = cifs_read_from_socket(server,
1178 buf + server->vals->header_preamble_size,
1179 HEADER_SIZE(server) - 1
1180 - server->vals->header_preamble_size);
Jeff Layton89482a52011-10-19 15:28:57 -04001181 if (length < 0)
1182 continue;
Jeff Layton2a37ef92011-10-19 15:29:23 -04001183 server->total_read += length;
Jeff Layton89482a52011-10-19 15:28:57 -04001184
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001185 if (server->ops->next_header) {
1186 next_offset = server->ops->next_header(buf);
1187 if (next_offset)
1188 server->pdu_size = next_offset;
1189 }
1190
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001191 memset(mids, 0, sizeof(mids));
1192 memset(bufs, 0, sizeof(bufs));
1193 num_mids = 0;
1194
Pavel Shilovsky9bb17e02016-11-17 15:24:34 -08001195 if (server->ops->is_transform_hdr &&
1196 server->ops->receive_transform &&
1197 server->ops->is_transform_hdr(buf)) {
1198 length = server->ops->receive_transform(server,
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001199 mids,
1200 bufs,
1201 &num_mids);
Pavel Shilovsky9bb17e02016-11-17 15:24:34 -08001202 } else {
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001203 mids[0] = server->ops->find_mid(server, buf);
1204 bufs[0] = buf;
Steve French7af929d2018-10-02 18:54:09 -05001205 num_mids = 1;
Jeff Laytonc8054eb2011-10-19 15:29:31 -04001206
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001207 if (!mids[0] || !mids[0]->receive)
1208 length = standard_receive3(server, mids[0]);
Pavel Shilovsky9bb17e02016-11-17 15:24:34 -08001209 else
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001210 length = mids[0]->receive(server, mids[0]);
Pavel Shilovsky9bb17e02016-11-17 15:24:34 -08001211 }
Jeff Layton44d22d82011-10-19 15:29:49 -04001212
Lars Persson696e4202018-06-25 14:05:25 +02001213 if (length < 0) {
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001214 for (i = 0; i < num_mids; i++)
1215 if (mids[i])
1216 cifs_mid_q_entry_release(mids[i]);
Steve Frenche4eb2952005-04-28 22:41:09 -07001217 continue;
Lars Persson696e4202018-06-25 14:05:25 +02001218 }
Steve Frenche4eb2952005-04-28 22:41:09 -07001219
Steve Frenchfda35942011-01-20 18:06:34 +00001220 server->lstrp = jiffies;
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001221
1222 for (i = 0; i < num_mids; i++) {
1223 if (mids[i] != NULL) {
1224 mids[i]->resp_buf_size = server->pdu_size;
1225 if ((mids[i]->mid_flags & MID_WAIT_CANCELLED) &&
1226 mids[i]->mid_state == MID_RESPONSE_RECEIVED &&
1227 server->ops->handle_cancelled_mid)
1228 server->ops->handle_cancelled_mid(
1229 mids[i]->resp_buf,
Sachin Prabhu38bd4902017-03-03 15:41:38 -08001230 server);
1231
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001232 if (!mids[i]->multiRsp || mids[i]->multiEnd)
1233 mids[i]->callback(mids[i]);
Lars Persson696e4202018-06-25 14:05:25 +02001234
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001235 cifs_mid_q_entry_release(mids[i]);
1236 } else if (server->ops->is_oplock_break &&
1237 server->ops->is_oplock_break(bufs[i],
1238 server)) {
Ronnie Sahlbergeca00452019-02-05 12:56:44 +10001239 smb2_add_credits_from_hdr(bufs[i], server);
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001240 cifs_dbg(FYI, "Received oplock break\n");
1241 } else {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10001242 cifs_server_dbg(VFS, "No task to wake, unknown frame "
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001243 "received! NumMids %d\n",
1244 atomic_read(&midCount));
1245 cifs_dump_mem("Received Data is: ", bufs[i],
1246 HEADER_SIZE(server));
Ronnie Sahlberg3e272572019-07-06 06:43:08 +10001247 smb2_add_credits_from_hdr(bufs[i], server);
Steve French39798772006-05-31 22:40:51 +00001248#ifdef CONFIG_CIFS_DEBUG2
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001249 if (server->ops->dump_detail)
1250 server->ops->dump_detail(bufs[i],
1251 server);
1252 cifs_dump_mids(server);
Steve French39798772006-05-31 22:40:51 +00001253#endif /* CIFS_DEBUG2 */
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001254 }
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001255 }
Ronnie Sahlbergb24df3e2018-08-08 15:07:45 +10001256
Ronnie Sahlberg8ce79ec2018-06-01 10:53:08 +10001257 if (pdu_length > server->pdu_size) {
1258 if (!allocate_buffers(server))
1259 continue;
1260 pdu_length -= server->pdu_size;
1261 server->total_read = 0;
1262 server->large_buf = false;
1263 buf = server->smallbuf;
1264 goto next_pdu;
Steve Frenche4eb2952005-04-28 22:41:09 -07001265 }
1266 } /* end while !EXITING */
1267
Justin P. Mattockfd62cb72011-02-24 22:15:02 -08001268 /* buffer usually freed in free_mid - need to free it here on exit */
Jeff Layton2a37ef92011-10-19 15:29:23 -04001269 cifs_buf_release(server->bigbuf);
1270 if (server->smallbuf) /* no sense logging a debug message if NULL */
1271 cifs_small_buf_release(server->smallbuf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001272
Steve Frencha5c3e1c2014-09-16 04:16:19 -05001273 task_to_wake = xchg(&server->tsk, NULL);
Pavel Shilovsky762dfd12011-08-01 13:19:44 +04001274 clean_demultiplex_info(server);
Steve Frencha5c3e1c2014-09-16 04:16:19 -05001275
1276 /* if server->tsk was NULL then wait for a signal before exiting */
1277 if (!task_to_wake) {
1278 set_current_state(TASK_INTERRUPTIBLE);
1279 while (!signal_pending(current)) {
1280 schedule();
1281 set_current_state(TASK_INTERRUPTIBLE);
1282 }
1283 set_current_state(TASK_RUNNING);
1284 }
1285
Jeff Layton0468a2c2008-12-01 07:09:35 -05001286 module_put_and_exit(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001287}
1288
Jeff Laytonc359cf32007-11-16 22:22:06 +00001289/* extract the host portion of the UNC string */
1290static char *
1291extract_hostname(const char *unc)
1292{
1293 const char *src;
1294 char *dst, *delim;
1295 unsigned int len;
1296
1297 /* skip double chars at beginning of string */
1298 /* BB: check validity of these bytes? */
Paulo Alcantarac34fea52018-11-14 14:03:40 -02001299 if (strlen(unc) < 3)
1300 return ERR_PTR(-EINVAL);
1301 for (src = unc; *src && *src == '\\'; src++)
1302 ;
1303 if (!*src)
1304 return ERR_PTR(-EINVAL);
Jeff Laytonc359cf32007-11-16 22:22:06 +00001305
1306 /* delimiter between hostname and sharename is always '\\' now */
1307 delim = strchr(src, '\\');
1308 if (!delim)
1309 return ERR_PTR(-EINVAL);
1310
1311 len = delim - src;
1312 dst = kmalloc((len + 1), GFP_KERNEL);
1313 if (dst == NULL)
1314 return ERR_PTR(-ENOMEM);
1315
1316 memcpy(dst, src, len);
1317 dst[len] = '\0';
1318
1319 return dst;
1320}
1321
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001322static int get_option_ul(substring_t args[], unsigned long *option)
1323{
1324 int rc;
1325 char *string;
1326
1327 string = match_strdup(args);
1328 if (string == NULL)
1329 return -ENOMEM;
Sachin Prabhubfa890a2012-04-13 14:04:32 +01001330 rc = kstrtoul(string, 0, option);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001331 kfree(string);
1332
1333 return rc;
1334}
1335
Eric W. Biederman3da46562013-02-06 01:37:39 -08001336static int get_option_uid(substring_t args[], kuid_t *result)
1337{
1338 unsigned long value;
1339 kuid_t uid;
1340 int rc;
1341
1342 rc = get_option_ul(args, &value);
1343 if (rc)
1344 return rc;
1345
1346 uid = make_kuid(current_user_ns(), value);
1347 if (!uid_valid(uid))
1348 return -EINVAL;
1349
1350 *result = uid;
1351 return 0;
1352}
1353
1354static int get_option_gid(substring_t args[], kgid_t *result)
1355{
1356 unsigned long value;
1357 kgid_t gid;
1358 int rc;
1359
1360 rc = get_option_ul(args, &value);
1361 if (rc)
1362 return rc;
1363
1364 gid = make_kgid(current_user_ns(), value);
1365 if (!gid_valid(gid))
1366 return -EINVAL;
1367
1368 *result = gid;
1369 return 0;
1370}
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001371
1372static int cifs_parse_security_flavors(char *value,
1373 struct smb_vol *vol)
1374{
1375
1376 substring_t args[MAX_OPT_ARGS];
1377
Jeff Layton1e3cc572013-06-10 17:12:23 -05001378 /*
1379 * With mount options, the last one should win. Reset any existing
1380 * settings back to default.
1381 */
1382 vol->sectype = Unspecified;
1383 vol->sign = false;
1384
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001385 switch (match_token(value, cifs_secflavor_tokens, args)) {
Jeff Layton3f618222013-06-12 19:52:14 -05001386 case Opt_sec_krb5p:
1387 cifs_dbg(VFS, "sec=krb5p is not supported!\n");
1388 return 1;
1389 case Opt_sec_krb5i:
1390 vol->sign = true;
1391 /* Fallthrough */
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001392 case Opt_sec_krb5:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001393 vol->sectype = Kerberos;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001394 break;
1395 case Opt_sec_ntlmsspi:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001396 vol->sign = true;
Jeff Layton3f618222013-06-12 19:52:14 -05001397 /* Fallthrough */
1398 case Opt_sec_ntlmssp:
1399 vol->sectype = RawNTLMSSP;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001400 break;
1401 case Opt_sec_ntlmi:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001402 vol->sign = true;
Jeff Layton3f618222013-06-12 19:52:14 -05001403 /* Fallthrough */
1404 case Opt_ntlm:
1405 vol->sectype = NTLM;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001406 break;
1407 case Opt_sec_ntlmv2i:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001408 vol->sign = true;
Jeff Layton3f618222013-06-12 19:52:14 -05001409 /* Fallthrough */
1410 case Opt_sec_ntlmv2:
1411 vol->sectype = NTLMv2;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001412 break;
1413#ifdef CONFIG_CIFS_WEAK_PW_HASH
1414 case Opt_sec_lanman:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001415 vol->sectype = LANMAN;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001416 break;
1417#endif
1418 case Opt_sec_none:
1419 vol->nullauth = 1;
1420 break;
1421 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05001422 cifs_dbg(VFS, "bad security option: %s\n", value);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001423 return 1;
1424 }
1425
1426 return 0;
1427}
1428
Linus Torvalds1da177e2005-04-16 15:20:36 -07001429static int
Jeff Layton15b6a472012-05-16 07:50:15 -04001430cifs_parse_cache_flavor(char *value, struct smb_vol *vol)
1431{
1432 substring_t args[MAX_OPT_ARGS];
1433
1434 switch (match_token(value, cifs_cacheflavor_tokens, args)) {
1435 case Opt_cache_loose:
1436 vol->direct_io = false;
1437 vol->strict_io = false;
Steve French83bbfa72019-08-27 23:58:54 -05001438 vol->cache_ro = false;
Steve French41e033f2019-08-30 02:12:41 -05001439 vol->cache_rw = false;
Jeff Layton15b6a472012-05-16 07:50:15 -04001440 break;
1441 case Opt_cache_strict:
1442 vol->direct_io = false;
1443 vol->strict_io = true;
Steve French83bbfa72019-08-27 23:58:54 -05001444 vol->cache_ro = false;
Steve French41e033f2019-08-30 02:12:41 -05001445 vol->cache_rw = false;
Jeff Layton15b6a472012-05-16 07:50:15 -04001446 break;
1447 case Opt_cache_none:
1448 vol->direct_io = true;
1449 vol->strict_io = false;
Steve French83bbfa72019-08-27 23:58:54 -05001450 vol->cache_ro = false;
Steve French41e033f2019-08-30 02:12:41 -05001451 vol->cache_rw = false;
Steve French83bbfa72019-08-27 23:58:54 -05001452 break;
1453 case Opt_cache_ro:
1454 vol->direct_io = false;
1455 vol->strict_io = false;
1456 vol->cache_ro = true;
Steve French41e033f2019-08-30 02:12:41 -05001457 vol->cache_rw = false;
1458 break;
1459 case Opt_cache_rw:
1460 vol->direct_io = false;
1461 vol->strict_io = false;
1462 vol->cache_ro = false;
1463 vol->cache_rw = true;
Jeff Layton15b6a472012-05-16 07:50:15 -04001464 break;
1465 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05001466 cifs_dbg(VFS, "bad cache= option: %s\n", value);
Jeff Layton15b6a472012-05-16 07:50:15 -04001467 return 1;
1468 }
1469 return 0;
1470}
1471
1472static int
Steve Frenchc7c137b2018-06-06 17:59:29 -05001473cifs_parse_smb_version(char *value, struct smb_vol *vol, bool is_smb3)
Jeff Layton23db65f2012-05-15 12:20:51 -04001474{
1475 substring_t args[MAX_OPT_ARGS];
1476
1477 switch (match_token(value, cifs_smb_version_tokens, args)) {
Steve French74204512018-06-19 14:34:08 -05001478#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
Jeff Layton23db65f2012-05-15 12:20:51 -04001479 case Smb_1:
Steve Frenchf92a7202018-05-24 04:11:07 -05001480 if (disable_legacy_dialects) {
1481 cifs_dbg(VFS, "mount with legacy dialect disabled\n");
1482 return 1;
1483 }
Steve Frenchc7c137b2018-06-06 17:59:29 -05001484 if (is_smb3) {
1485 cifs_dbg(VFS, "vers=1.0 (cifs) not permitted when mounting with smb3\n");
1486 return 1;
1487 }
Jeff Layton23db65f2012-05-15 12:20:51 -04001488 vol->ops = &smb1_operations;
1489 vol->vals = &smb1_values;
1490 break;
Steve Frenchdd446b12012-11-28 23:21:06 -06001491 case Smb_20:
Steve Frenchf92a7202018-05-24 04:11:07 -05001492 if (disable_legacy_dialects) {
1493 cifs_dbg(VFS, "mount with legacy dialect disabled\n");
1494 return 1;
1495 }
Steve Frenchc7c137b2018-06-06 17:59:29 -05001496 if (is_smb3) {
1497 cifs_dbg(VFS, "vers=2.0 not permitted when mounting with smb3\n");
1498 return 1;
1499 }
Pavel Shilovsky53ef1012013-09-05 16:11:28 +04001500 vol->ops = &smb20_operations;
Steve Frenchdd446b12012-11-28 23:21:06 -06001501 vol->vals = &smb20_values;
1502 break;
Steve French74204512018-06-19 14:34:08 -05001503#else
1504 case Smb_1:
1505 cifs_dbg(VFS, "vers=1.0 (cifs) mount not permitted when legacy dialects disabled\n");
1506 return 1;
1507 case Smb_20:
1508 cifs_dbg(VFS, "vers=2.0 mount not permitted when legacy dialects disabled\n");
1509 return 1;
1510#endif /* CIFS_ALLOW_INSECURE_LEGACY */
Steve French1080ef72011-02-24 18:07:19 +00001511 case Smb_21:
1512 vol->ops = &smb21_operations;
1513 vol->vals = &smb21_values;
1514 break;
Steve Frenche4aa25e2012-10-01 12:26:22 -05001515 case Smb_30:
Steve French38107d42012-12-08 22:08:06 -06001516 vol->ops = &smb30_operations;
Steve Frenche4aa25e2012-10-01 12:26:22 -05001517 vol->vals = &smb30_values;
1518 break;
Steve French20b6d8b2013-06-12 22:48:41 -05001519 case Smb_302:
1520 vol->ops = &smb30_operations; /* currently identical with 3.0 */
1521 vol->vals = &smb302_values;
1522 break;
Steve French5f7fbf72014-12-17 22:52:58 -06001523 case Smb_311:
Steve Frenchaab18932015-06-23 23:37:11 -05001524 vol->ops = &smb311_operations;
Steve French5f7fbf72014-12-17 22:52:58 -06001525 vol->vals = &smb311_values;
1526 break;
Steve French9764c022017-09-17 10:41:35 -05001527 case Smb_3any:
1528 vol->ops = &smb30_operations; /* currently identical with 3.0 */
1529 vol->vals = &smb3any_values;
1530 break;
1531 case Smb_default:
1532 vol->ops = &smb30_operations; /* currently identical with 3.0 */
1533 vol->vals = &smbdefault_values;
1534 break;
Jeff Layton23db65f2012-05-15 12:20:51 -04001535 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05001536 cifs_dbg(VFS, "Unknown vers= option specified: %s\n", value);
Jeff Layton23db65f2012-05-15 12:20:51 -04001537 return 1;
1538 }
1539 return 0;
1540}
1541
Jeff Laytond387a5c2012-12-10 06:10:46 -05001542/*
1543 * Parse a devname into substrings and populate the vol->UNC and vol->prepath
1544 * fields with the result. Returns 0 on success and an error otherwise.
1545 */
1546static int
1547cifs_parse_devname(const char *devname, struct smb_vol *vol)
1548{
1549 char *pos;
1550 const char *delims = "/\\";
1551 size_t len;
1552
Yao Liu68e26722019-01-28 19:47:28 +08001553 if (unlikely(!devname || !*devname)) {
1554 cifs_dbg(VFS, "Device name not specified.\n");
1555 return -EINVAL;
1556 }
1557
Jeff Laytond387a5c2012-12-10 06:10:46 -05001558 /* make sure we have a valid UNC double delimiter prefix */
1559 len = strspn(devname, delims);
1560 if (len != 2)
1561 return -EINVAL;
1562
1563 /* find delimiter between host and sharename */
1564 pos = strpbrk(devname + 2, delims);
1565 if (!pos)
1566 return -EINVAL;
1567
1568 /* skip past delimiter */
1569 ++pos;
1570
1571 /* now go until next delimiter or end of string */
1572 len = strcspn(pos, delims);
1573
1574 /* move "pos" up to delimiter or NULL */
1575 pos += len;
1576 vol->UNC = kstrndup(devname, pos - devname, GFP_KERNEL);
1577 if (!vol->UNC)
1578 return -ENOMEM;
1579
1580 convert_delimiter(vol->UNC, '\\');
1581
Sachin Prabhu11e31642016-02-08 13:44:01 +05301582 /* skip any delimiter */
1583 if (*pos == '/' || *pos == '\\')
1584 pos++;
1585
1586 /* If pos is NULL then no prepath */
1587 if (!*pos)
Jeff Laytond387a5c2012-12-10 06:10:46 -05001588 return 0;
1589
1590 vol->prepath = kstrdup(pos, GFP_KERNEL);
1591 if (!vol->prepath)
1592 return -ENOMEM;
1593
1594 return 0;
1595}
1596
Jeff Layton23db65f2012-05-15 12:20:51 -04001597static int
Sean Finneyb9468452011-04-11 13:19:32 +00001598cifs_parse_mount_options(const char *mountdata, const char *devname,
Steve Frenchc7c137b2018-06-06 17:59:29 -05001599 struct smb_vol *vol, bool is_smb3)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001600{
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001601 char *data, *end;
Vasily Averin957df452011-06-06 11:33:12 +04001602 char *mountdata_copy = NULL, *options;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001603 unsigned int temp_len, i, j;
1604 char separator[2];
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001605 short int override_uid = -1;
1606 short int override_gid = -1;
1607 bool uid_specified = false;
1608 bool gid_specified = false;
Jeff Laytond8162552012-03-23 14:40:56 -04001609 bool sloppy = false;
1610 char *invalid = NULL;
Jeff Layton88463992010-11-22 15:31:03 -05001611 char *nodename = utsname()->nodename;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001612 char *string = NULL;
1613 char *tmp_end, *value;
1614 char delim;
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001615 bool got_ip = false;
Steve French7e682f72017-08-31 21:34:24 -05001616 bool got_version = false;
Jeff Laytonb979aaa2012-11-26 11:09:55 -05001617 unsigned short port = 0;
1618 struct sockaddr *dstaddr = (struct sockaddr *)&vol->dstaddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001619
1620 separator[0] = ',';
Steve French50c2f752007-07-13 00:33:32 +00001621 separator[1] = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001622 delim = separator[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001623
Jeff Layton6ee95422012-11-26 11:09:57 -05001624 /* ensure we always start with zeroed-out smb_vol */
1625 memset(vol, 0, sizeof(*vol));
1626
Jeff Layton88463992010-11-22 15:31:03 -05001627 /*
1628 * does not have to be perfect mapping since field is
1629 * informational, only used for servers that do not support
1630 * port 445 and it can be overridden at mount time
1631 */
Jeff Layton1397f2e2011-01-07 11:30:28 -05001632 memset(vol->source_rfc1001_name, 0x20, RFC1001_NAME_LEN);
1633 for (i = 0; i < strnlen(nodename, RFC1001_NAME_LEN); i++)
Jeff Layton88463992010-11-22 15:31:03 -05001634 vol->source_rfc1001_name[i] = toupper(nodename[i]);
1635
Jeff Layton1397f2e2011-01-07 11:30:28 -05001636 vol->source_rfc1001_name[RFC1001_NAME_LEN] = 0;
Steve Frencha10faeb22005-08-22 21:38:31 -07001637 /* null target name indicates to use *SMBSERVR default called name
1638 if we end up sending RFC1001 session initialize */
1639 vol->target_rfc1001_name[0] = 0;
Jeff Layton3e4b3e12010-07-19 18:00:17 -04001640 vol->cred_uid = current_uid();
1641 vol->linux_uid = current_uid();
David Howellsa001e5b2008-11-14 10:38:47 +11001642 vol->linux_gid = current_gid();
Steve Frenche8506d22019-02-28 21:32:15 -06001643 vol->bsize = 1024 * 1024; /* can improve cp performance significantly */
Steve French2baa2682014-09-27 02:19:01 -05001644 /*
1645 * default to SFM style remapping of seven reserved characters
1646 * unless user overrides it or we negotiate CIFS POSIX where
1647 * it is unnecessary. Can not simultaneously use more than one mapping
1648 * since then readdir could list files that open could not open
1649 */
1650 vol->remap = true;
1651
Jeff Laytonf55ed1a2009-05-26 16:28:11 -04001652 /* default to only allowing write access to owner of the mount */
1653 vol->dir_mode = vol->file_mode = S_IRUGO | S_IXUGO | S_IWUSR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001654
1655 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
Jeremy Allisonac670552005-06-22 17:26:35 -07001656 /* default is always to request posix paths. */
1657 vol->posix_paths = 1;
Jeff Laytona0c92172009-05-27 15:40:47 -04001658 /* default to using server inode numbers where available */
1659 vol->server_ino = 1;
Jeremy Allisonac670552005-06-22 17:26:35 -07001660
Jeff Layton1b359202012-09-19 15:20:27 -07001661 /* default is to use strict cifs caching semantics */
1662 vol->strict_io = true;
1663
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05301664 vol->actimeo = CIFS_DEF_ACTIMEO;
1665
Steve Frenchca567eb2019-03-29 16:31:07 -05001666 /* Most clients set timeout to 0, allows server to use its default */
1667 vol->handle_timeout = 0; /* See MS-SMB2 spec section 2.2.14.2.12 */
1668
Steve French9764c022017-09-17 10:41:35 -05001669 /* offer SMB2.1 and later (SMB3 etc). Secure and widely accepted */
1670 vol->ops = &smb30_operations;
1671 vol->vals = &smbdefault_values;
Jeff Layton23db65f2012-05-15 12:20:51 -04001672
Rabin Vincentb782fcc2016-07-19 09:25:45 +02001673 vol->echo_interval = SMB_ECHO_INTERVAL_DEFAULT;
1674
Sean Finneyb9468452011-04-11 13:19:32 +00001675 if (!mountdata)
1676 goto cifs_parse_mount_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001677
Sean Finneyb9468452011-04-11 13:19:32 +00001678 mountdata_copy = kstrndup(mountdata, PAGE_SIZE, GFP_KERNEL);
1679 if (!mountdata_copy)
1680 goto cifs_parse_mount_err;
1681
1682 options = mountdata_copy;
Pavel Shilovsky4906e502011-04-14 22:00:56 +04001683 end = options + strlen(options);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001684
Steve French50c2f752007-07-13 00:33:32 +00001685 if (strncmp(options, "sep=", 4) == 0) {
Steve Frenchfb8c4b12007-07-10 01:16:18 +00001686 if (options[4] != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001687 separator[0] = options[4];
1688 options += 5;
1689 } else {
Joe Perchesf96637b2013-05-04 22:12:25 -05001690 cifs_dbg(FYI, "Null separator not allowed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001691 }
1692 }
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001693 vol->backupuid_specified = false; /* no backup intent for a user */
1694 vol->backupgid_specified = false; /* no backup intent for a group */
Steve French50c2f752007-07-13 00:33:32 +00001695
Jeff Layton37d4f992013-05-24 07:40:05 -04001696 switch (cifs_parse_devname(devname, vol)) {
1697 case 0:
1698 break;
1699 case -ENOMEM:
1700 cifs_dbg(VFS, "Unable to allocate memory for devname.\n");
1701 goto cifs_parse_mount_err;
1702 case -EINVAL:
1703 cifs_dbg(VFS, "Malformed UNC in devname.\n");
1704 goto cifs_parse_mount_err;
1705 default:
1706 cifs_dbg(VFS, "Unknown error parsing devname.\n");
1707 goto cifs_parse_mount_err;
Jeff Laytond387a5c2012-12-10 06:10:46 -05001708 }
1709
Linus Torvalds1da177e2005-04-16 15:20:36 -07001710 while ((data = strsep(&options, separator)) != NULL) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001711 substring_t args[MAX_OPT_ARGS];
1712 unsigned long option;
1713 int token;
1714
Linus Torvalds1da177e2005-04-16 15:20:36 -07001715 if (!*data)
1716 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001717
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001718 token = match_token(data, cifs_mount_option_tokens, args);
1719
1720 switch (token) {
1721
1722 /* Ingnore the following */
1723 case Opt_ignore:
1724 break;
1725
1726 /* Boolean values */
1727 case Opt_user_xattr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001728 vol->no_xattr = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001729 break;
1730 case Opt_nouser_xattr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001731 vol->no_xattr = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001732 break;
1733 case Opt_forceuid:
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001734 override_uid = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001735 break;
1736 case Opt_noforceuid:
Jeff Layton9b9d6b242009-07-31 06:56:09 -04001737 override_uid = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001738 break;
Jeff Layton72bd4812012-10-03 16:02:36 -04001739 case Opt_forcegid:
1740 override_gid = 1;
1741 break;
1742 case Opt_noforcegid:
1743 override_gid = 0;
1744 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001745 case Opt_noblocksend:
Steve Frenchedf1ae42008-10-29 00:47:57 +00001746 vol->noblocksnd = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001747 break;
1748 case Opt_noautotune:
Steve Frenchedf1ae42008-10-29 00:47:57 +00001749 vol->noautotune = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001750 break;
Steve French3e7a02d2019-09-11 21:46:20 -05001751 case Opt_nolease:
1752 vol->no_lease = 1;
1753 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001754 case Opt_hard:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001755 vol->retry = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001756 break;
1757 case Opt_soft:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001758 vol->retry = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001759 break;
1760 case Opt_perm:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001761 vol->noperm = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001762 break;
1763 case Opt_noperm:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001764 vol->noperm = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001765 break;
1766 case Opt_mapchars:
Steve French2baa2682014-09-27 02:19:01 -05001767 vol->sfu_remap = true;
1768 vol->remap = false; /* disable SFM mapping */
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001769 break;
1770 case Opt_nomapchars:
Steve French2baa2682014-09-27 02:19:01 -05001771 vol->sfu_remap = false;
1772 break;
1773 case Opt_mapposix:
1774 vol->remap = true;
1775 vol->sfu_remap = false; /* disable SFU mapping */
1776 break;
1777 case Opt_nomapposix:
1778 vol->remap = false;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001779 break;
1780 case Opt_sfu:
Steve French50c2f752007-07-13 00:33:32 +00001781 vol->sfu_emul = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001782 break;
1783 case Opt_nosfu:
Steve French50c2f752007-07-13 00:33:32 +00001784 vol->sfu_emul = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001785 break;
1786 case Opt_nodfs:
Steve French2c1b8612008-10-16 18:35:21 +00001787 vol->nodfs = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001788 break;
Paulo Alcantara (SUSE)8eecd1c2019-07-16 19:04:50 -03001789 case Opt_rootfs:
1790#ifdef CONFIG_CIFS_ROOT
1791 vol->rootfs = true;
1792#endif
1793 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001794 case Opt_posixpaths:
Jeremy Allisonac670552005-06-22 17:26:35 -07001795 vol->posix_paths = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001796 break;
1797 case Opt_noposixpaths:
Jeremy Allisonac670552005-06-22 17:26:35 -07001798 vol->posix_paths = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001799 break;
1800 case Opt_nounix:
Steve Frenchb3266142018-05-20 23:41:10 -05001801 if (vol->linux_ext)
1802 cifs_dbg(VFS,
1803 "conflicting unix mount options\n");
Steve Frenchc18c8422007-07-18 23:21:09 +00001804 vol->no_linux_ext = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001805 break;
Steve Frenchb3266142018-05-20 23:41:10 -05001806 case Opt_unix:
1807 if (vol->no_linux_ext)
1808 cifs_dbg(VFS,
1809 "conflicting unix mount options\n");
1810 vol->linux_ext = 1;
1811 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001812 case Opt_nocase:
Steve French50c2f752007-07-13 00:33:32 +00001813 vol->nocase = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001814 break;
1815 case Opt_brl:
Steve Frenchc46fa8a2005-08-18 20:49:57 -07001816 vol->nobrl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001817 break;
1818 case Opt_nobrl:
Steve Frenchc46fa8a2005-08-18 20:49:57 -07001819 vol->nobrl = 1;
Pavel Shilovsky5cfdddc2012-03-27 20:51:15 +04001820 /*
1821 * turn off mandatory locking in mode
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001822 * if remote locking is turned off since the
Pavel Shilovsky5cfdddc2012-03-27 20:51:15 +04001823 * local vfs will do advisory
1824 */
Steve French50c2f752007-07-13 00:33:32 +00001825 if (vol->file_mode ==
1826 (S_IALLUGO & ~(S_ISUID | S_IXGRP)))
Steve Frenchd3485d32005-08-19 11:04:29 -07001827 vol->file_mode = S_IALLUGO;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001828 break;
Steve French3d4ef9a2018-04-25 22:19:09 -05001829 case Opt_nohandlecache:
1830 vol->nohandlecache = 1;
1831 break;
1832 case Opt_handlecache:
1833 vol->nohandlecache = 0;
1834 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001835 case Opt_forcemandatorylock:
Steve French13a6e422008-12-02 17:24:33 +00001836 vol->mand_lock = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001837 break;
1838 case Opt_setuids:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001839 vol->setuids = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001840 break;
1841 case Opt_nosetuids:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001842 vol->setuids = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001843 break;
Steve French95932652016-09-23 01:36:34 -05001844 case Opt_setuidfromacl:
1845 vol->setuidfromacl = 1;
1846 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001847 case Opt_dynperm:
Jeff Laytond0a9c072008-05-12 22:23:49 +00001848 vol->dynperm = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001849 break;
1850 case Opt_nodynperm:
Jeff Laytond0a9c072008-05-12 22:23:49 +00001851 vol->dynperm = false;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001852 break;
1853 case Opt_nohard:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001854 vol->retry = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001855 break;
1856 case Opt_nosoft:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001857 vol->retry = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001858 break;
1859 case Opt_nointr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001860 vol->intr = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001861 break;
1862 case Opt_intr:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001863 vol->intr = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001864 break;
1865 case Opt_nostrictsync:
Steve Frenchbe652442009-02-23 15:21:59 +00001866 vol->nostrictsync = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001867 break;
1868 case Opt_strictsync:
Steve Frenchbe652442009-02-23 15:21:59 +00001869 vol->nostrictsync = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001870 break;
1871 case Opt_serverino:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001872 vol->server_ino = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001873 break;
1874 case Opt_noserverino:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001875 vol->server_ino = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001876 break;
1877 case Opt_rwpidforward:
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00001878 vol->rwpidforward = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001879 break;
Steve French412094a2019-06-24 02:01:42 -05001880 case Opt_modesid:
1881 vol->mode_ace = 1;
1882 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001883 case Opt_cifsacl:
Steve French0a4b92c2006-01-12 15:44:21 -08001884 vol->cifs_acl = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001885 break;
1886 case Opt_nocifsacl:
Steve French0a4b92c2006-01-12 15:44:21 -08001887 vol->cifs_acl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001888 break;
1889 case Opt_acl:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001890 vol->no_psx_acl = 0;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001891 break;
1892 case Opt_noacl:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001893 vol->no_psx_acl = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001894 break;
1895 case Opt_locallease:
Steve French84210e92008-10-23 04:42:37 +00001896 vol->local_lease = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001897 break;
1898 case Opt_sign:
Jeff Layton1e3cc572013-06-10 17:12:23 -05001899 vol->sign = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001900 break;
Steve French4f5c10f2019-09-03 21:18:49 -05001901 case Opt_ignore_signature:
1902 vol->sign = true;
1903 vol->ignore_signature = true;
1904 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001905 case Opt_seal:
Steve French95b1cb92008-05-15 16:44:38 +00001906 /* we do not do the following in secFlags because seal
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001907 * is a per tree connection (mount) not a per socket
1908 * or per-smb connection option in the protocol
1909 * vol->secFlg |= CIFSSEC_MUST_SEAL;
1910 */
Steve French95b1cb92008-05-15 16:44:38 +00001911 vol->seal = 1;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001912 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001913 case Opt_noac:
Andy Shevchenko0b456f02014-08-27 16:49:44 +03001914 pr_warn("CIFS: Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001915 break;
1916 case Opt_fsc:
Suresh Jayaraman607a5692010-11-24 17:49:05 +05301917#ifndef CONFIG_CIFS_FSCACHE
Joe Perchesf96637b2013-05-04 22:12:25 -05001918 cifs_dbg(VFS, "FS-Cache support needs CONFIG_CIFS_FSCACHE kernel config option set\n");
Sean Finneyb9468452011-04-11 13:19:32 +00001919 goto cifs_parse_mount_err;
Suresh Jayaraman607a5692010-11-24 17:49:05 +05301920#endif
Suresh Jayaramanfa1df752010-07-05 18:13:36 +05301921 vol->fsc = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001922 break;
1923 case Opt_mfsymlinks:
Stefan Metzmacher736a33202010-07-30 14:56:00 +02001924 vol->mfsymlinks = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001925 break;
1926 case Opt_multiuser:
Jeff Layton0eb8a132010-10-06 19:51:12 -04001927 vol->multiuser = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001928 break;
Jeff Laytond8162552012-03-23 14:40:56 -04001929 case Opt_sloppy:
1930 sloppy = true;
1931 break;
Jeff Laytona0b3df52013-05-24 07:40:59 -04001932 case Opt_nosharesock:
1933 vol->nosharesock = true;
1934 break;
Steve Frenchb2a30772015-09-29 21:49:28 -05001935 case Opt_nopersistent:
1936 vol->nopersistent = true;
1937 if (vol->persistent) {
1938 cifs_dbg(VFS,
1939 "persistenthandles mount options conflict\n");
1940 goto cifs_parse_mount_err;
1941 }
1942 break;
1943 case Opt_persistent:
1944 vol->persistent = true;
Steve French592fafe2015-11-03 10:08:53 -06001945 if ((vol->nopersistent) || (vol->resilient)) {
Steve Frenchb2a30772015-09-29 21:49:28 -05001946 cifs_dbg(VFS,
1947 "persistenthandles mount options conflict\n");
1948 goto cifs_parse_mount_err;
1949 }
1950 break;
Steve French592fafe2015-11-03 10:08:53 -06001951 case Opt_resilient:
1952 vol->resilient = true;
1953 if (vol->persistent) {
1954 cifs_dbg(VFS,
1955 "persistenthandles mount options conflict\n");
1956 goto cifs_parse_mount_err;
1957 }
1958 break;
1959 case Opt_noresilient:
1960 vol->resilient = false; /* already the default */
1961 break;
Germano Percossi39566442016-12-15 12:31:18 +05301962 case Opt_domainauto:
1963 vol->domainauto = true;
1964 break;
Long Li8339dd32017-11-07 01:54:55 -07001965 case Opt_rdma:
1966 vol->rdma = true;
1967 break;
Steve French9fe5ff12019-06-24 20:39:04 -05001968 case Opt_compress:
1969 vol->compression = UNKNOWN_TYPE;
1970 cifs_dbg(VFS,
1971 "SMB3 compression support is experimental\n");
1972 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001973
1974 /* Numeric Values */
1975 case Opt_backupuid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001976 if (get_option_uid(args, &vol->backupuid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001977 cifs_dbg(VFS, "%s: Invalid backupuid value\n",
1978 __func__);
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001979 goto cifs_parse_mount_err;
1980 }
1981 vol->backupuid_specified = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001982 break;
1983 case Opt_backupgid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001984 if (get_option_gid(args, &vol->backupgid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001985 cifs_dbg(VFS, "%s: Invalid backupgid value\n",
1986 __func__);
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05001987 goto cifs_parse_mount_err;
1988 }
1989 vol->backupgid_specified = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001990 break;
1991 case Opt_uid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08001992 if (get_option_uid(args, &vol->linux_uid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05001993 cifs_dbg(VFS, "%s: Invalid uid value\n",
1994 __func__);
Sean Finneyb9468452011-04-11 13:19:32 +00001995 goto cifs_parse_mount_err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001996 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04001997 uid_specified = true;
1998 break;
1999 case Opt_cruid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08002000 if (get_option_uid(args, &vol->cred_uid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002001 cifs_dbg(VFS, "%s: Invalid cruid value\n",
2002 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002003 goto cifs_parse_mount_err;
2004 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002005 break;
2006 case Opt_gid:
Eric W. Biederman3da46562013-02-06 01:37:39 -08002007 if (get_option_gid(args, &vol->linux_gid)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002008 cifs_dbg(VFS, "%s: Invalid gid value\n",
2009 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002010 goto cifs_parse_mount_err;
2011 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002012 gid_specified = true;
2013 break;
2014 case Opt_file_mode:
2015 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002016 cifs_dbg(VFS, "%s: Invalid file_mode value\n",
2017 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002018 goto cifs_parse_mount_err;
2019 }
2020 vol->file_mode = option;
2021 break;
2022 case Opt_dirmode:
2023 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002024 cifs_dbg(VFS, "%s: Invalid dir_mode value\n",
2025 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002026 goto cifs_parse_mount_err;
2027 }
2028 vol->dir_mode = option;
2029 break;
2030 case Opt_port:
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002031 if (get_option_ul(args, &option) ||
2032 option > USHRT_MAX) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002033 cifs_dbg(VFS, "%s: Invalid port value\n",
2034 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002035 goto cifs_parse_mount_err;
2036 }
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002037 port = (unsigned short)option;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002038 break;
Steve French563317e2019-09-08 23:22:02 -05002039 case Opt_min_enc_offload:
2040 if (get_option_ul(args, &option)) {
2041 cifs_dbg(VFS, "Invalid minimum encrypted read offload size (esize)\n");
2042 goto cifs_parse_mount_err;
2043 }
2044 vol->min_offload = option;
2045 break;
Steve Frenche8506d22019-02-28 21:32:15 -06002046 case Opt_blocksize:
2047 if (get_option_ul(args, &option)) {
2048 cifs_dbg(VFS, "%s: Invalid blocksize value\n",
2049 __func__);
2050 goto cifs_parse_mount_err;
2051 }
2052 /*
2053 * inode blocksize realistically should never need to be
2054 * less than 16K or greater than 16M and default is 1MB.
2055 * Note that small inode block sizes (e.g. 64K) can lead
2056 * to very poor performance of common tools like cp and scp
2057 */
2058 if ((option < CIFS_MAX_MSGSIZE) ||
2059 (option > (4 * SMB3_DEFAULT_IOSIZE))) {
2060 cifs_dbg(VFS, "%s: Invalid blocksize\n",
2061 __func__);
2062 goto cifs_parse_mount_err;
2063 }
2064 vol->bsize = option;
2065 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002066 case Opt_rsize:
2067 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002068 cifs_dbg(VFS, "%s: Invalid rsize value\n",
2069 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002070 goto cifs_parse_mount_err;
2071 }
2072 vol->rsize = option;
2073 break;
2074 case Opt_wsize:
2075 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002076 cifs_dbg(VFS, "%s: Invalid wsize value\n",
2077 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002078 goto cifs_parse_mount_err;
2079 }
2080 vol->wsize = option;
2081 break;
2082 case Opt_actimeo:
2083 if (get_option_ul(args, &option)) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002084 cifs_dbg(VFS, "%s: Invalid actimeo value\n",
2085 __func__);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002086 goto cifs_parse_mount_err;
2087 }
2088 vol->actimeo = HZ * option;
2089 if (vol->actimeo > CIFS_MAX_ACTIMEO) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002090 cifs_dbg(VFS, "attribute cache timeout too large\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002091 goto cifs_parse_mount_err;
2092 }
2093 break;
Steve Frenchca567eb2019-03-29 16:31:07 -05002094 case Opt_handletimeout:
2095 if (get_option_ul(args, &option)) {
2096 cifs_dbg(VFS, "%s: Invalid handletimeout value\n",
2097 __func__);
2098 goto cifs_parse_mount_err;
2099 }
2100 vol->handle_timeout = option;
2101 if (vol->handle_timeout > SMB3_MAX_HANDLE_TIMEOUT) {
2102 cifs_dbg(VFS, "Invalid handle cache timeout, longer than 16 minutes\n");
2103 goto cifs_parse_mount_err;
2104 }
2105 break;
Steve Frenchadfeb3e2015-12-18 12:31:36 -06002106 case Opt_echo_interval:
2107 if (get_option_ul(args, &option)) {
2108 cifs_dbg(VFS, "%s: Invalid echo interval value\n",
2109 __func__);
2110 goto cifs_parse_mount_err;
2111 }
2112 vol->echo_interval = option;
2113 break;
Steve French8b217fe2016-11-11 22:36:20 -06002114 case Opt_snapshot:
2115 if (get_option_ul(args, &option)) {
2116 cifs_dbg(VFS, "%s: Invalid snapshot time\n",
2117 __func__);
2118 goto cifs_parse_mount_err;
2119 }
2120 vol->snapshot_time = option;
2121 break;
Steve French141891f2016-09-23 00:44:16 -05002122 case Opt_max_credits:
2123 if (get_option_ul(args, &option) || (option < 20) ||
2124 (option > 60000)) {
2125 cifs_dbg(VFS, "%s: Invalid max_credits value\n",
2126 __func__);
2127 goto cifs_parse_mount_err;
2128 }
2129 vol->max_credits = option;
2130 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002131
2132 /* String Arguments */
2133
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01002134 case Opt_blank_user:
2135 /* null user, ie. anonymous authentication */
2136 vol->nullauth = 1;
2137 vol->username = NULL;
2138 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002139 case Opt_user:
2140 string = match_strdup(args);
2141 if (string == NULL)
2142 goto out_nomem;
2143
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04002144 if (strnlen(string, CIFS_MAX_USERNAME_LEN) >
2145 CIFS_MAX_USERNAME_LEN) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002146 pr_warn("CIFS: username too long\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002147 goto cifs_parse_mount_err;
2148 }
Taesoo Kim2bd50fb2015-03-21 19:08:30 -04002149
2150 kfree(vol->username);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002151 vol->username = kstrdup(string, GFP_KERNEL);
Joe Perchesf96637b2013-05-04 22:12:25 -05002152 if (!vol->username)
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002153 goto cifs_parse_mount_err;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002154 break;
2155 case Opt_blank_pass:
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002156 /* passwords have to be handled differently
2157 * to allow the character used for deliminator
2158 * to be passed within them
2159 */
2160
Sachin Prabhuc369c9a2013-04-09 18:17:41 +01002161 /*
2162 * Check if this is a case where the password
2163 * starts with a delimiter
2164 */
2165 tmp_end = strchr(data, '=');
2166 tmp_end++;
2167 if (!(tmp_end < end && tmp_end[1] == delim)) {
2168 /* No it is not. Set the password to NULL */
Aurelien Aptel97f4b722018-01-25 15:59:39 +01002169 kzfree(vol->password);
Sachin Prabhuc369c9a2013-04-09 18:17:41 +01002170 vol->password = NULL;
2171 break;
2172 }
Gustavo A. R. Silva07fa6012018-11-27 10:01:51 +11002173 /* Fallthrough - to Opt_pass below.*/
Sachin Prabhuc369c9a2013-04-09 18:17:41 +01002174 case Opt_pass:
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002175 /* Obtain the value string */
2176 value = strchr(data, '=');
Sachin Prabhu10238072012-03-28 18:07:08 +01002177 value++;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002178
2179 /* Set tmp_end to end of the string */
2180 tmp_end = (char *) value + strlen(value);
2181
2182 /* Check if following character is the deliminator
2183 * If yes, we have encountered a double deliminator
2184 * reset the NULL character to the deliminator
2185 */
Suresh Jayaramane73f8432012-06-12 07:15:50 +05302186 if (tmp_end < end && tmp_end[1] == delim) {
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002187 tmp_end[0] = delim;
2188
Suresh Jayaramane73f8432012-06-12 07:15:50 +05302189 /* Keep iterating until we get to a single
2190 * deliminator OR the end
2191 */
2192 while ((tmp_end = strchr(tmp_end, delim))
2193 != NULL && (tmp_end[1] == delim)) {
2194 tmp_end = (char *) &tmp_end[2];
2195 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002196
Suresh Jayaramane73f8432012-06-12 07:15:50 +05302197 /* Reset var options to point to next element */
2198 if (tmp_end) {
2199 tmp_end[0] = '\0';
2200 options = (char *) &tmp_end[1];
2201 } else
2202 /* Reached the end of the mount option
2203 * string */
2204 options = end;
2205 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002206
Aurelien Aptel97f4b722018-01-25 15:59:39 +01002207 kzfree(vol->password);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002208 /* Now build new password string */
2209 temp_len = strlen(value);
2210 vol->password = kzalloc(temp_len+1, GFP_KERNEL);
2211 if (vol->password == NULL) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002212 pr_warn("CIFS: no memory for password\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002213 goto cifs_parse_mount_err;
2214 }
2215
2216 for (i = 0, j = 0; i < temp_len; i++, j++) {
2217 vol->password[j] = value[i];
2218 if ((value[i] == delim) &&
2219 value[i+1] == delim)
2220 /* skip the second deliminator */
2221 i++;
2222 }
2223 vol->password[j] = '\0';
2224 break;
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01002225 case Opt_blank_ip:
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002226 /* FIXME: should this be an error instead? */
2227 got_ip = false;
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01002228 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002229 case Opt_ip:
2230 string = match_strdup(args);
2231 if (string == NULL)
2232 goto out_nomem;
2233
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002234 if (!cifs_convert_address(dstaddr, string,
2235 strlen(string))) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002236 pr_err("CIFS: bad ip= option (%s).\n", string);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002237 goto cifs_parse_mount_err;
2238 }
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002239 got_ip = true;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002240 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002241 case Opt_domain:
2242 string = match_strdup(args);
2243 if (string == NULL)
2244 goto out_nomem;
2245
Chen Gang057d6332013-07-19 09:01:36 +08002246 if (strnlen(string, CIFS_MAX_DOMAINNAME_LEN)
2247 == CIFS_MAX_DOMAINNAME_LEN) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002248 pr_warn("CIFS: domain name too long\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002249 goto cifs_parse_mount_err;
2250 }
2251
Taesoo Kim2bd50fb2015-03-21 19:08:30 -04002252 kfree(vol->domainname);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002253 vol->domainname = kstrdup(string, GFP_KERNEL);
2254 if (!vol->domainname) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002255 pr_warn("CIFS: no memory for domainname\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002256 goto cifs_parse_mount_err;
2257 }
Joe Perchesf96637b2013-05-04 22:12:25 -05002258 cifs_dbg(FYI, "Domain name set\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002259 break;
2260 case Opt_srcaddr:
2261 string = match_strdup(args);
2262 if (string == NULL)
2263 goto out_nomem;
2264
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01002265 if (!cifs_convert_address(
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002266 (struct sockaddr *)&vol->srcaddr,
2267 string, strlen(string))) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002268 pr_warn("CIFS: Could not parse srcaddr: %s\n",
2269 string);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002270 goto cifs_parse_mount_err;
2271 }
2272 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002273 case Opt_iocharset:
2274 string = match_strdup(args);
2275 if (string == NULL)
2276 goto out_nomem;
2277
Sachin Prabhu4fe9e962012-04-10 18:12:27 +01002278 if (strnlen(string, 1024) >= 65) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002279 pr_warn("CIFS: iocharset name too long.\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002280 goto cifs_parse_mount_err;
2281 }
2282
Rasmus Villemoes87e747c2014-10-13 15:54:35 -07002283 if (strncasecmp(string, "default", 7) != 0) {
Taesoo Kim2bd50fb2015-03-21 19:08:30 -04002284 kfree(vol->iocharset);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002285 vol->iocharset = kstrdup(string,
2286 GFP_KERNEL);
2287 if (!vol->iocharset) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002288 pr_warn("CIFS: no memory for charset\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002289 goto cifs_parse_mount_err;
2290 }
2291 }
2292 /* if iocharset not set then load_nls_default
2293 * is used by caller
2294 */
Joe Perchesf96637b2013-05-04 22:12:25 -05002295 cifs_dbg(FYI, "iocharset set to %s\n", string);
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002296 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002297 case Opt_netbiosname:
2298 string = match_strdup(args);
2299 if (string == NULL)
2300 goto out_nomem;
2301
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002302 memset(vol->source_rfc1001_name, 0x20,
2303 RFC1001_NAME_LEN);
2304 /*
2305 * FIXME: are there cases in which a comma can
2306 * be valid in workstation netbios name (and
2307 * need special handling)?
2308 */
2309 for (i = 0; i < RFC1001_NAME_LEN; i++) {
2310 /* don't ucase netbiosname for user */
2311 if (string[i] == 0)
2312 break;
2313 vol->source_rfc1001_name[i] = string[i];
2314 }
2315 /* The string has 16th byte zero still from
2316 * set at top of the function
2317 */
2318 if (i == RFC1001_NAME_LEN && string[i] != 0)
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002319 pr_warn("CIFS: netbiosname longer than 15 truncated.\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002320 break;
2321 case Opt_servern:
2322 /* servernetbiosname specified override *SMBSERVER */
2323 string = match_strdup(args);
2324 if (string == NULL)
2325 goto out_nomem;
2326
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002327 /* last byte, type, is 0x20 for servr type */
2328 memset(vol->target_rfc1001_name, 0x20,
2329 RFC1001_NAME_LEN_WITH_NULL);
2330
2331 /* BB are there cases in which a comma can be
2332 valid in this workstation netbios name
2333 (and need special handling)? */
2334
2335 /* user or mount helper must uppercase the
2336 netbios name */
2337 for (i = 0; i < 15; i++) {
2338 if (string[i] == 0)
2339 break;
2340 vol->target_rfc1001_name[i] = string[i];
2341 }
2342 /* The string has 16th byte zero still from
2343 set at top of the function */
2344 if (i == RFC1001_NAME_LEN && string[i] != 0)
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002345 pr_warn("CIFS: server netbiosname longer than 15 truncated.\n");
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002346 break;
2347 case Opt_ver:
Steve French7e682f72017-08-31 21:34:24 -05002348 /* version of mount userspace tools, not dialect */
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002349 string = match_strdup(args);
2350 if (string == NULL)
2351 goto out_nomem;
2352
Steve French7e682f72017-08-31 21:34:24 -05002353 /* If interface changes in mount.cifs bump to new ver */
Rasmus Villemoes87e747c2014-10-13 15:54:35 -07002354 if (strncasecmp(string, "1", 1) == 0) {
Steve French7e682f72017-08-31 21:34:24 -05002355 if (strlen(string) > 1) {
2356 pr_warn("Bad mount helper ver=%s. Did "
2357 "you want SMB1 (CIFS) dialect "
2358 "and mean to type vers=1.0 "
2359 "instead?\n", string);
2360 goto cifs_parse_mount_err;
2361 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002362 /* This is the default */
2363 break;
2364 }
2365 /* For all other value, error */
Steve French7e682f72017-08-31 21:34:24 -05002366 pr_warn("CIFS: Invalid mount helper version specified\n");
Sean Finneyb9468452011-04-11 13:19:32 +00002367 goto cifs_parse_mount_err;
Jeff Layton23db65f2012-05-15 12:20:51 -04002368 case Opt_vers:
Steve French7e682f72017-08-31 21:34:24 -05002369 /* protocol version (dialect) */
Jeff Layton23db65f2012-05-15 12:20:51 -04002370 string = match_strdup(args);
2371 if (string == NULL)
2372 goto out_nomem;
2373
Steve Frenchc7c137b2018-06-06 17:59:29 -05002374 if (cifs_parse_smb_version(string, vol, is_smb3) != 0)
Jeff Layton23db65f2012-05-15 12:20:51 -04002375 goto cifs_parse_mount_err;
Steve French7e682f72017-08-31 21:34:24 -05002376 got_version = true;
Jeff Layton23db65f2012-05-15 12:20:51 -04002377 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002378 case Opt_sec:
2379 string = match_strdup(args);
2380 if (string == NULL)
2381 goto out_nomem;
2382
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002383 if (cifs_parse_security_flavors(string, vol) != 0)
2384 goto cifs_parse_mount_err;
2385 break;
Jeff Layton15b6a472012-05-16 07:50:15 -04002386 case Opt_cache:
2387 string = match_strdup(args);
2388 if (string == NULL)
2389 goto out_nomem;
2390
2391 if (cifs_parse_cache_flavor(string, vol) != 0)
2392 goto cifs_parse_mount_err;
2393 break;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002394 default:
Jeff Laytond8162552012-03-23 14:40:56 -04002395 /*
2396 * An option we don't recognize. Save it off for later
2397 * if we haven't already found one
2398 */
2399 if (!invalid)
2400 invalid = data;
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002401 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002402 }
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002403 /* Free up any allocated string */
2404 kfree(string);
2405 string = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002406 }
Jeff Layton0eb8a132010-10-06 19:51:12 -04002407
Jeff Laytond8162552012-03-23 14:40:56 -04002408 if (!sloppy && invalid) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002409 pr_err("CIFS: Unknown mount option \"%s\"\n", invalid);
Jeff Laytond8162552012-03-23 14:40:56 -04002410 goto cifs_parse_mount_err;
2411 }
2412
Long Li8339dd32017-11-07 01:54:55 -07002413 if (vol->rdma && vol->vals->protocol_id < SMB30_PROT_ID) {
2414 cifs_dbg(VFS, "SMB Direct requires Version >=3.0\n");
2415 goto cifs_parse_mount_err;
2416 }
2417
Jeff Layton8a8798a2012-01-17 16:09:15 -05002418#ifndef CONFIG_KEYS
2419 /* Muliuser mounts require CONFIG_KEYS support */
2420 if (vol->multiuser) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002421 cifs_dbg(VFS, "Multiuser mounts require kernels with CONFIG_KEYS enabled\n");
Sean Finneyb9468452011-04-11 13:19:32 +00002422 goto cifs_parse_mount_err;
Jeff Layton0eb8a132010-10-06 19:51:12 -04002423 }
Jeff Layton8a8798a2012-01-17 16:09:15 -05002424#endif
Jeff Laytone5e69ab2012-11-25 08:00:42 -05002425 if (!vol->UNC) {
Jeff Layton37d4f992013-05-24 07:40:05 -04002426 cifs_dbg(VFS, "CIFS mount error: No usable UNC path provided in device string!\n");
Jeff Laytone5e69ab2012-11-25 08:00:42 -05002427 goto cifs_parse_mount_err;
2428 }
Jeff Layton0eb8a132010-10-06 19:51:12 -04002429
Jeff Layton62a1a432012-12-10 06:10:45 -05002430 /* make sure UNC has a share name */
2431 if (!strchr(vol->UNC + 3, '\\')) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002432 cifs_dbg(VFS, "Malformed UNC. Unable to find share name.\n");
Jeff Layton62a1a432012-12-10 06:10:45 -05002433 goto cifs_parse_mount_err;
2434 }
2435
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002436 if (!got_ip) {
Daniel N Pettersson29bb3152017-04-27 11:32:36 +02002437 int len;
2438 const char *slash;
2439
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002440 /* No ip= option specified? Try to get it from UNC */
Daniel N Pettersson29bb3152017-04-27 11:32:36 +02002441 /* Use the address part of the UNC. */
2442 slash = strchr(&vol->UNC[2], '\\');
2443 len = slash - &vol->UNC[2];
2444 if (!cifs_convert_address(dstaddr, &vol->UNC[2], len)) {
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002445 pr_err("Unable to determine destination address.\n");
Jeff Laytonb979aaa2012-11-26 11:09:55 -05002446 goto cifs_parse_mount_err;
2447 }
2448 }
2449
2450 /* set the port that we got earlier */
2451 cifs_set_port(dstaddr, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002452
Jeff Layton9b9d6b242009-07-31 06:56:09 -04002453 if (uid_specified)
2454 vol->override_uid = override_uid;
2455 else if (override_uid == 1)
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002456 pr_notice("CIFS: ignoring forceuid mount option specified with no uid= option.\n");
Jeff Layton9b9d6b242009-07-31 06:56:09 -04002457
2458 if (gid_specified)
2459 vol->override_gid = override_gid;
2460 else if (override_gid == 1)
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002461 pr_notice("CIFS: ignoring forcegid mount option specified with no gid= option.\n");
Jeff Layton9b9d6b242009-07-31 06:56:09 -04002462
Steve French7e682f72017-08-31 21:34:24 -05002463 if (got_version == false)
2464 pr_warn("No dialect specified on mount. Default has changed to "
Steve French9764c022017-09-17 10:41:35 -05002465 "a more secure dialect, SMB2.1 or later (e.g. SMB3), from CIFS "
Steve French7e682f72017-08-31 21:34:24 -05002466 "(SMB1). To use the less secure SMB1 dialect to access "
Steve French9764c022017-09-17 10:41:35 -05002467 "old servers which do not support SMB3 (or SMB2.1) specify vers=1.0"
2468 " on mount.\n");
Steve French7e682f72017-08-31 21:34:24 -05002469
Sean Finneyb9468452011-04-11 13:19:32 +00002470 kfree(mountdata_copy);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002471 return 0;
Sean Finneyb9468452011-04-11 13:19:32 +00002472
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002473out_nomem:
Andy Shevchenko0b456f02014-08-27 16:49:44 +03002474 pr_warn("Could not allocate temporary buffer\n");
Sean Finneyb9468452011-04-11 13:19:32 +00002475cifs_parse_mount_err:
Sachin Prabhu8830d7e2012-03-23 14:40:56 -04002476 kfree(string);
Sean Finneyb9468452011-04-11 13:19:32 +00002477 kfree(mountdata_copy);
2478 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002479}
2480
Ben Greear3eb9a882010-09-01 17:06:02 -07002481/** Returns true if srcaddr isn't specified and rhs isn't
2482 * specified, or if srcaddr is specified and
2483 * matches the IP address of the rhs argument.
2484 */
Jeff Layton45151482010-07-06 20:43:02 -04002485static bool
Ben Greear3eb9a882010-09-01 17:06:02 -07002486srcip_matches(struct sockaddr *srcaddr, struct sockaddr *rhs)
2487{
2488 switch (srcaddr->sa_family) {
2489 case AF_UNSPEC:
2490 return (rhs->sa_family == AF_UNSPEC);
2491 case AF_INET: {
2492 struct sockaddr_in *saddr4 = (struct sockaddr_in *)srcaddr;
2493 struct sockaddr_in *vaddr4 = (struct sockaddr_in *)rhs;
2494 return (saddr4->sin_addr.s_addr == vaddr4->sin_addr.s_addr);
2495 }
2496 case AF_INET6: {
2497 struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)srcaddr;
Nickolai Zeldoviche3e27752013-01-16 21:36:17 -05002498 struct sockaddr_in6 *vaddr6 = (struct sockaddr_in6 *)rhs;
Ben Greear3eb9a882010-09-01 17:06:02 -07002499 return ipv6_addr_equal(&saddr6->sin6_addr, &vaddr6->sin6_addr);
2500 }
2501 default:
2502 WARN_ON(1);
2503 return false; /* don't expect to be here */
2504 }
2505}
2506
Pavel Shilovsky4b886132010-12-13 22:18:07 +03002507/*
2508 * If no port is specified in addr structure, we try to match with 445 port
2509 * and if it fails - with 139 ports. It should be called only if address
2510 * families of server and addr are equal.
2511 */
2512static bool
2513match_port(struct TCP_Server_Info *server, struct sockaddr *addr)
2514{
Steve French6da97912011-03-13 18:55:55 +00002515 __be16 port, *sport;
Pavel Shilovsky4b886132010-12-13 22:18:07 +03002516
Long Li3b249112019-05-15 14:09:04 -07002517 /* SMBDirect manages its own ports, don't match it here */
2518 if (server->rdma)
2519 return true;
2520
Pavel Shilovsky4b886132010-12-13 22:18:07 +03002521 switch (addr->sa_family) {
2522 case AF_INET:
2523 sport = &((struct sockaddr_in *) &server->dstaddr)->sin_port;
2524 port = ((struct sockaddr_in *) addr)->sin_port;
2525 break;
2526 case AF_INET6:
2527 sport = &((struct sockaddr_in6 *) &server->dstaddr)->sin6_port;
2528 port = ((struct sockaddr_in6 *) addr)->sin6_port;
2529 break;
2530 default:
2531 WARN_ON(1);
2532 return false;
2533 }
2534
2535 if (!port) {
2536 port = htons(CIFS_PORT);
2537 if (port == *sport)
2538 return true;
2539
2540 port = htons(RFC1001_PORT);
2541 }
2542
2543 return port == *sport;
2544}
Ben Greear3eb9a882010-09-01 17:06:02 -07002545
2546static bool
2547match_address(struct TCP_Server_Info *server, struct sockaddr *addr,
2548 struct sockaddr *srcaddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002549{
Jeff Layton45151482010-07-06 20:43:02 -04002550 switch (addr->sa_family) {
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002551 case AF_INET: {
2552 struct sockaddr_in *addr4 = (struct sockaddr_in *)addr;
2553 struct sockaddr_in *srv_addr4 =
2554 (struct sockaddr_in *)&server->dstaddr;
2555
2556 if (addr4->sin_addr.s_addr != srv_addr4->sin_addr.s_addr)
Jeff Layton45151482010-07-06 20:43:02 -04002557 return false;
Jeff Layton45151482010-07-06 20:43:02 -04002558 break;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002559 }
2560 case AF_INET6: {
2561 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
2562 struct sockaddr_in6 *srv_addr6 =
2563 (struct sockaddr_in6 *)&server->dstaddr;
2564
Jeff Layton45151482010-07-06 20:43:02 -04002565 if (!ipv6_addr_equal(&addr6->sin6_addr,
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002566 &srv_addr6->sin6_addr))
Jeff Layton45151482010-07-06 20:43:02 -04002567 return false;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002568 if (addr6->sin6_scope_id != srv_addr6->sin6_scope_id)
Jeff Layton45151482010-07-06 20:43:02 -04002569 return false;
Jeff Layton45151482010-07-06 20:43:02 -04002570 break;
2571 }
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002572 default:
2573 WARN_ON(1);
2574 return false; /* don't expect to be here */
2575 }
Jeff Layton45151482010-07-06 20:43:02 -04002576
Ben Greear3eb9a882010-09-01 17:06:02 -07002577 if (!srcip_matches(srcaddr, (struct sockaddr *)&server->srcaddr))
2578 return false;
2579
Jeff Layton45151482010-07-06 20:43:02 -04002580 return true;
2581}
2582
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002583static bool
2584match_security(struct TCP_Server_Info *server, struct smb_vol *vol)
2585{
Jeff Layton3f618222013-06-12 19:52:14 -05002586 /*
2587 * The select_sectype function should either return the vol->sectype
2588 * that was specified, or "Unspecified" if that sectype was not
2589 * compatible with the given NEGOTIATE request.
2590 */
Sachin Prabhuef65aae2017-01-18 15:35:57 +05302591 if (server->ops->select_sectype(server, vol->sectype)
2592 == Unspecified)
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002593 return false;
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002594
Jeff Layton3f618222013-06-12 19:52:14 -05002595 /*
2596 * Now check if signing mode is acceptable. No need to check
2597 * global_secflags at this point since if MUST_SIGN is set then
2598 * the server->sign had better be too.
2599 */
Jeff Layton38d77c52013-05-26 07:01:00 -04002600 if (vol->sign && !server->sign)
2601 return false;
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002602
2603 return true;
2604}
2605
Jeff Layton9fa114f2012-11-26 11:09:57 -05002606static int match_server(struct TCP_Server_Info *server, struct smb_vol *vol)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002607{
Jeff Layton9fa114f2012-11-26 11:09:57 -05002608 struct sockaddr *addr = (struct sockaddr *)&vol->dstaddr;
2609
Jeff Laytona0b3df52013-05-24 07:40:59 -04002610 if (vol->nosharesock)
2611 return 0;
2612
Steve French43cdae82019-06-13 14:26:49 -05002613 /* If multidialect negotiation see if existing sessions match one */
2614 if (strcmp(vol->vals->version_string, SMB3ANY_VERSION_STRING) == 0) {
2615 if (server->vals->protocol_id < SMB30_PROT_ID)
2616 return 0;
2617 } else if (strcmp(vol->vals->version_string,
2618 SMBDEFAULT_VERSION_STRING) == 0) {
2619 if (server->vals->protocol_id < SMB21_PROT_ID)
2620 return 0;
2621 } else if ((server->vals != vol->vals) || (server->ops != vol->ops))
Jeff Layton23db65f2012-05-15 12:20:51 -04002622 return 0;
2623
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002624 if (!net_eq(cifs_net_ns(server), current->nsproxy->net_ns))
2625 return 0;
2626
2627 if (!match_address(server, addr,
2628 (struct sockaddr *)&vol->srcaddr))
2629 return 0;
2630
2631 if (!match_port(server, addr))
2632 return 0;
2633
2634 if (!match_security(server, vol))
2635 return 0;
2636
Rabin Vincentb782fcc2016-07-19 09:25:45 +02002637 if (server->echo_interval != vol->echo_interval * HZ)
Steve Frenchadfeb3e2015-12-18 12:31:36 -06002638 return 0;
2639
Long Li8339dd32017-11-07 01:54:55 -07002640 if (server->rdma != vol->rdma)
2641 return 0;
2642
Steve French4f5c10f2019-09-03 21:18:49 -05002643 if (server->ignore_signature != vol->ignore_signature)
2644 return 0;
2645
Steve French563317e2019-09-08 23:22:02 -05002646 if (server->min_offload != vol->min_offload)
2647 return 0;
2648
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002649 return 1;
2650}
2651
Paulo Alcantara54be1f62018-11-14 16:01:21 -02002652struct TCP_Server_Info *
Jeff Layton9fa114f2012-11-26 11:09:57 -05002653cifs_find_tcp_session(struct smb_vol *vol)
Jeff Layton45151482010-07-06 20:43:02 -04002654{
Jeff Laytone7ddee92008-11-14 13:44:38 -05002655 struct TCP_Server_Info *server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002656
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302657 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton45151482010-07-06 20:43:02 -04002658 list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
Jeff Layton9fa114f2012-11-26 11:09:57 -05002659 if (!match_server(server, vol))
Jeff Laytondaf5b0b2010-07-06 20:43:02 -04002660 continue;
2661
Jeff Laytone7ddee92008-11-14 13:44:38 -05002662 ++server->srv_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302663 spin_unlock(&cifs_tcp_ses_lock);
Joe Perchesf96637b2013-05-04 22:12:25 -05002664 cifs_dbg(FYI, "Existing tcp session with server found\n");
Jeff Laytone7ddee92008-11-14 13:44:38 -05002665 return server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002666 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302667 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002668 return NULL;
2669}
2670
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07002671void
2672cifs_put_tcp_session(struct TCP_Server_Info *server, int from_reconnect)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002673{
Steve Frencha5c3e1c2014-09-16 04:16:19 -05002674 struct task_struct *task;
2675
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302676 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002677 if (--server->srv_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302678 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002679 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002680 }
Steve Frenchdea570e02008-05-06 22:05:51 +00002681
Rob Landleyf1d0c992011-01-22 15:44:05 -06002682 put_net(cifs_net_ns(server));
2683
Jeff Laytone7ddee92008-11-14 13:44:38 -05002684 list_del_init(&server->tcp_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302685 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytone7ddee92008-11-14 13:44:38 -05002686
Jeff Laytonc74093b2011-01-11 07:24:23 -05002687 cancel_delayed_work_sync(&server->echo);
2688
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07002689 if (from_reconnect)
2690 /*
2691 * Avoid deadlock here: reconnect work calls
2692 * cifs_put_tcp_session() at its end. Need to be sure
2693 * that reconnect work does nothing with server pointer after
2694 * that step.
2695 */
2696 cancel_delayed_work(&server->reconnect);
2697 else
2698 cancel_delayed_work_sync(&server->reconnect);
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07002699
Jeff Laytone7ddee92008-11-14 13:44:38 -05002700 spin_lock(&GlobalMid_Lock);
2701 server->tcpStatus = CifsExiting;
2702 spin_unlock(&GlobalMid_Lock);
2703
Pavel Shilovsky026e93d2016-11-03 16:47:37 -07002704 cifs_crypto_secmech_release(server);
Suresh Jayaraman488f1d2d2010-07-05 18:12:15 +05302705 cifs_fscache_release_client_cookie(server);
2706
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05002707 kfree(server->session_key.response);
2708 server->session_key.response = NULL;
2709 server->session_key.len = 0;
Steve Frencha5c3e1c2014-09-16 04:16:19 -05002710
2711 task = xchg(&server->tsk, NULL);
2712 if (task)
Eric W. Biederman72abe3b2019-05-15 12:33:50 -05002713 send_sig(SIGKILL, task, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002714}
2715
Jeff Layton63c038c2008-12-01 18:41:46 -05002716static struct TCP_Server_Info *
2717cifs_get_tcp_session(struct smb_vol *volume_info)
2718{
2719 struct TCP_Server_Info *tcp_ses = NULL;
Jeff Layton63c038c2008-12-01 18:41:46 -05002720 int rc;
2721
Joe Perchesf96637b2013-05-04 22:12:25 -05002722 cifs_dbg(FYI, "UNC: %s\n", volume_info->UNC);
Jeff Layton63c038c2008-12-01 18:41:46 -05002723
2724 /* see if we already have a matching tcp_ses */
Jeff Layton9fa114f2012-11-26 11:09:57 -05002725 tcp_ses = cifs_find_tcp_session(volume_info);
Jeff Layton63c038c2008-12-01 18:41:46 -05002726 if (tcp_ses)
2727 return tcp_ses;
2728
2729 tcp_ses = kzalloc(sizeof(struct TCP_Server_Info), GFP_KERNEL);
2730 if (!tcp_ses) {
2731 rc = -ENOMEM;
2732 goto out_err;
2733 }
2734
Jeff Layton23db65f2012-05-15 12:20:51 -04002735 tcp_ses->ops = volume_info->ops;
2736 tcp_ses->vals = volume_info->vals;
Rob Landleyf1d0c992011-01-22 15:44:05 -06002737 cifs_set_net_ns(tcp_ses, get_net(current->nsproxy->net_ns));
Jeff Layton63c038c2008-12-01 18:41:46 -05002738 tcp_ses->hostname = extract_hostname(volume_info->UNC);
2739 if (IS_ERR(tcp_ses->hostname)) {
2740 rc = PTR_ERR(tcp_ses->hostname);
Shirish Pargaonkarf7c5445a2010-10-26 18:10:24 -05002741 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002742 }
2743
Paulo Alcantara (SUSE)8eecd1c2019-07-16 19:04:50 -03002744 tcp_ses->noblockcnt = volume_info->rootfs;
2745 tcp_ses->noblocksnd = volume_info->noblocksnd || volume_info->rootfs;
Jeff Layton63c038c2008-12-01 18:41:46 -05002746 tcp_ses->noautotune = volume_info->noautotune;
Steve French6a5fa2362010-01-01 01:28:43 +00002747 tcp_ses->tcp_nodelay = volume_info->sockopt_tcp_nodelay;
Long Li8339dd32017-11-07 01:54:55 -07002748 tcp_ses->rdma = volume_info->rdma;
Pavel Shilovskyfc40f9c2012-02-17 17:09:12 +03002749 tcp_ses->in_flight = 0;
Steve French1b63f182019-09-09 22:57:11 -05002750 tcp_ses->max_in_flight = 0;
Pavel Shilovsky2d86dbc2012-02-06 15:59:18 +04002751 tcp_ses->credits = 1;
Jeff Layton63c038c2008-12-01 18:41:46 -05002752 init_waitqueue_head(&tcp_ses->response_q);
2753 init_waitqueue_head(&tcp_ses->request_q);
2754 INIT_LIST_HEAD(&tcp_ses->pending_mid_q);
2755 mutex_init(&tcp_ses->srv_mutex);
2756 memcpy(tcp_ses->workstation_RFC1001_name,
2757 volume_info->source_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
2758 memcpy(tcp_ses->server_RFC1001_name,
2759 volume_info->target_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
Shirish Pargaonkar5d0d2882010-10-13 18:15:00 -05002760 tcp_ses->session_estab = false;
Jeff Layton63c038c2008-12-01 18:41:46 -05002761 tcp_ses->sequence_number = 0;
Pavel Shilovsky5b964852019-01-18 11:30:26 -08002762 tcp_ses->reconnect_instance = 1;
Steve Frenchfda35942011-01-20 18:06:34 +00002763 tcp_ses->lstrp = jiffies;
Steve French9fe5ff12019-06-24 20:39:04 -05002764 tcp_ses->compress_algorithm = cpu_to_le16(volume_info->compression);
Jeff Layton58fa0152012-05-01 17:41:16 -04002765 spin_lock_init(&tcp_ses->req_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002766 INIT_LIST_HEAD(&tcp_ses->tcp_ses_list);
2767 INIT_LIST_HEAD(&tcp_ses->smb_ses_list);
Jeff Laytonc74093b2011-01-11 07:24:23 -05002768 INIT_DELAYED_WORK(&tcp_ses->echo, cifs_echo_request);
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07002769 INIT_DELAYED_WORK(&tcp_ses->reconnect, smb2_reconnect_server);
2770 mutex_init(&tcp_ses->reconnect_mutex);
Jeff Layton9fa114f2012-11-26 11:09:57 -05002771 memcpy(&tcp_ses->srcaddr, &volume_info->srcaddr,
2772 sizeof(tcp_ses->srcaddr));
2773 memcpy(&tcp_ses->dstaddr, &volume_info->dstaddr,
2774 sizeof(tcp_ses->dstaddr));
Steve Frenchfa70b872016-09-22 00:39:34 -05002775 generate_random_uuid(tcp_ses->client_guid);
Jeff Layton63c038c2008-12-01 18:41:46 -05002776 /*
2777 * at this point we are the only ones with the pointer
2778 * to the struct since the kernel thread not created yet
2779 * no need to spinlock this init of tcpStatus or srv_count
2780 */
2781 tcp_ses->tcpStatus = CifsNew;
2782 ++tcp_ses->srv_count;
2783
Steve Frenchadfeb3e2015-12-18 12:31:36 -06002784 if (volume_info->echo_interval >= SMB_ECHO_INTERVAL_MIN &&
2785 volume_info->echo_interval <= SMB_ECHO_INTERVAL_MAX)
2786 tcp_ses->echo_interval = volume_info->echo_interval * HZ;
2787 else
2788 tcp_ses->echo_interval = SMB_ECHO_INTERVAL_DEFAULT * HZ;
Long Li2f894642017-11-22 17:38:34 -07002789 if (tcp_ses->rdma) {
2790#ifndef CONFIG_CIFS_SMB_DIRECT
2791 cifs_dbg(VFS, "CONFIG_CIFS_SMB_DIRECT is not enabled\n");
2792 rc = -ENOENT;
2793 goto out_err_crypto_release;
2794#endif
2795 tcp_ses->smbd_conn = smbd_get_connection(
2796 tcp_ses, (struct sockaddr *)&volume_info->dstaddr);
2797 if (tcp_ses->smbd_conn) {
2798 cifs_dbg(VFS, "RDMA transport established\n");
2799 rc = 0;
2800 goto smbd_connected;
2801 } else {
2802 rc = -ENOENT;
2803 goto out_err_crypto_release;
2804 }
2805 }
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03002806 rc = ip_connect(tcp_ses);
Jeff Layton63c038c2008-12-01 18:41:46 -05002807 if (rc < 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05002808 cifs_dbg(VFS, "Error connecting to socket. Aborting operation.\n");
Shirish Pargaonkarf7c5445a2010-10-26 18:10:24 -05002809 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002810 }
Long Li2f894642017-11-22 17:38:34 -07002811smbd_connected:
Jeff Layton63c038c2008-12-01 18:41:46 -05002812 /*
2813 * since we're in a cifs function already, we know that
2814 * this will succeed. No need for try_module_get().
2815 */
2816 __module_get(THIS_MODULE);
Al Viro7c97c202011-06-21 08:51:28 -04002817 tcp_ses->tsk = kthread_run(cifs_demultiplex_thread,
Jeff Layton63c038c2008-12-01 18:41:46 -05002818 tcp_ses, "cifsd");
2819 if (IS_ERR(tcp_ses->tsk)) {
2820 rc = PTR_ERR(tcp_ses->tsk);
Joe Perchesf96637b2013-05-04 22:12:25 -05002821 cifs_dbg(VFS, "error %d create cifsd thread\n", rc);
Jeff Layton63c038c2008-12-01 18:41:46 -05002822 module_put(THIS_MODULE);
Shirish Pargaonkarf7c5445a2010-10-26 18:10:24 -05002823 goto out_err_crypto_release;
Jeff Layton63c038c2008-12-01 18:41:46 -05002824 }
Steve French563317e2019-09-08 23:22:02 -05002825 tcp_ses->min_offload = volume_info->min_offload;
Steve Frenchfd88ce92011-04-12 01:01:14 +00002826 tcp_ses->tcpStatus = CifsNeedNegotiate;
Jeff Layton63c038c2008-12-01 18:41:46 -05002827
Paulo Alcantara93d5cb52018-11-14 17:13:25 -02002828 tcp_ses->nr_targets = 1;
Steve French4f5c10f2019-09-03 21:18:49 -05002829 tcp_ses->ignore_signature = volume_info->ignore_signature;
Jeff Layton63c038c2008-12-01 18:41:46 -05002830 /* thread spawned, put it on the list */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302831 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002832 list_add(&tcp_ses->tcp_ses_list, &cifs_tcp_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302833 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton63c038c2008-12-01 18:41:46 -05002834
Suresh Jayaraman488f1d2d2010-07-05 18:12:15 +05302835 cifs_fscache_get_client_cookie(tcp_ses);
2836
Jeff Laytonc74093b2011-01-11 07:24:23 -05002837 /* queue echo request delayed work */
Steve Frenchadfeb3e2015-12-18 12:31:36 -06002838 queue_delayed_work(cifsiod_wq, &tcp_ses->echo, tcp_ses->echo_interval);
Jeff Laytonc74093b2011-01-11 07:24:23 -05002839
Jeff Layton63c038c2008-12-01 18:41:46 -05002840 return tcp_ses;
2841
Shirish Pargaonkarf7c5445a2010-10-26 18:10:24 -05002842out_err_crypto_release:
Pavel Shilovsky026e93d2016-11-03 16:47:37 -07002843 cifs_crypto_secmech_release(tcp_ses);
Shirish Pargaonkard2b91522010-10-21 14:25:08 -05002844
Rob Landleyf1d0c992011-01-22 15:44:05 -06002845 put_net(cifs_net_ns(tcp_ses));
2846
Jeff Layton63c038c2008-12-01 18:41:46 -05002847out_err:
2848 if (tcp_ses) {
Steve French8347a5c2009-10-06 18:31:29 +00002849 if (!IS_ERR(tcp_ses->hostname))
2850 kfree(tcp_ses->hostname);
Jeff Layton63c038c2008-12-01 18:41:46 -05002851 if (tcp_ses->ssocket)
2852 sock_release(tcp_ses->ssocket);
2853 kfree(tcp_ses);
2854 }
2855 return ERR_PTR(rc);
2856}
2857
Steve French96daf2b2011-05-27 04:34:02 +00002858static int match_session(struct cifs_ses *ses, struct smb_vol *vol)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002859{
Jeff Layton3f618222013-06-12 19:52:14 -05002860 if (vol->sectype != Unspecified &&
2861 vol->sectype != ses->sectype)
2862 return 0;
2863
2864 switch (ses->sectype) {
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002865 case Kerberos:
Eric W. Biederman64ed39d2013-02-06 02:30:39 -08002866 if (!uid_eq(vol->cred_uid, ses->cred_uid))
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002867 return 0;
2868 break;
2869 default:
Jeff Layton04febab2012-01-17 16:09:15 -05002870 /* NULL username means anonymous session */
2871 if (ses->user_name == NULL) {
2872 if (!vol->nullauth)
2873 return 0;
2874 break;
2875 }
2876
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002877 /* anything else takes username/password */
Jeff Layton04febab2012-01-17 16:09:15 -05002878 if (strncmp(ses->user_name,
2879 vol->username ? vol->username : "",
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04002880 CIFS_MAX_USERNAME_LEN))
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002881 return 0;
Jeff Layton08b37d52014-05-23 06:53:10 -04002882 if ((vol->username && strlen(vol->username) != 0) &&
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002883 ses->password != NULL &&
2884 strncmp(ses->password,
2885 vol->password ? vol->password : "",
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04002886 CIFS_MAX_PASSWORD_LEN))
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002887 return 0;
2888 }
2889 return 1;
2890}
2891
Aurelien Aptelb327a712018-01-24 13:46:10 +01002892/**
2893 * cifs_setup_ipc - helper to setup the IPC tcon for the session
2894 *
2895 * A new IPC connection is made and stored in the session
2896 * tcon_ipc. The IPC tcon has the same lifetime as the session.
2897 */
2898static int
2899cifs_setup_ipc(struct cifs_ses *ses, struct smb_vol *volume_info)
2900{
2901 int rc = 0, xid;
2902 struct cifs_tcon *tcon;
2903 struct nls_table *nls_codepage;
2904 char unc[SERVER_NAME_LENGTH + sizeof("//x/IPC$")] = {0};
2905 bool seal = false;
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10002906 struct TCP_Server_Info *server = ses->server;
Aurelien Aptelb327a712018-01-24 13:46:10 +01002907
2908 /*
2909 * If the mount request that resulted in the creation of the
2910 * session requires encryption, force IPC to be encrypted too.
2911 */
2912 if (volume_info->seal) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10002913 if (server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION)
Aurelien Aptelb327a712018-01-24 13:46:10 +01002914 seal = true;
2915 else {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10002916 cifs_server_dbg(VFS,
Aurelien Aptelb327a712018-01-24 13:46:10 +01002917 "IPC: server doesn't support encryption\n");
2918 return -EOPNOTSUPP;
2919 }
2920 }
2921
2922 tcon = tconInfoAlloc();
2923 if (tcon == NULL)
2924 return -ENOMEM;
2925
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10002926 scnprintf(unc, sizeof(unc), "\\\\%s\\IPC$", server->hostname);
Aurelien Aptelb327a712018-01-24 13:46:10 +01002927
2928 /* cannot fail */
2929 nls_codepage = load_nls_default();
2930
2931 xid = get_xid();
2932 tcon->ses = ses;
2933 tcon->ipc = true;
2934 tcon->seal = seal;
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10002935 rc = server->ops->tree_connect(xid, ses, unc, tcon, nls_codepage);
Aurelien Aptelb327a712018-01-24 13:46:10 +01002936 free_xid(xid);
2937
2938 if (rc) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10002939 cifs_server_dbg(VFS, "failed to connect to IPC (rc=%d)\n", rc);
Aurelien Aptelb327a712018-01-24 13:46:10 +01002940 tconInfoFree(tcon);
2941 goto out;
2942 }
2943
2944 cifs_dbg(FYI, "IPC tcon rc = %d ipc tid = %d\n", rc, tcon->tid);
2945
2946 ses->tcon_ipc = tcon;
2947out:
2948 unload_nls(nls_codepage);
2949 return rc;
2950}
2951
2952/**
2953 * cifs_free_ipc - helper to release the session IPC tcon
2954 *
2955 * Needs to be called everytime a session is destroyed
2956 */
2957static int
2958cifs_free_ipc(struct cifs_ses *ses)
2959{
2960 int rc = 0, xid;
2961 struct cifs_tcon *tcon = ses->tcon_ipc;
2962
2963 if (tcon == NULL)
2964 return 0;
2965
2966 if (ses->server->ops->tree_disconnect) {
2967 xid = get_xid();
2968 rc = ses->server->ops->tree_disconnect(xid, tcon);
2969 free_xid(xid);
2970 }
2971
2972 if (rc)
2973 cifs_dbg(FYI, "failed to disconnect IPC tcon (rc=%d)\n", rc);
2974
2975 tconInfoFree(tcon);
2976 ses->tcon_ipc = NULL;
2977 return rc;
2978}
2979
Steve French96daf2b2011-05-27 04:34:02 +00002980static struct cifs_ses *
Jeff Layton4ff67b72010-07-06 20:43:02 -04002981cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb_vol *vol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002982{
Steve French96daf2b2011-05-27 04:34:02 +00002983 struct cifs_ses *ses;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002984
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302985 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton4ff67b72010-07-06 20:43:02 -04002986 list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05002987 if (ses->status == CifsExiting)
2988 continue;
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00002989 if (!match_session(ses, vol))
2990 continue;
Jeff Layton14fbf502008-11-14 13:53:46 -05002991 ++ses->ses_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302992 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05002993 return ses;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002994 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05302995 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002996 return NULL;
2997}
2998
Paulo Alcantara (SUSE)50720102019-03-19 16:54:29 -03002999void cifs_put_smb_ses(struct cifs_ses *ses)
Jeff Layton14fbf502008-11-14 13:53:46 -05003000{
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05003001 unsigned int rc, xid;
Jeff Layton14fbf502008-11-14 13:53:46 -05003002 struct TCP_Server_Info *server = ses->server;
3003
Joe Perchesf96637b2013-05-04 22:12:25 -05003004 cifs_dbg(FYI, "%s: ses_count=%d\n", __func__, ses->ses_count);
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05003005
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303006 spin_lock(&cifs_tcp_ses_lock);
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05003007 if (ses->status == CifsExiting) {
3008 spin_unlock(&cifs_tcp_ses_lock);
3009 return;
3010 }
Jeff Layton14fbf502008-11-14 13:53:46 -05003011 if (--ses->ses_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303012 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05003013 return;
3014 }
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05003015 if (ses->status == CifsGood)
3016 ses->status = CifsExiting;
3017 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05003018
Aurelien Aptelb327a712018-01-24 13:46:10 +01003019 cifs_free_ipc(ses);
3020
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05003021 if (ses->status == CifsExiting && server->ops->logoff) {
3022 xid = get_xid();
3023 rc = server->ops->logoff(xid, ses);
3024 if (rc)
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10003025 cifs_server_dbg(VFS, "%s: Session Logoff failure rc=%d\n",
Shirish Pargaonkar7f485582013-10-12 10:06:03 -05003026 __func__, rc);
3027 _free_xid(xid);
3028 }
3029
3030 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05003031 list_del_init(&ses->smb_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303032 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton14fbf502008-11-14 13:53:46 -05003033
Jeff Layton14fbf502008-11-14 13:53:46 -05003034 sesInfoFree(ses);
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07003035 cifs_put_tcp_session(server, 0);
Jeff Layton14fbf502008-11-14 13:53:46 -05003036}
3037
Jeff Layton8a8798a2012-01-17 16:09:15 -05003038#ifdef CONFIG_KEYS
3039
Chen Gang057d6332013-07-19 09:01:36 +08003040/* strlen("cifs:a:") + CIFS_MAX_DOMAINNAME_LEN + 1 */
3041#define CIFSCREDS_DESC_SIZE (7 + CIFS_MAX_DOMAINNAME_LEN + 1)
Jeff Layton8a8798a2012-01-17 16:09:15 -05003042
3043/* Populate username and pw fields from keyring if possible */
3044static int
3045cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses)
3046{
3047 int rc = 0;
Ronnie Sahlbergf2aee322019-08-22 08:09:50 +10003048 int is_domain = 0;
David Howells146aa8b2015-10-21 14:04:48 +01003049 const char *delim, *payload;
3050 char *desc;
Jeff Layton8a8798a2012-01-17 16:09:15 -05003051 ssize_t len;
3052 struct key *key;
3053 struct TCP_Server_Info *server = ses->server;
3054 struct sockaddr_in *sa;
3055 struct sockaddr_in6 *sa6;
David Howells146aa8b2015-10-21 14:04:48 +01003056 const struct user_key_payload *upayload;
Jeff Layton8a8798a2012-01-17 16:09:15 -05003057
3058 desc = kmalloc(CIFSCREDS_DESC_SIZE, GFP_KERNEL);
3059 if (!desc)
3060 return -ENOMEM;
3061
3062 /* try to find an address key first */
3063 switch (server->dstaddr.ss_family) {
3064 case AF_INET:
3065 sa = (struct sockaddr_in *)&server->dstaddr;
3066 sprintf(desc, "cifs:a:%pI4", &sa->sin_addr.s_addr);
3067 break;
3068 case AF_INET6:
3069 sa6 = (struct sockaddr_in6 *)&server->dstaddr;
3070 sprintf(desc, "cifs:a:%pI6c", &sa6->sin6_addr.s6_addr);
3071 break;
3072 default:
Joe Perchesf96637b2013-05-04 22:12:25 -05003073 cifs_dbg(FYI, "Bad ss_family (%hu)\n",
3074 server->dstaddr.ss_family);
Jeff Layton8a8798a2012-01-17 16:09:15 -05003075 rc = -EINVAL;
3076 goto out_err;
3077 }
3078
Joe Perchesf96637b2013-05-04 22:12:25 -05003079 cifs_dbg(FYI, "%s: desc=%s\n", __func__, desc);
Linus Torvalds028db3e2019-07-10 18:43:43 -07003080 key = request_key(&key_type_logon, desc, "");
Jeff Layton8a8798a2012-01-17 16:09:15 -05003081 if (IS_ERR(key)) {
3082 if (!ses->domainName) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003083 cifs_dbg(FYI, "domainName is NULL\n");
Jeff Layton8a8798a2012-01-17 16:09:15 -05003084 rc = PTR_ERR(key);
3085 goto out_err;
3086 }
3087
3088 /* didn't work, try to find a domain key */
3089 sprintf(desc, "cifs:d:%s", ses->domainName);
Joe Perchesf96637b2013-05-04 22:12:25 -05003090 cifs_dbg(FYI, "%s: desc=%s\n", __func__, desc);
Linus Torvalds028db3e2019-07-10 18:43:43 -07003091 key = request_key(&key_type_logon, desc, "");
Jeff Layton8a8798a2012-01-17 16:09:15 -05003092 if (IS_ERR(key)) {
3093 rc = PTR_ERR(key);
3094 goto out_err;
3095 }
Ronnie Sahlbergf2aee322019-08-22 08:09:50 +10003096 is_domain = 1;
Jeff Layton8a8798a2012-01-17 16:09:15 -05003097 }
3098
3099 down_read(&key->sem);
David Howells0837e492017-03-01 15:11:23 +00003100 upayload = user_key_payload_locked(key);
Jeff Layton8a8798a2012-01-17 16:09:15 -05003101 if (IS_ERR_OR_NULL(upayload)) {
Jeff Layton4edc53c2012-02-07 06:30:51 -05003102 rc = upayload ? PTR_ERR(upayload) : -EINVAL;
Jeff Layton8a8798a2012-01-17 16:09:15 -05003103 goto out_key_put;
3104 }
3105
3106 /* find first : in payload */
David Howells146aa8b2015-10-21 14:04:48 +01003107 payload = upayload->data;
Jeff Layton8a8798a2012-01-17 16:09:15 -05003108 delim = strnchr(payload, upayload->datalen, ':');
Joe Perchesf96637b2013-05-04 22:12:25 -05003109 cifs_dbg(FYI, "payload=%s\n", payload);
Jeff Layton8a8798a2012-01-17 16:09:15 -05003110 if (!delim) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003111 cifs_dbg(FYI, "Unable to find ':' in payload (datalen=%d)\n",
3112 upayload->datalen);
Jeff Layton8a8798a2012-01-17 16:09:15 -05003113 rc = -EINVAL;
3114 goto out_key_put;
3115 }
3116
3117 len = delim - payload;
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04003118 if (len > CIFS_MAX_USERNAME_LEN || len <= 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003119 cifs_dbg(FYI, "Bad value from username search (len=%zd)\n",
3120 len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05003121 rc = -EINVAL;
3122 goto out_key_put;
3123 }
3124
3125 vol->username = kstrndup(payload, len, GFP_KERNEL);
3126 if (!vol->username) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003127 cifs_dbg(FYI, "Unable to allocate %zd bytes for username\n",
3128 len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05003129 rc = -ENOMEM;
3130 goto out_key_put;
3131 }
Joe Perchesf96637b2013-05-04 22:12:25 -05003132 cifs_dbg(FYI, "%s: username=%s\n", __func__, vol->username);
Jeff Layton8a8798a2012-01-17 16:09:15 -05003133
3134 len = key->datalen - (len + 1);
Scott Lovenberg8c3a2b42013-08-09 08:47:17 -04003135 if (len > CIFS_MAX_PASSWORD_LEN || len <= 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003136 cifs_dbg(FYI, "Bad len for password search (len=%zd)\n", len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05003137 rc = -EINVAL;
3138 kfree(vol->username);
3139 vol->username = NULL;
3140 goto out_key_put;
3141 }
3142
3143 ++delim;
3144 vol->password = kstrndup(delim, len, GFP_KERNEL);
3145 if (!vol->password) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003146 cifs_dbg(FYI, "Unable to allocate %zd bytes for password\n",
3147 len);
Jeff Layton8a8798a2012-01-17 16:09:15 -05003148 rc = -ENOMEM;
3149 kfree(vol->username);
3150 vol->username = NULL;
3151 goto out_key_put;
3152 }
3153
Ronnie Sahlbergf2aee322019-08-22 08:09:50 +10003154 /*
3155 * If we have a domain key then we must set the domainName in the
3156 * for the request.
3157 */
3158 if (is_domain && ses->domainName) {
3159 vol->domainname = kstrndup(ses->domainName,
3160 strlen(ses->domainName),
3161 GFP_KERNEL);
3162 if (!vol->domainname) {
3163 cifs_dbg(FYI, "Unable to allocate %zd bytes for "
3164 "domain\n", len);
3165 rc = -ENOMEM;
3166 kfree(vol->username);
3167 vol->username = NULL;
Dan Carpenter478228e2019-08-27 13:59:17 +03003168 kzfree(vol->password);
Ronnie Sahlbergf2aee322019-08-22 08:09:50 +10003169 vol->password = NULL;
3170 goto out_key_put;
3171 }
3172 }
3173
Jeff Layton8a8798a2012-01-17 16:09:15 -05003174out_key_put:
3175 up_read(&key->sem);
3176 key_put(key);
3177out_err:
3178 kfree(desc);
Joe Perchesf96637b2013-05-04 22:12:25 -05003179 cifs_dbg(FYI, "%s: returning %d\n", __func__, rc);
Jeff Layton8a8798a2012-01-17 16:09:15 -05003180 return rc;
3181}
3182#else /* ! CONFIG_KEYS */
3183static inline int
3184cifs_set_cifscreds(struct smb_vol *vol __attribute__((unused)),
3185 struct cifs_ses *ses __attribute__((unused)))
3186{
3187 return -ENOSYS;
3188}
3189#endif /* CONFIG_KEYS */
3190
Aurelien Aptel4a1360d2018-01-25 18:47:52 +01003191/**
3192 * cifs_get_smb_ses - get a session matching @volume_info data from @server
3193 *
3194 * This function assumes it is being called from cifs_mount() where we
3195 * already got a server reference (server refcount +1). See
3196 * cifs_get_tcon() for refcount explanations.
3197 */
Paulo Alcantara (SUSE)50720102019-03-19 16:54:29 -03003198struct cifs_ses *
Jeff Layton36988c72010-04-24 07:57:43 -04003199cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
3200{
Pavel Shilovsky286170a2012-05-25 10:43:58 +04003201 int rc = -ENOMEM;
3202 unsigned int xid;
Steve French96daf2b2011-05-27 04:34:02 +00003203 struct cifs_ses *ses;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003204 struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
3205 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
Jeff Layton36988c72010-04-24 07:57:43 -04003206
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003207 xid = get_xid();
Jeff Layton36988c72010-04-24 07:57:43 -04003208
Jeff Layton4ff67b72010-07-06 20:43:02 -04003209 ses = cifs_find_smb_ses(server, volume_info);
Jeff Layton36988c72010-04-24 07:57:43 -04003210 if (ses) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003211 cifs_dbg(FYI, "Existing smb sess found (status=%d)\n",
3212 ses->status);
Jeff Layton36988c72010-04-24 07:57:43 -04003213
Jeff Layton36988c72010-04-24 07:57:43 -04003214 mutex_lock(&ses->session_mutex);
Jeff Layton198b5682010-04-24 07:57:48 -04003215 rc = cifs_negotiate_protocol(xid, ses);
3216 if (rc) {
3217 mutex_unlock(&ses->session_mutex);
3218 /* problem -- put our ses reference */
3219 cifs_put_smb_ses(ses);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003220 free_xid(xid);
Jeff Layton198b5682010-04-24 07:57:48 -04003221 return ERR_PTR(rc);
3222 }
Jeff Layton36988c72010-04-24 07:57:43 -04003223 if (ses->need_reconnect) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003224 cifs_dbg(FYI, "Session needs reconnect\n");
Jeff Layton36988c72010-04-24 07:57:43 -04003225 rc = cifs_setup_session(xid, ses,
3226 volume_info->local_nls);
3227 if (rc) {
3228 mutex_unlock(&ses->session_mutex);
3229 /* problem -- put our reference */
3230 cifs_put_smb_ses(ses);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003231 free_xid(xid);
Jeff Layton36988c72010-04-24 07:57:43 -04003232 return ERR_PTR(rc);
3233 }
3234 }
3235 mutex_unlock(&ses->session_mutex);
Jeff Layton460cf342010-09-14 11:38:24 -04003236
3237 /* existing SMB ses has a server reference already */
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07003238 cifs_put_tcp_session(server, 0);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003239 free_xid(xid);
Jeff Layton36988c72010-04-24 07:57:43 -04003240 return ses;
3241 }
3242
Joe Perchesf96637b2013-05-04 22:12:25 -05003243 cifs_dbg(FYI, "Existing smb sess not found\n");
Jeff Layton36988c72010-04-24 07:57:43 -04003244 ses = sesInfoAlloc();
3245 if (ses == NULL)
3246 goto get_ses_fail;
3247
3248 /* new SMB session uses our server ref */
3249 ses->server = server;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003250 if (server->dstaddr.ss_family == AF_INET6)
3251 sprintf(ses->serverName, "%pI6", &addr6->sin6_addr);
Jeff Layton36988c72010-04-24 07:57:43 -04003252 else
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003253 sprintf(ses->serverName, "%pI4", &addr->sin_addr);
Jeff Layton36988c72010-04-24 07:57:43 -04003254
Steve French8727c8a2011-02-25 01:11:56 -06003255 if (volume_info->username) {
3256 ses->user_name = kstrdup(volume_info->username, GFP_KERNEL);
3257 if (!ses->user_name)
3258 goto get_ses_fail;
3259 }
Jeff Layton36988c72010-04-24 07:57:43 -04003260
3261 /* volume_info->password freed at unmount */
3262 if (volume_info->password) {
3263 ses->password = kstrdup(volume_info->password, GFP_KERNEL);
3264 if (!ses->password)
3265 goto get_ses_fail;
3266 }
3267 if (volume_info->domainname) {
Shirish Pargaonkard3686d52010-10-28 09:53:07 -05003268 ses->domainName = kstrdup(volume_info->domainname, GFP_KERNEL);
3269 if (!ses->domainName)
3270 goto get_ses_fail;
Jeff Layton36988c72010-04-24 07:57:43 -04003271 }
Germano Percossi39566442016-12-15 12:31:18 +05303272 if (volume_info->domainauto)
3273 ses->domainAuto = volume_info->domainauto;
Jeff Layton3e4b3e12010-07-19 18:00:17 -04003274 ses->cred_uid = volume_info->cred_uid;
Jeff Layton36988c72010-04-24 07:57:43 -04003275 ses->linux_uid = volume_info->linux_uid;
Steve Frenchd9b94202011-04-12 01:24:57 +00003276
Jeff Layton28e11bd2013-05-26 07:01:00 -04003277 ses->sectype = volume_info->sectype;
3278 ses->sign = volume_info->sign;
Jeff Layton36988c72010-04-24 07:57:43 -04003279 mutex_lock(&ses->session_mutex);
Jeff Layton198b5682010-04-24 07:57:48 -04003280 rc = cifs_negotiate_protocol(xid, ses);
3281 if (!rc)
3282 rc = cifs_setup_session(xid, ses, volume_info->local_nls);
Jeff Layton36988c72010-04-24 07:57:43 -04003283 mutex_unlock(&ses->session_mutex);
Steve Frenchc8e56f12010-09-08 21:10:58 +00003284 if (rc)
Jeff Layton36988c72010-04-24 07:57:43 -04003285 goto get_ses_fail;
3286
3287 /* success, put it on the list */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303288 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton36988c72010-04-24 07:57:43 -04003289 list_add(&ses->smb_ses_list, &server->smb_ses_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303290 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton36988c72010-04-24 07:57:43 -04003291
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003292 free_xid(xid);
Aurelien Aptelb327a712018-01-24 13:46:10 +01003293
3294 cifs_setup_ipc(ses, volume_info);
3295
Jeff Layton36988c72010-04-24 07:57:43 -04003296 return ses;
3297
3298get_ses_fail:
3299 sesInfoFree(ses);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003300 free_xid(xid);
Jeff Layton36988c72010-04-24 07:57:43 -04003301 return ERR_PTR(rc);
3302}
3303
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003304static int match_tcon(struct cifs_tcon *tcon, struct smb_vol *volume_info)
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00003305{
3306 if (tcon->tidStatus == CifsExiting)
3307 return 0;
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003308 if (strncmp(tcon->treeName, volume_info->UNC, MAX_TREE_SIZE))
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00003309 return 0;
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003310 if (tcon->seal != volume_info->seal)
3311 return 0;
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003312 if (tcon->snapshot_time != volume_info->snapshot_time)
3313 return 0;
Steve Frenchca567eb2019-03-29 16:31:07 -05003314 if (tcon->handle_timeout != volume_info->handle_timeout)
3315 return 0;
Steve French3e7a02d2019-09-11 21:46:20 -05003316 if (tcon->no_lease != volume_info->no_lease)
3317 return 0;
Pavel Shilovsky37bb04e2011-05-05 09:55:11 +00003318 return 1;
3319}
3320
Steve French96daf2b2011-05-27 04:34:02 +00003321static struct cifs_tcon *
Steve French8b217fe2016-11-11 22:36:20 -06003322cifs_find_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003323{
3324 struct list_head *tmp;
Steve French96daf2b2011-05-27 04:34:02 +00003325 struct cifs_tcon *tcon;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003326
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303327 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05003328 list_for_each(tmp, &ses->tcon_list) {
Steve French96daf2b2011-05-27 04:34:02 +00003329 tcon = list_entry(tmp, struct cifs_tcon, tcon_list);
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003330 if (!match_tcon(tcon, volume_info))
Jeff Laytonf1987b42008-11-15 11:12:47 -05003331 continue;
Jeff Laytonf1987b42008-11-15 11:12:47 -05003332 ++tcon->tc_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303333 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003334 return tcon;
3335 }
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303336 spin_unlock(&cifs_tcp_ses_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003337 return NULL;
3338}
3339
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07003340void
Steve French96daf2b2011-05-27 04:34:02 +00003341cifs_put_tcon(struct cifs_tcon *tcon)
Jeff Laytonf1987b42008-11-15 11:12:47 -05003342{
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003343 unsigned int xid;
Aurelien Aptelb327a712018-01-24 13:46:10 +01003344 struct cifs_ses *ses;
Jeff Laytonf1987b42008-11-15 11:12:47 -05003345
Aurelien Aptelb327a712018-01-24 13:46:10 +01003346 /*
3347 * IPC tcon share the lifetime of their session and are
3348 * destroyed in the session put function
3349 */
3350 if (tcon == NULL || tcon->ipc)
3351 return;
3352
3353 ses = tcon->ses;
Joe Perchesf96637b2013-05-04 22:12:25 -05003354 cifs_dbg(FYI, "%s: tc_count=%d\n", __func__, tcon->tc_count);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303355 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05003356 if (--tcon->tc_count > 0) {
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303357 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05003358 return;
3359 }
3360
3361 list_del_init(&tcon->tcon_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303362 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf1987b42008-11-15 11:12:47 -05003363
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003364 xid = get_xid();
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003365 if (ses->server->ops->tree_disconnect)
3366 ses->server->ops->tree_disconnect(xid, tcon);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003367 _free_xid(xid);
Jeff Laytonf1987b42008-11-15 11:12:47 -05003368
Suresh Jayaramand03382c2010-07-05 18:12:27 +05303369 cifs_fscache_release_super_cookie(tcon);
Steve French9f841592010-07-23 20:37:53 +00003370 tconInfoFree(tcon);
Jeff Laytonf1987b42008-11-15 11:12:47 -05003371 cifs_put_smb_ses(ses);
3372}
3373
Aurelien Aptel4a1360d2018-01-25 18:47:52 +01003374/**
3375 * cifs_get_tcon - get a tcon matching @volume_info data from @ses
3376 *
3377 * - tcon refcount is the number of mount points using the tcon.
3378 * - ses refcount is the number of tcon using the session.
3379 *
3380 * 1. This function assumes it is being called from cifs_mount() where
3381 * we already got a session reference (ses refcount +1).
3382 *
3383 * 2. Since we're in the context of adding a mount point, the end
3384 * result should be either:
3385 *
3386 * a) a new tcon already allocated with refcount=1 (1 mount point) and
3387 * its session refcount incremented (1 new tcon). This +1 was
3388 * already done in (1).
3389 *
3390 * b) an existing tcon with refcount+1 (add a mount point to it) and
3391 * identical ses refcount (no new tcon). Because of (1) we need to
3392 * decrement the ses refcount.
3393 */
Steve French96daf2b2011-05-27 04:34:02 +00003394static struct cifs_tcon *
3395cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
Jeff Laytond00c28d2010-04-24 07:57:44 -04003396{
3397 int rc, xid;
Steve French96daf2b2011-05-27 04:34:02 +00003398 struct cifs_tcon *tcon;
Jeff Laytond00c28d2010-04-24 07:57:44 -04003399
Steve French8b217fe2016-11-11 22:36:20 -06003400 tcon = cifs_find_tcon(ses, volume_info);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003401 if (tcon) {
Aurelien Aptel4a1360d2018-01-25 18:47:52 +01003402 /*
3403 * tcon has refcount already incremented but we need to
3404 * decrement extra ses reference gotten by caller (case b)
3405 */
Joe Perchesf96637b2013-05-04 22:12:25 -05003406 cifs_dbg(FYI, "Found match on UNC path\n");
Jeff Laytond00c28d2010-04-24 07:57:44 -04003407 cifs_put_smb_ses(ses);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003408 return tcon;
3409 }
3410
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003411 if (!ses->server->ops->tree_connect) {
3412 rc = -ENOSYS;
3413 goto out_fail;
3414 }
3415
Jeff Laytond00c28d2010-04-24 07:57:44 -04003416 tcon = tconInfoAlloc();
3417 if (tcon == NULL) {
3418 rc = -ENOMEM;
3419 goto out_fail;
3420 }
3421
Steve French8b217fe2016-11-11 22:36:20 -06003422 if (volume_info->snapshot_time) {
Steve French8b217fe2016-11-11 22:36:20 -06003423 if (ses->server->vals->protocol_id == 0) {
3424 cifs_dbg(VFS,
3425 "Use SMB2 or later for snapshot mount option\n");
3426 rc = -EOPNOTSUPP;
3427 goto out_fail;
3428 } else
3429 tcon->snapshot_time = volume_info->snapshot_time;
Steve French8b217fe2016-11-11 22:36:20 -06003430 }
3431
Steve Frenchca567eb2019-03-29 16:31:07 -05003432 if (volume_info->handle_timeout) {
3433 if (ses->server->vals->protocol_id == 0) {
3434 cifs_dbg(VFS,
3435 "Use SMB2.1 or later for handle timeout option\n");
3436 rc = -EOPNOTSUPP;
3437 goto out_fail;
3438 } else
3439 tcon->handle_timeout = volume_info->handle_timeout;
3440 }
3441
Jeff Laytond00c28d2010-04-24 07:57:44 -04003442 tcon->ses = ses;
3443 if (volume_info->password) {
3444 tcon->password = kstrdup(volume_info->password, GFP_KERNEL);
3445 if (!tcon->password) {
3446 rc = -ENOMEM;
3447 goto out_fail;
3448 }
3449 }
3450
Steve French23657ad2018-04-22 15:14:58 -05003451 if (volume_info->seal) {
3452 if (ses->server->vals->protocol_id == 0) {
3453 cifs_dbg(VFS,
3454 "SMB3 or later required for encryption\n");
3455 rc = -EOPNOTSUPP;
3456 goto out_fail;
3457 } else if (tcon->ses->server->capabilities &
3458 SMB2_GLOBAL_CAP_ENCRYPTION)
3459 tcon->seal = true;
3460 else {
3461 cifs_dbg(VFS, "Encryption is not supported on share\n");
3462 rc = -EOPNOTSUPP;
3463 goto out_fail;
3464 }
3465 }
3466
Steve French8505c8b2018-06-18 14:01:59 -05003467 if (volume_info->linux_ext) {
3468 if (ses->server->posix_ext_supported) {
Steve Frenchb3266142018-05-20 23:41:10 -05003469 tcon->posix_extensions = true;
Steve French2fbb5642018-06-12 12:11:31 -05003470 printk_once(KERN_WARNING
3471 "SMB3.11 POSIX Extensions are experimental\n");
Steve French8505c8b2018-06-18 14:01:59 -05003472 } else {
3473 cifs_dbg(VFS, "Server does not support mounting with posix SMB3.11 extensions.\n");
3474 rc = -EOPNOTSUPP;
3475 goto out_fail;
Steve French2fbb5642018-06-12 12:11:31 -05003476 }
Steve Frenchb3266142018-05-20 23:41:10 -05003477 }
Steve Frenchb3266142018-05-20 23:41:10 -05003478
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003479 /*
3480 * BB Do we need to wrap session_mutex around this TCon call and Unix
3481 * SetFS as we do on SessSetup and reconnect?
3482 */
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003483 xid = get_xid();
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003484 rc = ses->server->ops->tree_connect(xid, ses, volume_info->UNC, tcon,
3485 volume_info->local_nls);
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003486 free_xid(xid);
Joe Perchesf96637b2013-05-04 22:12:25 -05003487 cifs_dbg(FYI, "Tcon rc = %d\n", rc);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003488 if (rc)
3489 goto out_fail;
3490
Steve Frenchb618f002015-11-03 09:15:03 -06003491 tcon->use_persistent = false;
3492 /* check if SMB2 or later, CIFS does not support persistent handles */
3493 if (volume_info->persistent) {
3494 if (ses->server->vals->protocol_id == 0) {
3495 cifs_dbg(VFS,
3496 "SMB3 or later required for persistent handles\n");
3497 rc = -EOPNOTSUPP;
3498 goto out_fail;
3499 } else if (ses->server->capabilities &
3500 SMB2_GLOBAL_CAP_PERSISTENT_HANDLES)
3501 tcon->use_persistent = true;
3502 else /* persistent handles requested but not supported */ {
3503 cifs_dbg(VFS,
3504 "Persistent handles not supported on share\n");
3505 rc = -EOPNOTSUPP;
3506 goto out_fail;
3507 }
3508 } else if ((tcon->capabilities & SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY)
3509 && (ses->server->capabilities & SMB2_GLOBAL_CAP_PERSISTENT_HANDLES)
3510 && (volume_info->nopersistent == false)) {
3511 cifs_dbg(FYI, "enabling persistent handles\n");
3512 tcon->use_persistent = true;
Steve French592fafe2015-11-03 10:08:53 -06003513 } else if (volume_info->resilient) {
3514 if (ses->server->vals->protocol_id == 0) {
3515 cifs_dbg(VFS,
3516 "SMB2.1 or later required for resilient handles\n");
3517 rc = -EOPNOTSUPP;
3518 goto out_fail;
3519 }
3520 tcon->use_resilient = true;
Steve Frenchb618f002015-11-03 09:15:03 -06003521 }
3522
Steve Frenchcae53f72019-09-03 17:49:46 -05003523 /* If the user really knows what they are doing they can override */
3524 if (tcon->share_flags & SMB2_SHAREFLAG_NO_CACHING) {
3525 if (volume_info->cache_ro)
3526 cifs_dbg(VFS, "cache=ro requested on mount but NO_CACHING flag set on share\n");
3527 else if (volume_info->cache_rw)
3528 cifs_dbg(VFS, "cache=singleclient requested on mount but NO_CACHING flag set on share\n");
3529 }
3530
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04003531 /*
3532 * We can have only one retry value for a connection to a share so for
3533 * resources mounted more than once to the same server share the last
3534 * value passed in for the retry flag is used.
3535 */
Jeff Laytond00c28d2010-04-24 07:57:44 -04003536 tcon->retry = volume_info->retry;
3537 tcon->nocase = volume_info->nocase;
Steve French3d4ef9a2018-04-25 22:19:09 -05003538 tcon->nohandlecache = volume_info->nohandlecache;
Jeff Laytond00c28d2010-04-24 07:57:44 -04003539 tcon->local_lease = volume_info->local_lease;
Steve French3e7a02d2019-09-11 21:46:20 -05003540 tcon->no_lease = volume_info->no_lease;
Pavel Shilovsky233839b2012-09-19 06:22:45 -07003541 INIT_LIST_HEAD(&tcon->pending_opens);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003542
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303543 spin_lock(&cifs_tcp_ses_lock);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003544 list_add(&tcon->tcon_list, &ses->tcon_list);
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05303545 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytond00c28d2010-04-24 07:57:44 -04003546
Suresh Jayaramand03382c2010-07-05 18:12:27 +05303547 cifs_fscache_get_super_cookie(tcon);
3548
Jeff Laytond00c28d2010-04-24 07:57:44 -04003549 return tcon;
3550
3551out_fail:
3552 tconInfoFree(tcon);
3553 return ERR_PTR(rc);
3554}
3555
Jeff Layton9d002df2010-10-06 19:51:11 -04003556void
3557cifs_put_tlink(struct tcon_link *tlink)
3558{
3559 if (!tlink || IS_ERR(tlink))
3560 return;
3561
3562 if (!atomic_dec_and_test(&tlink->tl_count) ||
3563 test_bit(TCON_LINK_IN_TREE, &tlink->tl_flags)) {
3564 tlink->tl_time = jiffies;
3565 return;
3566 }
3567
3568 if (!IS_ERR(tlink_tcon(tlink)))
3569 cifs_put_tcon(tlink_tcon(tlink));
3570 kfree(tlink);
3571 return;
3572}
Jeff Laytond00c28d2010-04-24 07:57:44 -04003573
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003574static int
3575compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data)
3576{
3577 struct cifs_sb_info *old = CIFS_SB(sb);
3578 struct cifs_sb_info *new = mnt_data->cifs_sb;
Paulo Alcantara (SUSE)29fbeb72019-06-18 16:16:02 -03003579 unsigned int oldflags = old->mnt_cifs_flags & CIFS_MOUNT_MASK;
3580 unsigned int newflags = new->mnt_cifs_flags & CIFS_MOUNT_MASK;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003581
3582 if ((sb->s_flags & CIFS_MS_MASK) != (mnt_data->flags & CIFS_MS_MASK))
3583 return 0;
3584
Paulo Alcantara (SUSE)29fbeb72019-06-18 16:16:02 -03003585 if (old->mnt_cifs_serverino_autodisabled)
3586 newflags &= ~CIFS_MOUNT_SERVER_INUM;
3587
3588 if (oldflags != newflags)
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003589 return 0;
3590
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003591 /*
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003592 * We want to share sb only if we don't specify an r/wsize or
3593 * specified r/wsize is greater than or equal to existing one.
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003594 */
3595 if (new->wsize && new->wsize < old->wsize)
3596 return 0;
3597
Jeff Layton5eba8ab2011-10-19 15:30:26 -04003598 if (new->rsize && new->rsize < old->rsize)
3599 return 0;
3600
Eric W. Biederman1f682332013-02-06 01:20:20 -08003601 if (!uid_eq(old->mnt_uid, new->mnt_uid) || !gid_eq(old->mnt_gid, new->mnt_gid))
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003602 return 0;
3603
3604 if (old->mnt_file_mode != new->mnt_file_mode ||
3605 old->mnt_dir_mode != new->mnt_dir_mode)
3606 return 0;
3607
3608 if (strcmp(old->local_nls->charset, new->local_nls->charset))
3609 return 0;
3610
3611 if (old->actimeo != new->actimeo)
3612 return 0;
3613
3614 return 1;
3615}
3616
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01003617static int
3618match_prepath(struct super_block *sb, struct cifs_mnt_data *mnt_data)
3619{
3620 struct cifs_sb_info *old = CIFS_SB(sb);
3621 struct cifs_sb_info *new = mnt_data->cifs_sb;
Sachin Prabhucd8c4292017-04-26 14:05:46 +01003622 bool old_set = old->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH;
3623 bool new_set = new->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH;
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01003624
Sachin Prabhucd8c4292017-04-26 14:05:46 +01003625 if (old_set && new_set && !strcmp(new->prepath, old->prepath))
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01003626 return 1;
Sachin Prabhucd8c4292017-04-26 14:05:46 +01003627 else if (!old_set && !new_set)
3628 return 1;
3629
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01003630 return 0;
3631}
3632
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003633int
3634cifs_match_super(struct super_block *sb, void *data)
3635{
3636 struct cifs_mnt_data *mnt_data = (struct cifs_mnt_data *)data;
3637 struct smb_vol *volume_info;
3638 struct cifs_sb_info *cifs_sb;
3639 struct TCP_Server_Info *tcp_srv;
Steve French96daf2b2011-05-27 04:34:02 +00003640 struct cifs_ses *ses;
3641 struct cifs_tcon *tcon;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003642 struct tcon_link *tlink;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003643 int rc = 0;
3644
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003645 spin_lock(&cifs_tcp_ses_lock);
3646 cifs_sb = CIFS_SB(sb);
3647 tlink = cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
3648 if (IS_ERR(tlink)) {
3649 spin_unlock(&cifs_tcp_ses_lock);
3650 return rc;
3651 }
3652 tcon = tlink_tcon(tlink);
3653 ses = tcon->ses;
3654 tcp_srv = ses->server;
3655
3656 volume_info = mnt_data->vol;
3657
Jeff Layton9fa114f2012-11-26 11:09:57 -05003658 if (!match_server(tcp_srv, volume_info) ||
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003659 !match_session(ses, volume_info) ||
Pavel Shilovskyae6f8dd2016-11-17 13:59:23 -08003660 !match_tcon(tcon, volume_info) ||
Sachin Prabhuc1d8b242016-07-29 22:38:20 +01003661 !match_prepath(sb, mnt_data)) {
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003662 rc = 0;
3663 goto out;
3664 }
3665
3666 rc = compare_mount_options(sb, mnt_data);
3667out:
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003668 spin_unlock(&cifs_tcp_ses_lock);
Jeff Laytonf484b5d02011-07-11 10:16:34 -04003669 cifs_put_tlink(tlink);
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04003670 return rc;
3671}
3672
Jeff Layton09e50d52008-07-23 10:11:19 -04003673#ifdef CONFIG_DEBUG_LOCK_ALLOC
3674static struct lock_class_key cifs_key[2];
3675static struct lock_class_key cifs_slock_key[2];
3676
3677static inline void
3678cifs_reclassify_socket4(struct socket *sock)
3679{
3680 struct sock *sk = sock->sk;
Hannes Frederic Sowafafc4e12016-04-08 15:11:27 +02003681 BUG_ON(!sock_allow_reclassification(sk));
Jeff Layton09e50d52008-07-23 10:11:19 -04003682 sock_lock_init_class_and_name(sk, "slock-AF_INET-CIFS",
3683 &cifs_slock_key[0], "sk_lock-AF_INET-CIFS", &cifs_key[0]);
3684}
3685
3686static inline void
3687cifs_reclassify_socket6(struct socket *sock)
3688{
3689 struct sock *sk = sock->sk;
Hannes Frederic Sowafafc4e12016-04-08 15:11:27 +02003690 BUG_ON(!sock_allow_reclassification(sk));
Jeff Layton09e50d52008-07-23 10:11:19 -04003691 sock_lock_init_class_and_name(sk, "slock-AF_INET6-CIFS",
3692 &cifs_slock_key[1], "sk_lock-AF_INET6-CIFS", &cifs_key[1]);
3693}
3694#else
3695static inline void
3696cifs_reclassify_socket4(struct socket *sock)
3697{
3698}
3699
3700static inline void
3701cifs_reclassify_socket6(struct socket *sock)
3702{
3703}
3704#endif
3705
Linus Torvalds1da177e2005-04-16 15:20:36 -07003706/* See RFC1001 section 14 on representation of Netbios names */
Steve French50c2f752007-07-13 00:33:32 +00003707static void rfc1002mangle(char *target, char *source, unsigned int length)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003708{
Steve French50c2f752007-07-13 00:33:32 +00003709 unsigned int i, j;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003710
Steve French50c2f752007-07-13 00:33:32 +00003711 for (i = 0, j = 0; i < (length); i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003712 /* mask a nibble at a time and encode */
3713 target[j] = 'A' + (0x0F & (source[i] >> 4));
3714 target[j+1] = 'A' + (0x0F & source[i]);
Steve French50c2f752007-07-13 00:33:32 +00003715 j += 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003716 }
3717
3718}
3719
Ben Greear3eb9a882010-09-01 17:06:02 -07003720static int
3721bind_socket(struct TCP_Server_Info *server)
3722{
3723 int rc = 0;
3724 if (server->srcaddr.ss_family != AF_UNSPEC) {
3725 /* Bind to the specified local IP address */
3726 struct socket *socket = server->ssocket;
3727 rc = socket->ops->bind(socket,
3728 (struct sockaddr *) &server->srcaddr,
3729 sizeof(server->srcaddr));
3730 if (rc < 0) {
3731 struct sockaddr_in *saddr4;
3732 struct sockaddr_in6 *saddr6;
3733 saddr4 = (struct sockaddr_in *)&server->srcaddr;
3734 saddr6 = (struct sockaddr_in6 *)&server->srcaddr;
3735 if (saddr6->sin6_family == AF_INET6)
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10003736 cifs_server_dbg(VFS, "Failed to bind to: %pI6c, error: %d\n",
Joe Perchesf96637b2013-05-04 22:12:25 -05003737 &saddr6->sin6_addr, rc);
Ben Greear3eb9a882010-09-01 17:06:02 -07003738 else
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10003739 cifs_server_dbg(VFS, "Failed to bind to: %pI4, error: %d\n",
Joe Perchesf96637b2013-05-04 22:12:25 -05003740 &saddr4->sin_addr.s_addr, rc);
Ben Greear3eb9a882010-09-01 17:06:02 -07003741 }
3742 }
3743 return rc;
3744}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003745
3746static int
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003747ip_rfc1001_connect(struct TCP_Server_Info *server)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003748{
3749 int rc = 0;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003750 /*
3751 * some servers require RFC1001 sessinit before sending
3752 * negprot - BB check reconnection in case where second
3753 * sessinit is sent but no second negprot
3754 */
3755 struct rfc1002_session_packet *ses_init_buf;
3756 struct smb_hdr *smb_buf;
3757 ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet),
3758 GFP_KERNEL);
3759 if (ses_init_buf) {
3760 ses_init_buf->trailer.session_req.called_len = 32;
3761
Colin Ian King997152f2016-01-25 16:25:54 +00003762 if (server->server_RFC1001_name[0] != 0)
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003763 rfc1002mangle(ses_init_buf->trailer.
3764 session_req.called_name,
3765 server->server_RFC1001_name,
3766 RFC1001_NAME_LEN_WITH_NULL);
3767 else
3768 rfc1002mangle(ses_init_buf->trailer.
3769 session_req.called_name,
3770 DEFAULT_CIFS_CALLED_NAME,
3771 RFC1001_NAME_LEN_WITH_NULL);
3772
3773 ses_init_buf->trailer.session_req.calling_len = 32;
3774
3775 /*
3776 * calling name ends in null (byte 16) from old smb
3777 * convention.
3778 */
Steve Frenchc85c35f2015-03-27 01:15:02 -05003779 if (server->workstation_RFC1001_name[0] != 0)
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003780 rfc1002mangle(ses_init_buf->trailer.
3781 session_req.calling_name,
3782 server->workstation_RFC1001_name,
3783 RFC1001_NAME_LEN_WITH_NULL);
3784 else
3785 rfc1002mangle(ses_init_buf->trailer.
3786 session_req.calling_name,
3787 "LINUX_CIFS_CLNT",
3788 RFC1001_NAME_LEN_WITH_NULL);
3789
3790 ses_init_buf->trailer.session_req.scope1 = 0;
3791 ses_init_buf->trailer.session_req.scope2 = 0;
3792 smb_buf = (struct smb_hdr *)ses_init_buf;
3793
3794 /* sizeof RFC1002_SESSION_REQUEST with no scope */
Steve Frenchbe8e3b02011-04-29 05:40:20 +00003795 smb_buf->smb_buf_length = cpu_to_be32(0x81000044);
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003796 rc = smb_send(server, smb_buf, 0x44);
3797 kfree(ses_init_buf);
3798 /*
3799 * RFC1001 layer in at least one server
3800 * requires very short break before negprot
3801 * presumably because not expecting negprot
3802 * to follow so fast. This is a simple
3803 * solution that works without
3804 * complicating the code and causes no
3805 * significant slowing down on mount
3806 * for everyone else
3807 */
3808 usleep_range(1000, 2000);
3809 }
3810 /*
3811 * else the negprot may still work without this
3812 * even though malloc failed
3813 */
3814
3815 return rc;
3816}
3817
3818static int
3819generic_ip_connect(struct TCP_Server_Info *server)
3820{
3821 int rc = 0;
Steve French6da97912011-03-13 18:55:55 +00003822 __be16 sport;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003823 int slen, sfamily;
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003824 struct socket *socket = server->ssocket;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003825 struct sockaddr *saddr;
3826
3827 saddr = (struct sockaddr *) &server->dstaddr;
3828
3829 if (server->dstaddr.ss_family == AF_INET6) {
3830 sport = ((struct sockaddr_in6 *) saddr)->sin6_port;
3831 slen = sizeof(struct sockaddr_in6);
3832 sfamily = AF_INET6;
3833 } else {
3834 sport = ((struct sockaddr_in *) saddr)->sin_port;
3835 slen = sizeof(struct sockaddr_in);
3836 sfamily = AF_INET;
3837 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003838
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003839 if (socket == NULL) {
Rob Landleyf1d0c992011-01-22 15:44:05 -06003840 rc = __sock_create(cifs_net_ns(server), sfamily, SOCK_STREAM,
3841 IPPROTO_TCP, &socket, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003842 if (rc < 0) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10003843 cifs_server_dbg(VFS, "Error %d creating socket\n", rc);
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003844 server->ssocket = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003845 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003846 }
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003847
3848 /* BB other socket options to set KEEPALIVE, NODELAY? */
Joe Perchesf96637b2013-05-04 22:12:25 -05003849 cifs_dbg(FYI, "Socket created\n");
Jeff Laytonbcf4b102008-12-01 18:42:15 -05003850 server->ssocket = socket;
3851 socket->sk->sk_allocation = GFP_NOFS;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003852 if (sfamily == AF_INET6)
3853 cifs_reclassify_socket6(socket);
3854 else
3855 cifs_reclassify_socket4(socket);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003856 }
3857
Ben Greear3eb9a882010-09-01 17:06:02 -07003858 rc = bind_socket(server);
3859 if (rc < 0)
3860 return rc;
3861
Jeff Laytond5c56052008-12-01 18:42:33 -05003862 /*
3863 * Eventually check for other socket options to change from
3864 * the default. sock_setsockopt not used because it expects
3865 * user space buffer
3866 */
3867 socket->sk->sk_rcvtimeo = 7 * HZ;
Steve Frenchda505c32009-01-19 03:49:35 +00003868 socket->sk->sk_sndtimeo = 5 * HZ;
Steve French6a5fa2362010-01-01 01:28:43 +00003869
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003870 /* make the bufsizes depend on wsize/rsize and max requests */
3871 if (server->noautotune) {
3872 if (socket->sk->sk_sndbuf < (200 * 1024))
3873 socket->sk->sk_sndbuf = 200 * 1024;
3874 if (socket->sk->sk_rcvbuf < (140 * 1024))
3875 socket->sk->sk_rcvbuf = 140 * 1024;
3876 }
3877
Steve French6a5fa2362010-01-01 01:28:43 +00003878 if (server->tcp_nodelay) {
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003879 int val = 1;
Steve French6a5fa2362010-01-01 01:28:43 +00003880 rc = kernel_setsockopt(socket, SOL_TCP, TCP_NODELAY,
3881 (char *)&val, sizeof(val));
3882 if (rc)
Joe Perchesf96637b2013-05-04 22:12:25 -05003883 cifs_dbg(FYI, "set TCP_NODELAY socket option error %d\n",
3884 rc);
Steve French6a5fa2362010-01-01 01:28:43 +00003885 }
3886
Joe Perchesf96637b2013-05-04 22:12:25 -05003887 cifs_dbg(FYI, "sndbuf %d rcvbuf %d rcvtimeo 0x%lx\n",
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003888 socket->sk->sk_sndbuf,
3889 socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo);
3890
Paulo Alcantara (SUSE)8eecd1c2019-07-16 19:04:50 -03003891 rc = socket->ops->connect(socket, saddr, slen,
3892 server->noblockcnt ? O_NONBLOCK : 0);
Paulo Alcantara (SUSE)d532cc72019-10-10 12:31:58 -03003893 /*
3894 * When mounting SMB root file systems, we do not want to block in
3895 * connect. Otherwise bail out and then let cifs_reconnect() perform
3896 * reconnect failover - if possible.
3897 */
3898 if (server->noblockcnt && rc == -EINPROGRESS)
Paulo Alcantara (SUSE)8eecd1c2019-07-16 19:04:50 -03003899 rc = 0;
Jeff Laytonee1b3ea2011-06-21 07:18:26 -04003900 if (rc < 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003901 cifs_dbg(FYI, "Error %d connecting to server\n", rc);
Jeff Laytonee1b3ea2011-06-21 07:18:26 -04003902 sock_release(socket);
3903 server->ssocket = NULL;
3904 return rc;
3905 }
3906
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003907 if (sport == htons(RFC1001_PORT))
3908 rc = ip_rfc1001_connect(server);
Steve French50c2f752007-07-13 00:33:32 +00003909
Linus Torvalds1da177e2005-04-16 15:20:36 -07003910 return rc;
3911}
3912
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003913static int
3914ip_connect(struct TCP_Server_Info *server)
3915{
Steve French6da97912011-03-13 18:55:55 +00003916 __be16 *sport;
Pavel Shilovskya9f1b852010-12-13 19:08:35 +03003917 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
3918 struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
3919
3920 if (server->dstaddr.ss_family == AF_INET6)
3921 sport = &addr6->sin6_port;
3922 else
3923 sport = &addr->sin_port;
3924
3925 if (*sport == 0) {
3926 int rc;
3927
3928 /* try with 445 port at first */
3929 *sport = htons(CIFS_PORT);
3930
3931 rc = generic_ip_connect(server);
3932 if (rc >= 0)
3933 return rc;
3934
3935 /* if it failed, try with 139 port */
3936 *sport = htons(RFC1001_PORT);
3937 }
3938
3939 return generic_ip_connect(server);
3940}
3941
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04003942void reset_cifs_unix_caps(unsigned int xid, struct cifs_tcon *tcon,
Al Viro2c6292a2011-06-17 09:05:48 -04003943 struct cifs_sb_info *cifs_sb, struct smb_vol *vol_info)
Steve French8af18972007-02-14 04:42:51 +00003944{
3945 /* if we are reconnecting then should we check to see if
3946 * any requested capabilities changed locally e.g. via
3947 * remount but we can not do much about it here
3948 * if they have (even if we could detect it by the following)
3949 * Perhaps we could add a backpointer to array of sb from tcon
3950 * or if we change to make all sb to same share the same
3951 * sb as NFS - then we only have one backpointer to sb.
3952 * What if we wanted to mount the server share twice once with
3953 * and once without posixacls or posix paths? */
3954 __u64 saved_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
Steve French50c2f752007-07-13 00:33:32 +00003955
Steve Frenchc18c8422007-07-18 23:21:09 +00003956 if (vol_info && vol_info->no_linux_ext) {
3957 tcon->fsUnixInfo.Capability = 0;
3958 tcon->unix_ext = 0; /* Unix Extensions disabled */
Joe Perchesf96637b2013-05-04 22:12:25 -05003959 cifs_dbg(FYI, "Linux protocol extensions disabled\n");
Steve Frenchc18c8422007-07-18 23:21:09 +00003960 return;
3961 } else if (vol_info)
3962 tcon->unix_ext = 1; /* Unix Extensions supported */
3963
3964 if (tcon->unix_ext == 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003965 cifs_dbg(FYI, "Unix extensions disabled so not set on reconnect\n");
Steve Frenchc18c8422007-07-18 23:21:09 +00003966 return;
3967 }
Steve French50c2f752007-07-13 00:33:32 +00003968
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003969 if (!CIFSSMBQFSUnixInfo(xid, tcon)) {
Steve French8af18972007-02-14 04:42:51 +00003970 __u64 cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
Joe Perchesf96637b2013-05-04 22:12:25 -05003971 cifs_dbg(FYI, "unix caps which server supports %lld\n", cap);
Steve French8af18972007-02-14 04:42:51 +00003972 /* check for reconnect case in which we do not
3973 want to change the mount behavior if we can avoid it */
Steve Frenchfb8c4b12007-07-10 01:16:18 +00003974 if (vol_info == NULL) {
Steve French50c2f752007-07-13 00:33:32 +00003975 /* turn off POSIX ACL and PATHNAMES if not set
Steve French8af18972007-02-14 04:42:51 +00003976 originally at mount time */
3977 if ((saved_cap & CIFS_UNIX_POSIX_ACL_CAP) == 0)
3978 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
Igor Mammedov11b6d642008-02-15 19:06:04 +00003979 if ((saved_cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
3980 if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003981 cifs_dbg(VFS, "POSIXPATH support change\n");
Steve French8af18972007-02-14 04:42:51 +00003982 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
Igor Mammedov11b6d642008-02-15 19:06:04 +00003983 } else if ((cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003984 cifs_dbg(VFS, "possible reconnect error\n");
3985 cifs_dbg(VFS, "server disabled POSIX path support\n");
Igor Mammedov11b6d642008-02-15 19:06:04 +00003986 }
Steve French8af18972007-02-14 04:42:51 +00003987 }
Steve French50c2f752007-07-13 00:33:32 +00003988
Steve French6848b732011-05-26 18:38:54 +00003989 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05003990 cifs_dbg(VFS, "per-share encryption not supported yet\n");
Steve French6848b732011-05-26 18:38:54 +00003991
Steve French8af18972007-02-14 04:42:51 +00003992 cap &= CIFS_UNIX_CAP_MASK;
Steve French75865f8c2007-06-24 18:30:48 +00003993 if (vol_info && vol_info->no_psx_acl)
Steve French8af18972007-02-14 04:42:51 +00003994 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
Steve French75865f8c2007-06-24 18:30:48 +00003995 else if (CIFS_UNIX_POSIX_ACL_CAP & cap) {
Joe Perchesf96637b2013-05-04 22:12:25 -05003996 cifs_dbg(FYI, "negotiated posix acl support\n");
Al Viro2c6292a2011-06-17 09:05:48 -04003997 if (cifs_sb)
3998 cifs_sb->mnt_cifs_flags |=
3999 CIFS_MOUNT_POSIXACL;
Steve French8af18972007-02-14 04:42:51 +00004000 }
4001
Steve French75865f8c2007-06-24 18:30:48 +00004002 if (vol_info && vol_info->posix_paths == 0)
Steve French8af18972007-02-14 04:42:51 +00004003 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
Steve French75865f8c2007-06-24 18:30:48 +00004004 else if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
Joe Perchesf96637b2013-05-04 22:12:25 -05004005 cifs_dbg(FYI, "negotiate posix pathnames\n");
Al Viro2c6292a2011-06-17 09:05:48 -04004006 if (cifs_sb)
4007 cifs_sb->mnt_cifs_flags |=
Steve French8af18972007-02-14 04:42:51 +00004008 CIFS_MOUNT_POSIX_PATHS;
4009 }
Steve French50c2f752007-07-13 00:33:32 +00004010
Joe Perchesf96637b2013-05-04 22:12:25 -05004011 cifs_dbg(FYI, "Negotiate caps 0x%x\n", (int)cap);
Steve French8af18972007-02-14 04:42:51 +00004012#ifdef CONFIG_CIFS_DEBUG2
Steve French75865f8c2007-06-24 18:30:48 +00004013 if (cap & CIFS_UNIX_FCNTL_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004014 cifs_dbg(FYI, "FCNTL cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00004015 if (cap & CIFS_UNIX_EXTATTR_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004016 cifs_dbg(FYI, "EXTATTR cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00004017 if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004018 cifs_dbg(FYI, "POSIX path cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00004019 if (cap & CIFS_UNIX_XATTR_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004020 cifs_dbg(FYI, "XATTR cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00004021 if (cap & CIFS_UNIX_POSIX_ACL_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004022 cifs_dbg(FYI, "POSIX ACL cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00004023 if (cap & CIFS_UNIX_LARGE_READ_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004024 cifs_dbg(FYI, "very large read cap\n");
Steve French75865f8c2007-06-24 18:30:48 +00004025 if (cap & CIFS_UNIX_LARGE_WRITE_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004026 cifs_dbg(FYI, "very large write cap\n");
Steve French6848b732011-05-26 18:38:54 +00004027 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004028 cifs_dbg(FYI, "transport encryption cap\n");
Steve French6848b732011-05-26 18:38:54 +00004029 if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
Joe Perchesf96637b2013-05-04 22:12:25 -05004030 cifs_dbg(FYI, "mandatory transport encryption cap\n");
Steve French8af18972007-02-14 04:42:51 +00004031#endif /* CIFS_DEBUG2 */
4032 if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
Steve French442aa312007-09-24 20:25:46 +00004033 if (vol_info == NULL) {
Joe Perchesf96637b2013-05-04 22:12:25 -05004034 cifs_dbg(FYI, "resetting capabilities failed\n");
Steve French442aa312007-09-24 20:25:46 +00004035 } else
Joe Perchesf96637b2013-05-04 22:12:25 -05004036 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 +00004037
Steve French8af18972007-02-14 04:42:51 +00004038 }
4039 }
4040}
4041
Sachin Prabhu4214ebf2016-07-29 22:38:19 +01004042int cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004043 struct cifs_sb_info *cifs_sb)
Jeff Laytonb1c8d2b2008-10-22 13:57:07 -04004044{
Jeff Layton2de970f2010-10-06 19:51:12 -04004045 INIT_DELAYED_WORK(&cifs_sb->prune_tlinks, cifs_prune_tlinks);
4046
Al Viro2ced6f62011-06-17 09:20:04 -04004047 spin_lock_init(&cifs_sb->tlink_tree_lock);
4048 cifs_sb->tlink_tree = RB_ROOT;
4049
Steve Frenche8506d22019-02-28 21:32:15 -06004050 cifs_sb->bsize = pvolume_info->bsize;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04004051 /*
Jeff Layton5eba8ab2011-10-19 15:30:26 -04004052 * Temporarily set r/wsize for matching superblock. If we end up using
4053 * new sb then client will later negotiate it downward if needed.
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04004054 */
Jeff Layton5eba8ab2011-10-19 15:30:26 -04004055 cifs_sb->rsize = pvolume_info->rsize;
Pavel Shilovsky25c7f412011-05-26 23:35:47 +04004056 cifs_sb->wsize = pvolume_info->wsize;
4057
Steve French3b795212008-11-13 19:45:32 +00004058 cifs_sb->mnt_uid = pvolume_info->linux_uid;
4059 cifs_sb->mnt_gid = pvolume_info->linux_gid;
4060 cifs_sb->mnt_file_mode = pvolume_info->file_mode;
4061 cifs_sb->mnt_dir_mode = pvolume_info->dir_mode;
Joe Perchesf96637b2013-05-04 22:12:25 -05004062 cifs_dbg(FYI, "file mode: 0x%hx dir mode: 0x%hx\n",
4063 cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode);
Steve French3b795212008-11-13 19:45:32 +00004064
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05304065 cifs_sb->actimeo = pvolume_info->actimeo;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004066 cifs_sb->local_nls = pvolume_info->local_nls;
Suresh Jayaraman6d20e842010-12-01 14:42:28 +05304067
Aurelien Aptel83930722018-09-20 18:10:25 -07004068 if (pvolume_info->nodfs)
4069 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_DFS;
Steve French3b795212008-11-13 19:45:32 +00004070 if (pvolume_info->noperm)
4071 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
4072 if (pvolume_info->setuids)
4073 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
Steve French95932652016-09-23 01:36:34 -05004074 if (pvolume_info->setuidfromacl)
4075 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UID_FROM_ACL;
Steve French3b795212008-11-13 19:45:32 +00004076 if (pvolume_info->server_ino)
4077 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
4078 if (pvolume_info->remap)
Steve French2baa2682014-09-27 02:19:01 -05004079 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SFM_CHR;
4080 if (pvolume_info->sfu_remap)
Steve French3b795212008-11-13 19:45:32 +00004081 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
4082 if (pvolume_info->no_xattr)
4083 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
4084 if (pvolume_info->sfu_emul)
4085 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
4086 if (pvolume_info->nobrl)
4087 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
Steve French3d4ef9a2018-04-25 22:19:09 -05004088 if (pvolume_info->nohandlecache)
4089 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_HANDLE_CACHE;
Steve Frenchbe652442009-02-23 15:21:59 +00004090 if (pvolume_info->nostrictsync)
Steve French4717bed2009-02-24 14:44:19 +00004091 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOSSYNC;
Steve French13a6e422008-12-02 17:24:33 +00004092 if (pvolume_info->mand_lock)
4093 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOPOSIXBRL;
Pavel Shilovskyd4ffff12011-05-26 06:02:00 +00004094 if (pvolume_info->rwpidforward)
4095 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RWPIDFORWARD;
Steve French412094a2019-06-24 02:01:42 -05004096 if (pvolume_info->mode_ace)
4097 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MODE_FROM_SID;
Steve French3b795212008-11-13 19:45:32 +00004098 if (pvolume_info->cifs_acl)
4099 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01004100 if (pvolume_info->backupuid_specified) {
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05004101 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPUID;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01004102 cifs_sb->mnt_backupuid = pvolume_info->backupuid;
4103 }
4104 if (pvolume_info->backupgid_specified) {
Shirish Pargaonkar3d3ea8e2011-09-26 09:56:44 -05004105 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPGID;
Sachin Prabhu3c7c87f2012-04-24 15:28:14 +01004106 cifs_sb->mnt_backupgid = pvolume_info->backupgid;
4107 }
Steve French3b795212008-11-13 19:45:32 +00004108 if (pvolume_info->override_uid)
4109 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID;
4110 if (pvolume_info->override_gid)
4111 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;
4112 if (pvolume_info->dynperm)
4113 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM;
Suresh Jayaramanfa1df752010-07-05 18:13:36 +05304114 if (pvolume_info->fsc)
4115 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_FSCACHE;
Jeff Layton0eb8a132010-10-06 19:51:12 -04004116 if (pvolume_info->multiuser)
4117 cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_MULTIUSER |
4118 CIFS_MOUNT_NO_PERM);
Pavel Shilovskyd39454f2011-01-24 14:16:35 -05004119 if (pvolume_info->strict_io)
4120 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_STRICT_IO;
Steve French3b795212008-11-13 19:45:32 +00004121 if (pvolume_info->direct_io) {
Joe Perchesf96637b2013-05-04 22:12:25 -05004122 cifs_dbg(FYI, "mounting share using direct i/o\n");
Steve French3b795212008-11-13 19:45:32 +00004123 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
4124 }
Steve French83bbfa72019-08-27 23:58:54 -05004125 if (pvolume_info->cache_ro) {
4126 cifs_dbg(VFS, "mounting share with read only caching. Ensure that the share will not be modified while in use.\n");
4127 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RO_CACHE;
Steve French41e033f2019-08-30 02:12:41 -05004128 } else if (pvolume_info->cache_rw) {
4129 cifs_dbg(VFS, "mounting share in single client RW caching mode. Ensure that no other systems will be accessing the share.\n");
4130 cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_RO_CACHE |
4131 CIFS_MOUNT_RW_CACHE);
Steve French83bbfa72019-08-27 23:58:54 -05004132 }
Stefan Metzmacher736a33202010-07-30 14:56:00 +02004133 if (pvolume_info->mfsymlinks) {
4134 if (pvolume_info->sfu_emul) {
Steve Frenchdb8b6312014-09-22 05:13:55 -05004135 /*
4136 * Our SFU ("Services for Unix" emulation does not allow
4137 * creating symlinks but does allow reading existing SFU
4138 * symlinks (it does allow both creating and reading SFU
4139 * style mknod and FIFOs though). When "mfsymlinks" and
4140 * "sfu" are both enabled at the same time, it allows
4141 * reading both types of symlinks, but will only create
4142 * them with mfsymlinks format. This allows better
4143 * Apple compatibility (probably better for Samba too)
4144 * while still recognizing old Windows style symlinks.
4145 */
4146 cifs_dbg(VFS, "mount options mfsymlinks and sfu both enabled\n");
Stefan Metzmacher736a33202010-07-30 14:56:00 +02004147 }
Steve Frenchdb8b6312014-09-22 05:13:55 -05004148 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MF_SYMLINKS;
Stefan Metzmacher736a33202010-07-30 14:56:00 +02004149 }
Steve French3b795212008-11-13 19:45:32 +00004150
4151 if ((pvolume_info->cifs_acl) && (pvolume_info->dynperm))
Joe Perchesf96637b2013-05-04 22:12:25 -05004152 cifs_dbg(VFS, "mount option dynperm ignored if cifsacl mount option supported\n");
Sachin Prabhu4214ebf2016-07-29 22:38:19 +01004153
4154 if (pvolume_info->prepath) {
4155 cifs_sb->prepath = kstrdup(pvolume_info->prepath, GFP_KERNEL);
4156 if (cifs_sb->prepath == NULL)
4157 return -ENOMEM;
4158 }
4159
4160 return 0;
Jeff Laytonb1c8d2b2008-10-22 13:57:07 -04004161}
4162
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004163void
4164cifs_cleanup_volume_info_contents(struct smb_vol *volume_info)
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004165{
Sean Finneyb9468452011-04-11 13:19:32 +00004166 kfree(volume_info->username);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004167 kzfree(volume_info->password);
Jesper Juhl95c75452011-08-27 18:58:34 +02004168 kfree(volume_info->UNC);
Sean Finneyb9468452011-04-11 13:19:32 +00004169 kfree(volume_info->domainname);
4170 kfree(volume_info->iocharset);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004171 kfree(volume_info->prepath);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004172}
4173
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04004174void
4175cifs_cleanup_volume_info(struct smb_vol *volume_info)
4176{
4177 if (!volume_info)
4178 return;
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004179 cifs_cleanup_volume_info_contents(volume_info);
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04004180 kfree(volume_info);
4181}
4182
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004183/* Release all succeed connections */
4184static inline void mount_put_conns(struct cifs_sb_info *cifs_sb,
4185 unsigned int xid,
4186 struct TCP_Server_Info *server,
4187 struct cifs_ses *ses, struct cifs_tcon *tcon)
4188{
4189 int rc = 0;
4190
4191 if (tcon)
4192 cifs_put_tcon(tcon);
4193 else if (ses)
4194 cifs_put_smb_ses(ses);
4195 else if (server)
4196 cifs_put_tcp_session(server, 0);
4197 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_POSIX_PATHS;
4198 free_xid(xid);
4199}
4200
4201/* Get connections for tcp, ses and tcon */
4202static int mount_get_conns(struct smb_vol *vol, struct cifs_sb_info *cifs_sb,
4203 unsigned int *xid,
4204 struct TCP_Server_Info **nserver,
4205 struct cifs_ses **nses, struct cifs_tcon **ntcon)
4206{
4207 int rc = 0;
4208 struct TCP_Server_Info *server;
4209 struct cifs_ses *ses;
4210 struct cifs_tcon *tcon;
4211
4212 *nserver = NULL;
4213 *nses = NULL;
4214 *ntcon = NULL;
4215
4216 *xid = get_xid();
4217
4218 /* get a reference to a tcp session */
4219 server = cifs_get_tcp_session(vol);
4220 if (IS_ERR(server)) {
4221 rc = PTR_ERR(server);
4222 return rc;
4223 }
4224
4225 *nserver = server;
4226
4227 if ((vol->max_credits < 20) || (vol->max_credits > 60000))
4228 server->max_credits = SMB2_MAX_CREDITS_AVAILABLE;
4229 else
4230 server->max_credits = vol->max_credits;
4231
4232 /* get a reference to a SMB session */
4233 ses = cifs_get_smb_ses(server, vol);
4234 if (IS_ERR(ses)) {
4235 rc = PTR_ERR(ses);
4236 return rc;
4237 }
4238
4239 *nses = ses;
4240
4241 if ((vol->persistent == true) && (!(ses->server->capabilities &
4242 SMB2_GLOBAL_CAP_PERSISTENT_HANDLES))) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10004243 cifs_server_dbg(VFS, "persistent handles not supported by server\n");
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004244 return -EOPNOTSUPP;
4245 }
4246
4247 /* search for existing tcon to this server share */
4248 tcon = cifs_get_tcon(ses, vol);
4249 if (IS_ERR(tcon)) {
4250 rc = PTR_ERR(tcon);
4251 return rc;
4252 }
4253
4254 *ntcon = tcon;
4255
4256 /* if new SMB3.11 POSIX extensions are supported do not remap / and \ */
4257 if (tcon->posix_extensions)
4258 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS;
4259
4260 /* tell server which Unix caps we support */
4261 if (cap_unix(tcon->ses)) {
4262 /*
4263 * reset of caps checks mount to see if unix extensions disabled
4264 * for just this mount.
4265 */
4266 reset_cifs_unix_caps(*xid, tcon, cifs_sb, vol);
4267 if ((tcon->ses->server->tcpStatus == CifsNeedReconnect) &&
4268 (le64_to_cpu(tcon->fsUnixInfo.Capability) &
4269 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP))
4270 return -EACCES;
4271 } else
4272 tcon->unix_ext = 0; /* server does not support them */
4273
4274 /* do not care if a following call succeed - informational */
Steve French1981eba2019-08-29 22:33:38 -05004275 if (!tcon->pipe && server->ops->qfs_tcon) {
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004276 server->ops->qfs_tcon(*xid, tcon);
Steve French1981eba2019-08-29 22:33:38 -05004277 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RO_CACHE) {
4278 if (tcon->fsDevInfo.DeviceCharacteristics &
Steve French52870d52019-10-01 21:25:46 -05004279 cpu_to_le32(FILE_READ_ONLY_DEVICE))
Steve French1981eba2019-08-29 22:33:38 -05004280 cifs_dbg(VFS, "mounted to read only share\n");
Steve French41e033f2019-08-30 02:12:41 -05004281 else if ((cifs_sb->mnt_cifs_flags &
4282 CIFS_MOUNT_RW_CACHE) == 0)
Steve French1981eba2019-08-29 22:33:38 -05004283 cifs_dbg(VFS, "read only mount of RW share\n");
Steve French41e033f2019-08-30 02:12:41 -05004284 /* no need to log a RW mount of a typical RW share */
Steve French1981eba2019-08-29 22:33:38 -05004285 }
4286 }
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004287
4288 cifs_sb->wsize = server->ops->negotiate_wsize(tcon, vol);
4289 cifs_sb->rsize = server->ops->negotiate_rsize(tcon, vol);
4290
4291 return 0;
4292}
4293
4294static int mount_setup_tlink(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses,
4295 struct cifs_tcon *tcon)
4296{
4297 struct tcon_link *tlink;
4298
4299 /* hang the tcon off of the superblock */
4300 tlink = kzalloc(sizeof(*tlink), GFP_KERNEL);
4301 if (tlink == NULL)
4302 return -ENOMEM;
4303
4304 tlink->tl_uid = ses->linux_uid;
4305 tlink->tl_tcon = tcon;
4306 tlink->tl_time = jiffies;
4307 set_bit(TCON_LINK_MASTER, &tlink->tl_flags);
4308 set_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
4309
4310 cifs_sb->master_tlink = tlink;
4311 spin_lock(&cifs_sb->tlink_tree_lock);
4312 tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
4313 spin_unlock(&cifs_sb->tlink_tree_lock);
4314
4315 queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
4316 TLINK_IDLE_EXPIRE);
4317 return 0;
4318}
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04004319
Steve French2d6d5892009-04-09 00:36:44 +00004320#ifdef CONFIG_CIFS_DFS_UPCALL
Steve French6d3ea7e2012-11-28 22:34:41 -06004321/*
4322 * cifs_build_path_to_root returns full path to root when we do not have an
4323 * exiting connection (tcon)
4324 */
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004325static char *
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04004326build_unc_path_to_root(const struct smb_vol *vol,
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004327 const struct cifs_sb_info *cifs_sb, bool useppath)
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004328{
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04004329 char *full_path, *pos;
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004330 unsigned int pplen = useppath && vol->prepath ?
4331 strlen(vol->prepath) + 1 : 0;
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04004332 unsigned int unc_len = strnlen(vol->UNC, MAX_TREE_SIZE + 1);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004333
Ronnie Sahlberg340625e2019-08-27 09:30:14 +10004334 if (unc_len > MAX_TREE_SIZE)
4335 return ERR_PTR(-EINVAL);
4336
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04004337 full_path = kmalloc(unc_len + pplen + 1, GFP_KERNEL);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004338 if (full_path == NULL)
4339 return ERR_PTR(-ENOMEM);
4340
Ronnie Sahlberg340625e2019-08-27 09:30:14 +10004341 memcpy(full_path, vol->UNC, unc_len);
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04004342 pos = full_path + unc_len;
4343
4344 if (pplen) {
Jeff Layton1fc29ba2013-05-31 10:00:18 -04004345 *pos = CIFS_DIR_SEP(cifs_sb);
Ronnie Sahlberg340625e2019-08-27 09:30:14 +10004346 memcpy(pos + 1, vol->prepath, pplen);
Jeff Laytonb2a0fa12011-07-06 08:10:36 -04004347 pos += pplen;
4348 }
4349
4350 *pos = '\0'; /* add trailing null */
Steve Frenchf87d39d2011-05-27 03:50:55 +00004351 convert_delimiter(full_path, CIFS_DIR_SEP(cifs_sb));
Joe Perchesf96637b2013-05-04 22:12:25 -05004352 cifs_dbg(FYI, "%s: full_path=%s\n", __func__, full_path);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004353 return full_path;
4354}
Sean Finneydd613942011-04-11 13:19:30 +00004355
Paulo Alcantara1c780222018-11-14 16:24:03 -02004356/**
4357 * expand_dfs_referral - Perform a dfs referral query and update the cifs_sb
4358 *
Sean Finneydd613942011-04-11 13:19:30 +00004359 *
Sean Finney046462a2011-04-11 13:19:33 +00004360 * If a referral is found, cifs_sb->mountdata will be (re-)allocated
4361 * to a string containing updated options for the submount. Otherwise it
4362 * will be left untouched.
Sean Finneydd613942011-04-11 13:19:30 +00004363 *
4364 * Returns the rc from get_dfs_path to the caller, which can be used to
4365 * determine whether there were referrals.
4366 */
4367static int
Pavel Shilovskyb669f332012-05-27 20:21:53 +04004368expand_dfs_referral(const unsigned int xid, struct cifs_ses *ses,
Sean Finneydd613942011-04-11 13:19:30 +00004369 struct smb_vol *volume_info, struct cifs_sb_info *cifs_sb,
Sean Finney046462a2011-04-11 13:19:33 +00004370 int check_prefix)
Sean Finneydd613942011-04-11 13:19:30 +00004371{
4372 int rc;
Paulo Alcantara1c780222018-11-14 16:24:03 -02004373 struct dfs_info3_param referral = {0};
Sean Finneydd613942011-04-11 13:19:30 +00004374 char *full_path = NULL, *ref_path = NULL, *mdata = NULL;
4375
Aurelien Aptel83930722018-09-20 18:10:25 -07004376 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS)
4377 return -EREMOTE;
4378
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004379 full_path = build_unc_path_to_root(volume_info, cifs_sb, true);
Sean Finneydd613942011-04-11 13:19:30 +00004380 if (IS_ERR(full_path))
4381 return PTR_ERR(full_path);
4382
4383 /* For DFS paths, skip the first '\' of the UNC */
4384 ref_path = check_prefix ? full_path + 1 : volume_info->UNC + 1;
4385
Paulo Alcantara1c780222018-11-14 16:24:03 -02004386 rc = dfs_cache_find(xid, ses, cifs_sb->local_nls, cifs_remap(cifs_sb),
4387 ref_path, &referral, NULL);
4388 if (!rc) {
Sean Finneydd613942011-04-11 13:19:30 +00004389 char *fake_devname = NULL;
4390
4391 mdata = cifs_compose_mount_options(cifs_sb->mountdata,
Paulo Alcantara1c780222018-11-14 16:24:03 -02004392 full_path + 1, &referral,
Sean Finneydd613942011-04-11 13:19:30 +00004393 &fake_devname);
Paulo Alcantara1c780222018-11-14 16:24:03 -02004394 free_dfs_info_param(&referral);
Sean Finney046462a2011-04-11 13:19:33 +00004395
Sean Finneydd613942011-04-11 13:19:30 +00004396 if (IS_ERR(mdata)) {
4397 rc = PTR_ERR(mdata);
4398 mdata = NULL;
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04004399 } else {
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004400 cifs_cleanup_volume_info_contents(volume_info);
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04004401 rc = cifs_setup_volume_info(volume_info, mdata,
Paulo Alcantara1c780222018-11-14 16:24:03 -02004402 fake_devname, false);
Sean Finneydd613942011-04-11 13:19:30 +00004403 }
Jeff Laytonb9bce2e2011-07-06 08:10:39 -04004404 kfree(fake_devname);
4405 kfree(cifs_sb->mountdata);
Sean Finney046462a2011-04-11 13:19:33 +00004406 cifs_sb->mountdata = mdata;
Sean Finneydd613942011-04-11 13:19:30 +00004407 }
4408 kfree(full_path);
4409 return rc;
4410}
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004411
4412static inline int get_next_dfs_tgt(const char *path,
4413 struct dfs_cache_tgt_list *tgt_list,
4414 struct dfs_cache_tgt_iterator **tgt_it)
4415{
4416 if (!*tgt_it)
4417 *tgt_it = dfs_cache_get_tgt_iterator(tgt_list);
4418 else
4419 *tgt_it = dfs_cache_get_next_tgt(tgt_list, *tgt_it);
4420 return !*tgt_it ? -EHOSTDOWN : 0;
4421}
4422
4423static int update_vol_info(const struct dfs_cache_tgt_iterator *tgt_it,
4424 struct smb_vol *fake_vol, struct smb_vol *vol)
4425{
4426 const char *tgt = dfs_cache_get_tgt_name(tgt_it);
4427 int len = strlen(tgt) + 2;
4428 char *new_unc;
4429
4430 new_unc = kmalloc(len, GFP_KERNEL);
4431 if (!new_unc)
4432 return -ENOMEM;
Ronnie Sahlberg74ea5f92019-02-09 09:51:11 +10004433 scnprintf(new_unc, len, "\\%s", tgt);
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004434
4435 kfree(vol->UNC);
4436 vol->UNC = new_unc;
4437
4438 if (fake_vol->prepath) {
4439 kfree(vol->prepath);
4440 vol->prepath = fake_vol->prepath;
4441 fake_vol->prepath = NULL;
4442 }
4443 memcpy(&vol->dstaddr, &fake_vol->dstaddr, sizeof(vol->dstaddr));
4444
4445 return 0;
4446}
4447
4448static int setup_dfs_tgt_conn(const char *path,
4449 const struct dfs_cache_tgt_iterator *tgt_it,
4450 struct cifs_sb_info *cifs_sb,
4451 struct smb_vol *vol,
4452 unsigned int *xid,
4453 struct TCP_Server_Info **server,
4454 struct cifs_ses **ses,
4455 struct cifs_tcon **tcon)
4456{
4457 int rc;
4458 struct dfs_info3_param ref = {0};
4459 char *mdata = NULL, *fake_devname = NULL;
Steve Frenchd0959b02019-10-05 10:53:58 -05004460 struct smb_vol fake_vol = {NULL};
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004461
4462 cifs_dbg(FYI, "%s: dfs path: %s\n", __func__, path);
4463
4464 rc = dfs_cache_get_tgt_referral(path, tgt_it, &ref);
4465 if (rc)
4466 return rc;
4467
4468 mdata = cifs_compose_mount_options(cifs_sb->mountdata, path, &ref,
4469 &fake_devname);
4470 free_dfs_info_param(&ref);
4471
4472 if (IS_ERR(mdata)) {
4473 rc = PTR_ERR(mdata);
4474 mdata = NULL;
4475 } else {
4476 cifs_dbg(FYI, "%s: fake_devname: %s\n", __func__, fake_devname);
4477 rc = cifs_setup_volume_info(&fake_vol, mdata, fake_devname,
4478 false);
4479 }
4480 kfree(mdata);
4481 kfree(fake_devname);
4482
4483 if (!rc) {
4484 /*
4485 * We use a 'fake_vol' here because we need pass it down to the
4486 * mount_{get,put} functions to test connection against new DFS
4487 * targets.
4488 */
4489 mount_put_conns(cifs_sb, *xid, *server, *ses, *tcon);
4490 rc = mount_get_conns(&fake_vol, cifs_sb, xid, server, ses,
4491 tcon);
4492 if (!rc) {
4493 /*
4494 * We were able to connect to new target server.
4495 * Update current volume info with new target server.
4496 */
4497 rc = update_vol_info(tgt_it, &fake_vol, vol);
4498 }
4499 }
4500 cifs_cleanup_volume_info_contents(&fake_vol);
4501 return rc;
4502}
4503
4504static int mount_do_dfs_failover(const char *path,
4505 struct cifs_sb_info *cifs_sb,
4506 struct smb_vol *vol,
4507 struct cifs_ses *root_ses,
4508 unsigned int *xid,
4509 struct TCP_Server_Info **server,
4510 struct cifs_ses **ses,
4511 struct cifs_tcon **tcon)
4512{
4513 int rc;
4514 struct dfs_cache_tgt_list tgt_list;
4515 struct dfs_cache_tgt_iterator *tgt_it = NULL;
4516
4517 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS)
4518 return -EOPNOTSUPP;
4519
4520 rc = dfs_cache_noreq_find(path, NULL, &tgt_list);
4521 if (rc)
4522 return rc;
4523
4524 for (;;) {
4525 /* Get next DFS target server - if any */
4526 rc = get_next_dfs_tgt(path, &tgt_list, &tgt_it);
4527 if (rc)
4528 break;
4529 /* Connect to next DFS target */
4530 rc = setup_dfs_tgt_conn(path, tgt_it, cifs_sb, vol, xid, server,
4531 ses, tcon);
4532 if (!rc || rc == -EACCES || rc == -EOPNOTSUPP)
4533 break;
4534 }
4535 if (!rc) {
4536 /*
4537 * Update DFS target hint in DFS referral cache with the target
4538 * server we successfully reconnected to.
4539 */
4540 rc = dfs_cache_update_tgthint(*xid, root_ses ? root_ses : *ses,
4541 cifs_sb->local_nls,
4542 cifs_remap(cifs_sb), path,
4543 tgt_it);
4544 }
4545 dfs_cache_free_tgts(&tgt_list);
4546 return rc;
4547}
Steve French2d6d5892009-04-09 00:36:44 +00004548#endif
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004549
Paulo Alcantara (SUSE)50720102019-03-19 16:54:29 -03004550int
Jeff Layton04db79b2011-07-06 08:10:38 -04004551cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
Steve Frenchc7c137b2018-06-06 17:59:29 -05004552 const char *devname, bool is_smb3)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004553{
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004554 int rc = 0;
Sean Finneydd613942011-04-11 13:19:30 +00004555
Steve Frenchc7c137b2018-06-06 17:59:29 -05004556 if (cifs_parse_mount_options(mount_data, devname, volume_info, is_smb3))
Jeff Layton04db79b2011-07-06 08:10:38 -04004557 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004558
Jeff Layton7586b762008-12-01 18:41:49 -05004559 if (volume_info->nullauth) {
Joe Perchesf96637b2013-05-04 22:12:25 -05004560 cifs_dbg(FYI, "Anonymous login\n");
Jeff Layton04febab2012-01-17 16:09:15 -05004561 kfree(volume_info->username);
4562 volume_info->username = NULL;
Jeff Layton7586b762008-12-01 18:41:49 -05004563 } else if (volume_info->username) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004564 /* BB fixme parse for domain name here */
Joe Perchesf96637b2013-05-04 22:12:25 -05004565 cifs_dbg(FYI, "Username: %s\n", volume_info->username);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004566 } else {
Joe Perchesf96637b2013-05-04 22:12:25 -05004567 cifs_dbg(VFS, "No username specified\n");
Steve French50c2f752007-07-13 00:33:32 +00004568 /* In userspace mount helper we can get user name from alternate
4569 locations such as env variables and files on disk */
Jeff Layton04db79b2011-07-06 08:10:38 -04004570 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004571 }
4572
Linus Torvalds1da177e2005-04-16 15:20:36 -07004573 /* this is needed for ASCII cp to Unicode converts */
Jeff Layton7586b762008-12-01 18:41:49 -05004574 if (volume_info->iocharset == NULL) {
Jeff Laytona5fc4ce2010-04-24 07:57:42 -04004575 /* load_nls_default cannot return null */
4576 volume_info->local_nls = load_nls_default();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004577 } else {
Jeff Laytona5fc4ce2010-04-24 07:57:42 -04004578 volume_info->local_nls = load_nls(volume_info->iocharset);
4579 if (volume_info->local_nls == NULL) {
Joe Perchesf96637b2013-05-04 22:12:25 -05004580 cifs_dbg(VFS, "CIFS mount error: iocharset %s not found\n",
Joe Perchesb6b38f72010-04-21 03:50:45 +00004581 volume_info->iocharset);
Jeff Layton04db79b2011-07-06 08:10:38 -04004582 return -ELIBACC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004583 }
4584 }
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004585
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004586 return rc;
Jeff Layton04db79b2011-07-06 08:10:38 -04004587}
4588
4589struct smb_vol *
Steve Frenchc7c137b2018-06-06 17:59:29 -05004590cifs_get_volume_info(char *mount_data, const char *devname, bool is_smb3)
Jeff Layton04db79b2011-07-06 08:10:38 -04004591{
4592 int rc;
4593 struct smb_vol *volume_info;
4594
Jeff Layton6ee95422012-11-26 11:09:57 -05004595 volume_info = kmalloc(sizeof(struct smb_vol), GFP_KERNEL);
Jeff Layton04db79b2011-07-06 08:10:38 -04004596 if (!volume_info)
4597 return ERR_PTR(-ENOMEM);
4598
Steve Frenchc7c137b2018-06-06 17:59:29 -05004599 rc = cifs_setup_volume_info(volume_info, mount_data, devname, is_smb3);
Jeff Layton04db79b2011-07-06 08:10:38 -04004600 if (rc) {
4601 cifs_cleanup_volume_info(volume_info);
4602 volume_info = ERR_PTR(rc);
4603 }
4604
4605 return volume_info;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004606}
4607
Aurelien Aptela6b50582016-05-25 19:59:09 +02004608static int
4609cifs_are_all_path_components_accessible(struct TCP_Server_Info *server,
4610 unsigned int xid,
4611 struct cifs_tcon *tcon,
4612 struct cifs_sb_info *cifs_sb,
Ronnie Sahlbergce465bf2019-07-11 13:46:58 +10004613 char *full_path,
4614 int added_treename)
Aurelien Aptela6b50582016-05-25 19:59:09 +02004615{
4616 int rc;
4617 char *s;
4618 char sep, tmp;
Ronnie Sahlbergce465bf2019-07-11 13:46:58 +10004619 int skip = added_treename ? 1 : 0;
Aurelien Aptela6b50582016-05-25 19:59:09 +02004620
4621 sep = CIFS_DIR_SEP(cifs_sb);
4622 s = full_path;
4623
4624 rc = server->ops->is_path_accessible(xid, tcon, cifs_sb, "");
4625 while (rc == 0) {
4626 /* skip separators */
4627 while (*s == sep)
4628 s++;
4629 if (!*s)
4630 break;
4631 /* next separator */
4632 while (*s && *s != sep)
4633 s++;
Ronnie Sahlbergce465bf2019-07-11 13:46:58 +10004634 /*
4635 * if the treename is added, we then have to skip the first
4636 * part within the separators
4637 */
4638 if (skip) {
4639 skip = 0;
4640 continue;
4641 }
Aurelien Aptela6b50582016-05-25 19:59:09 +02004642 /*
4643 * temporarily null-terminate the path at the end of
4644 * the current component
4645 */
4646 tmp = *s;
4647 *s = 0;
4648 rc = server->ops->is_path_accessible(xid, tcon, cifs_sb,
4649 full_path);
4650 *s = tmp;
4651 }
4652 return rc;
4653}
4654
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004655/*
4656 * Check if path is remote (e.g. a DFS share). Return -EREMOTE if it is,
4657 * otherwise 0.
4658 */
4659static int is_path_remote(struct cifs_sb_info *cifs_sb, struct smb_vol *vol,
4660 const unsigned int xid,
4661 struct TCP_Server_Info *server,
4662 struct cifs_tcon *tcon)
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004663{
Jeff Layton1daaae82012-03-21 06:30:40 -04004664 int rc;
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004665 char *full_path;
4666
4667 if (!server->ops->is_path_accessible)
4668 return -EOPNOTSUPP;
4669
4670 /*
4671 * cifs_build_path_to_root works only when we have a valid tcon
4672 */
4673 full_path = cifs_build_path_to_root(vol, cifs_sb, tcon,
4674 tcon->Flags & SMB_SHARE_IS_IN_DFS);
4675 if (full_path == NULL)
4676 return -ENOMEM;
4677
4678 cifs_dbg(FYI, "%s: full_path: %s\n", __func__, full_path);
4679
4680 rc = server->ops->is_path_accessible(xid, tcon, cifs_sb,
4681 full_path);
4682 if (rc != 0 && rc != -EREMOTE) {
4683 kfree(full_path);
4684 return rc;
4685 }
4686
4687 if (rc != -EREMOTE) {
4688 rc = cifs_are_all_path_components_accessible(server, xid, tcon,
Ronnie Sahlbergce465bf2019-07-11 13:46:58 +10004689 cifs_sb, full_path, tcon->Flags & SMB_SHARE_IS_IN_DFS);
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004690 if (rc != 0) {
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10004691 cifs_server_dbg(VFS, "cannot query dirs between root and final path, "
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004692 "enabling CIFS_MOUNT_USE_PREFIX_PATH\n");
4693 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
4694 rc = 0;
4695 }
4696 }
4697
4698 kfree(full_path);
4699 return rc;
4700}
4701
4702#ifdef CONFIG_CIFS_DFS_UPCALL
4703int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *vol)
4704{
4705 int rc = 0;
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04004706 unsigned int xid;
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04004707 struct cifs_ses *ses;
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004708 struct cifs_tcon *root_tcon = NULL;
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004709 struct cifs_tcon *tcon = NULL;
Pavel Shilovskyaf4281d2012-05-27 20:48:35 +04004710 struct TCP_Server_Info *server;
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004711 char *root_path = NULL, *full_path = NULL;
Paulo Alcantara (SUSE)50720102019-03-19 16:54:29 -03004712 char *old_mountdata, *origin_mountdata = NULL;
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004713 int count;
Al Virodd854462011-06-17 08:24:42 -04004714
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004715 rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses, &tcon);
4716 if (!rc && tcon) {
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004717 /* If not a standalone DFS root, then check if path is remote */
4718 rc = dfs_cache_find(xid, ses, cifs_sb->local_nls,
4719 cifs_remap(cifs_sb), vol->UNC + 1, NULL,
4720 NULL);
4721 if (rc) {
4722 rc = is_path_remote(cifs_sb, vol, xid, server, tcon);
4723 if (!rc)
4724 goto out;
4725 if (rc != -EREMOTE)
4726 goto error;
4727 }
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004728 }
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004729 /*
4730 * If first DFS target server went offline and we failed to connect it,
4731 * server and ses pointers are NULL at this point, though we still have
4732 * chance to get a cached DFS referral in expand_dfs_referral() and
4733 * retry next target available in it.
4734 *
4735 * If a NULL ses ptr is passed to dfs_cache_find(), a lookup will be
4736 * performed against DFS path and *no* requests will be sent to server
4737 * for any new DFS referrals. Hence it's safe to skip checking whether
4738 * server or ses ptr is NULL.
4739 */
4740 if (rc == -EACCES || rc == -EOPNOTSUPP)
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004741 goto error;
Pavel Shilovsky724d9f12011-05-05 09:55:12 +00004742
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004743 root_path = build_unc_path_to_root(vol, cifs_sb, false);
4744 if (IS_ERR(root_path)) {
4745 rc = PTR_ERR(root_path);
4746 root_path = NULL;
4747 goto error;
4748 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004749
Paulo Alcantara93d5cb52018-11-14 17:13:25 -02004750 full_path = build_unc_path_to_root(vol, cifs_sb, true);
4751 if (IS_ERR(full_path)) {
4752 rc = PTR_ERR(full_path);
4753 full_path = NULL;
4754 goto error;
4755 }
Sean Finneyc1508ca2011-04-11 13:19:31 +00004756 /*
4757 * Perform an unconditional check for whether there are DFS
4758 * referrals for this path without prefix, to provide support
4759 * for DFS referrals from w2k8 servers which don't seem to respond
4760 * with PATH_NOT_COVERED to requests that include the prefix.
4761 * Chase the referral if found, otherwise continue normally.
4762 */
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004763 old_mountdata = cifs_sb->mountdata;
4764 (void)expand_dfs_referral(xid, ses, vol, cifs_sb, false);
Sean Finneyc1508ca2011-04-11 13:19:31 +00004765
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004766 if (cifs_sb->mountdata == NULL) {
4767 rc = -ENOENT;
4768 goto error;
4769 }
4770
Paulo Alcantara (SUSE)50720102019-03-19 16:54:29 -03004771 /* Save DFS root volume information for DFS refresh worker */
4772 origin_mountdata = kstrndup(cifs_sb->mountdata,
4773 strlen(cifs_sb->mountdata), GFP_KERNEL);
4774 if (!origin_mountdata) {
4775 rc = -ENOMEM;
4776 goto error;
4777 }
4778
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004779 if (cifs_sb->mountdata != old_mountdata) {
4780 /* If we were redirected, reconnect to new target server */
4781 mount_put_conns(cifs_sb, xid, server, ses, tcon);
4782 rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses, &tcon);
4783 }
4784 if (rc) {
4785 if (rc == -EACCES || rc == -EOPNOTSUPP)
4786 goto error;
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004787 /* Perform DFS failover to any other DFS targets */
4788 rc = mount_do_dfs_failover(root_path + 1, cifs_sb, vol, NULL,
4789 &xid, &server, &ses, &tcon);
4790 if (rc)
4791 goto error;
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004792 }
4793
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004794 kfree(root_path);
4795 root_path = build_unc_path_to_root(vol, cifs_sb, false);
4796 if (IS_ERR(root_path)) {
4797 rc = PTR_ERR(root_path);
4798 root_path = NULL;
4799 goto error;
4800 }
4801 /* Cache out resolved root server */
4802 (void)dfs_cache_find(xid, ses, cifs_sb->local_nls, cifs_remap(cifs_sb),
4803 root_path + 1, NULL, NULL);
4804 /*
4805 * Save root tcon for additional DFS requests to update or create a new
4806 * DFS cache entry, or even perform DFS failover.
4807 */
4808 spin_lock(&cifs_tcp_ses_lock);
4809 tcon->tc_count++;
4810 tcon->dfs_path = root_path;
4811 root_path = NULL;
4812 tcon->remap = cifs_remap(cifs_sb);
4813 spin_unlock(&cifs_tcp_ses_lock);
4814
4815 root_tcon = tcon;
4816
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004817 for (count = 1; ;) {
4818 if (!rc && tcon) {
4819 rc = is_path_remote(cifs_sb, vol, xid, server, tcon);
4820 if (!rc || rc != -EREMOTE)
4821 break;
Pavel Shilovsky68889f22012-05-25 14:40:22 +04004822 }
Steve French6d3ea7e2012-11-28 22:34:41 -06004823 /*
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004824 * BB: when we implement proper loop detection,
4825 * we will remove this check. But now we need it
4826 * to prevent an indefinite loop if 'DFS tree' is
4827 * misconfigured (i.e. has loops).
Steve French6d3ea7e2012-11-28 22:34:41 -06004828 */
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004829 if (count++ > MAX_NESTED_LINKS) {
Igor Mammedov5c2503a2009-04-21 19:31:05 +04004830 rc = -ELOOP;
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004831 break;
Igor Mammedov5c2503a2009-04-21 19:31:05 +04004832 }
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004833
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004834 kfree(full_path);
4835 full_path = build_unc_path_to_root(vol, cifs_sb, true);
4836 if (IS_ERR(full_path)) {
4837 rc = PTR_ERR(full_path);
4838 full_path = NULL;
4839 break;
4840 }
4841
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004842 old_mountdata = cifs_sb->mountdata;
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004843 rc = expand_dfs_referral(xid, root_tcon->ses, vol, cifs_sb,
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004844 true);
4845 if (rc)
4846 break;
Jeff Layton7b91e262009-07-23 15:22:30 -04004847
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004848 if (cifs_sb->mountdata != old_mountdata) {
4849 mount_put_conns(cifs_sb, xid, server, ses, tcon);
4850 rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses,
4851 &tcon);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004852 }
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004853 if (rc) {
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004854 if (rc == -EACCES || rc == -EOPNOTSUPP)
4855 break;
4856 /* Perform DFS failover to any other DFS targets */
4857 rc = mount_do_dfs_failover(full_path + 1, cifs_sb, vol,
4858 root_tcon->ses, &xid,
4859 &server, &ses, &tcon);
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004860 if (rc == -EACCES || rc == -EOPNOTSUPP || !server ||
4861 !ses)
4862 goto error;
4863 }
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004864 }
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004865 cifs_put_tcon(root_tcon);
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004866
Jeff Layton9d002df2010-10-06 19:51:11 -04004867 if (rc)
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004868 goto error;
Igor Mammedov1bfe73c2009-04-01 17:54:42 +04004869
Paulo Alcantara93d5cb52018-11-14 17:13:25 -02004870 spin_lock(&cifs_tcp_ses_lock);
4871 if (!tcon->dfs_path) {
4872 /* Save full path in new tcon to do failover when reconnecting tcons */
4873 tcon->dfs_path = full_path;
4874 full_path = NULL;
4875 tcon->remap = cifs_remap(cifs_sb);
4876 }
4877 cifs_sb->origin_fullpath = kstrndup(tcon->dfs_path,
YueHaibing2f0a6172018-12-18 01:34:39 +00004878 strlen(tcon->dfs_path),
4879 GFP_ATOMIC);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -02004880 if (!cifs_sb->origin_fullpath) {
4881 spin_unlock(&cifs_tcp_ses_lock);
4882 rc = -ENOMEM;
4883 goto error;
4884 }
4885 spin_unlock(&cifs_tcp_ses_lock);
4886
Paulo Alcantara (SUSE)50720102019-03-19 16:54:29 -03004887 rc = dfs_cache_add_vol(origin_mountdata, vol, cifs_sb->origin_fullpath);
Paulo Alcantarae511d312018-11-14 17:16:44 -02004888 if (rc) {
4889 kfree(cifs_sb->origin_fullpath);
4890 goto error;
4891 }
Aurelien Aptel5fc7fcd2018-11-16 16:13:25 +01004892 /*
4893 * After reconnecting to a different server, unique ids won't
4894 * match anymore, so we disable serverino. This prevents
4895 * dentry revalidation to think the dentry are stale (ESTALE).
4896 */
4897 cifs_autodisable_serverino(cifs_sb);
Jeff Layton70fe7dc2007-11-16 22:21:07 +00004898out:
Pavel Shilovsky6d5786a2012-06-20 11:21:16 +04004899 free_xid(xid);
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004900 return mount_setup_tlink(cifs_sb, ses, tcon);
4901
4902error:
Paulo Alcantara4a367dc2018-11-14 16:53:52 -02004903 kfree(full_path);
4904 kfree(root_path);
Paulo Alcantara (SUSE)50720102019-03-19 16:54:29 -03004905 kfree(origin_mountdata);
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004906 mount_put_conns(cifs_sb, xid, server, ses, tcon);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004907 return rc;
4908}
Paulo Alcantara56c762e2018-11-14 13:03:14 -02004909#else
4910int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *vol)
4911{
4912 int rc = 0;
4913 unsigned int xid;
4914 struct cifs_ses *ses;
4915 struct cifs_tcon *tcon;
4916 struct TCP_Server_Info *server;
4917
4918 rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses, &tcon);
4919 if (rc)
4920 goto error;
4921
4922 if (tcon) {
4923 rc = is_path_remote(cifs_sb, vol, xid, server, tcon);
4924 if (rc == -EREMOTE)
4925 rc = -EOPNOTSUPP;
4926 if (rc)
4927 goto error;
4928 }
4929
4930 free_xid(xid);
4931
4932 return mount_setup_tlink(cifs_sb, ses, tcon);
4933
4934error:
4935 mount_put_conns(cifs_sb, xid, server, ses, tcon);
4936 return rc;
4937}
4938#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07004939
Jeff Layton8d1bca32011-06-11 21:17:10 -04004940/*
Aurelien Aptelb327a712018-01-24 13:46:10 +01004941 * Issue a TREE_CONNECT request.
Jeff Layton8d1bca32011-06-11 21:17:10 -04004942 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004943int
Pavel Shilovsky2e6e02a2012-05-25 11:11:39 +04004944CIFSTCon(const unsigned int xid, struct cifs_ses *ses,
Steve French96daf2b2011-05-27 04:34:02 +00004945 const char *tree, struct cifs_tcon *tcon,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004946 const struct nls_table *nls_codepage)
4947{
4948 struct smb_hdr *smb_buffer;
4949 struct smb_hdr *smb_buffer_response;
4950 TCONX_REQ *pSMB;
4951 TCONX_RSP *pSMBr;
4952 unsigned char *bcc_ptr;
4953 int rc = 0;
Jeff Layton690c5222011-01-20 13:36:51 -05004954 int length;
4955 __u16 bytes_left, count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004956
4957 if (ses == NULL)
4958 return -EIO;
4959
4960 smb_buffer = cifs_buf_get();
Steve Frenchca43e3b2009-09-01 17:20:50 +00004961 if (smb_buffer == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004962 return -ENOMEM;
Steve Frenchca43e3b2009-09-01 17:20:50 +00004963
Linus Torvalds1da177e2005-04-16 15:20:36 -07004964 smb_buffer_response = smb_buffer;
4965
4966 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
4967 NULL /*no tid */ , 4 /*wct */ );
Steve French1982c342005-08-17 12:38:22 -07004968
Pavel Shilovsky88257362012-05-23 14:01:59 +04004969 smb_buffer->Mid = get_next_mid(ses->server);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004970 smb_buffer->Uid = ses->Suid;
4971 pSMB = (TCONX_REQ *) smb_buffer;
4972 pSMBr = (TCONX_RSP *) smb_buffer_response;
4973
4974 pSMB->AndXCommand = 0xFF;
4975 pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004976 bcc_ptr = &pSMB->Password[0];
Aurelien Aptelb327a712018-01-24 13:46:10 +01004977 if (tcon->pipe || (ses->server->sec_mode & SECMODE_USER)) {
Steve Frencheeac8042006-01-13 21:34:58 -08004978 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
Steve French7c7b25b2006-06-01 19:20:10 +00004979 *bcc_ptr = 0; /* password is null byte */
Steve Frencheeac8042006-01-13 21:34:58 -08004980 bcc_ptr++; /* skip password */
Steve French7c7b25b2006-06-01 19:20:10 +00004981 /* already aligned so no need to do it below */
Steve Frencheeac8042006-01-13 21:34:58 -08004982 } else {
Shirish Pargaonkar540b2e32011-01-18 22:33:54 -06004983 pSMB->PasswordLength = cpu_to_le16(CIFS_AUTH_RESP_SIZE);
Steve Frencheeac8042006-01-13 21:34:58 -08004984 /* BB FIXME add code to fail this if NTLMv2 or Kerberos
4985 specified as required (when that support is added to
4986 the vfs in the future) as only NTLM or the much
Steve French7c7b25b2006-06-01 19:20:10 +00004987 weaker LANMAN (which we do not send by default) is accepted
Steve Frencheeac8042006-01-13 21:34:58 -08004988 by Samba (not sure whether other servers allow
4989 NTLMv2 password here) */
Steve French7c7b25b2006-06-01 19:20:10 +00004990#ifdef CONFIG_CIFS_WEAK_PW_HASH
Jeff Layton04912d62010-04-24 07:57:45 -04004991 if ((global_secflags & CIFSSEC_MAY_LANMAN) &&
Jeff Layton3f618222013-06-12 19:52:14 -05004992 (ses->sectype == LANMAN))
Shirish Pargaonkard3ba50b2010-10-27 15:20:36 -05004993 calc_lanman_hash(tcon->password, ses->server->cryptkey,
Steve French96daf2b2011-05-27 04:34:02 +00004994 ses->server->sec_mode &
Jeff Layton4e53a3f2008-12-05 20:41:21 -05004995 SECMODE_PW_ENCRYPT ? true : false,
4996 bcc_ptr);
Steve French7c7b25b2006-06-01 19:20:10 +00004997 else
4998#endif /* CIFS_WEAK_PW_HASH */
Shirish Pargaonkaree2c9252011-01-27 09:58:04 -06004999 rc = SMBNTencrypt(tcon->password, ses->server->cryptkey,
Shirish Pargaonkar9ef59922011-10-20 13:21:59 -05005000 bcc_ptr, nls_codepage);
Steve Frenchf3a31a22015-03-26 19:23:20 -05005001 if (rc) {
5002 cifs_dbg(FYI, "%s Can't generate NTLM rsp. Error: %d\n",
5003 __func__, rc);
5004 cifs_buf_release(smb_buffer);
5005 return rc;
5006 }
Steve Frencheeac8042006-01-13 21:34:58 -08005007
Shirish Pargaonkar540b2e32011-01-18 22:33:54 -06005008 bcc_ptr += CIFS_AUTH_RESP_SIZE;
Steve Frenchfb8c4b12007-07-10 01:16:18 +00005009 if (ses->capabilities & CAP_UNICODE) {
Steve French7c7b25b2006-06-01 19:20:10 +00005010 /* must align unicode strings */
5011 *bcc_ptr = 0; /* null byte password */
5012 bcc_ptr++;
5013 }
Steve Frencheeac8042006-01-13 21:34:58 -08005014 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005015
Jeff Layton38d77c52013-05-26 07:01:00 -04005016 if (ses->server->sign)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005017 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
5018
5019 if (ses->capabilities & CAP_STATUS32) {
5020 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
5021 }
5022 if (ses->capabilities & CAP_DFS) {
5023 smb_buffer->Flags2 |= SMBFLG2_DFS;
5024 }
5025 if (ses->capabilities & CAP_UNICODE) {
5026 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
5027 length =
Steve Frenchacbbb762012-01-18 22:32:33 -06005028 cifs_strtoUTF16((__le16 *) bcc_ptr, tree,
Steve French50c2f752007-07-13 00:33:32 +00005029 6 /* max utf8 char length in bytes */ *
Steve Frencha878fb22006-05-30 18:04:19 +00005030 (/* server len*/ + 256 /* share len */), nls_codepage);
5031 bcc_ptr += 2 * length; /* convert num 16 bit words to bytes */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005032 bcc_ptr += 2; /* skip trailing null */
5033 } else { /* ASCII */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005034 strcpy(bcc_ptr, tree);
5035 bcc_ptr += strlen(tree) + 1;
5036 }
5037 strcpy(bcc_ptr, "?????");
5038 bcc_ptr += strlen("?????");
5039 bcc_ptr += 1;
5040 count = bcc_ptr - &pSMB->Password[0];
Steve Frenchbe8e3b02011-04-29 05:40:20 +00005041 pSMB->hdr.smb_buf_length = cpu_to_be32(be32_to_cpu(
5042 pSMB->hdr.smb_buf_length) + count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005043 pSMB->ByteCount = cpu_to_le16(count);
5044
Steve French133672e2007-11-13 22:41:37 +00005045 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length,
Jeff Layton77499812011-01-11 07:24:23 -05005046 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005047
Linus Torvalds1da177e2005-04-16 15:20:36 -07005048 /* above now done in SendReceive */
Aurelien Aptelb327a712018-01-24 13:46:10 +01005049 if (rc == 0) {
Steve French0e0d2cf2009-05-01 05:27:32 +00005050 bool is_unicode;
5051
Linus Torvalds1da177e2005-04-16 15:20:36 -07005052 tcon->tidStatus = CifsGood;
Steve French3b795212008-11-13 19:45:32 +00005053 tcon->need_reconnect = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005054 tcon->tid = smb_buffer_response->Tid;
5055 bcc_ptr = pByteArea(smb_buffer_response);
Jeff Layton690c5222011-01-20 13:36:51 -05005056 bytes_left = get_bcc(smb_buffer_response);
Jeff Laytoncc20c032009-04-30 07:16:21 -04005057 length = strnlen(bcc_ptr, bytes_left - 2);
Steve French0e0d2cf2009-05-01 05:27:32 +00005058 if (smb_buffer->Flags2 & SMBFLG2_UNICODE)
5059 is_unicode = true;
5060 else
5061 is_unicode = false;
5062
Jeff Laytoncc20c032009-04-30 07:16:21 -04005063
Steve French50c2f752007-07-13 00:33:32 +00005064 /* skip service field (NB: this field is always ASCII) */
Steve French7f8ed422007-09-28 22:28:55 +00005065 if (length == 3) {
5066 if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') &&
5067 (bcc_ptr[2] == 'C')) {
Joe Perchesf96637b2013-05-04 22:12:25 -05005068 cifs_dbg(FYI, "IPC connection\n");
Aurelien Aptelb327a712018-01-24 13:46:10 +01005069 tcon->ipc = true;
5070 tcon->pipe = true;
Steve French7f8ed422007-09-28 22:28:55 +00005071 }
5072 } else if (length == 2) {
5073 if ((bcc_ptr[0] == 'A') && (bcc_ptr[1] == ':')) {
5074 /* the most common case */
Joe Perchesf96637b2013-05-04 22:12:25 -05005075 cifs_dbg(FYI, "disk share connection\n");
Steve French7f8ed422007-09-28 22:28:55 +00005076 }
5077 }
Steve French50c2f752007-07-13 00:33:32 +00005078 bcc_ptr += length + 1;
Jeff Laytoncc20c032009-04-30 07:16:21 -04005079 bytes_left -= (length + 1);
Zhao Hongjiang46b51d02013-06-24 01:57:47 -05005080 strlcpy(tcon->treeName, tree, sizeof(tcon->treeName));
Jeff Laytoncc20c032009-04-30 07:16:21 -04005081
5082 /* mostly informational -- no need to fail on error here */
Jeff Layton90a98b22009-07-20 13:40:52 -04005083 kfree(tcon->nativeFileSystem);
Steve Frenchacbbb762012-01-18 22:32:33 -06005084 tcon->nativeFileSystem = cifs_strndup_from_utf16(bcc_ptr,
Steve French0e0d2cf2009-05-01 05:27:32 +00005085 bytes_left, is_unicode,
Jeff Laytoncc20c032009-04-30 07:16:21 -04005086 nls_codepage);
5087
Joe Perchesf96637b2013-05-04 22:12:25 -05005088 cifs_dbg(FYI, "nativeFileSystem=%s\n", tcon->nativeFileSystem);
Jeff Laytoncc20c032009-04-30 07:16:21 -04005089
Steve Frenchfb8c4b12007-07-10 01:16:18 +00005090 if ((smb_buffer_response->WordCount == 3) ||
Steve French1a4e15a2006-10-12 21:33:51 +00005091 (smb_buffer_response->WordCount == 7))
5092 /* field is in same location */
Steve French39798772006-05-31 22:40:51 +00005093 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
5094 else
5095 tcon->Flags = 0;
Joe Perchesf96637b2013-05-04 22:12:25 -05005096 cifs_dbg(FYI, "Tcon flags: 0x%x\n", tcon->Flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005097 }
5098
Mariusz Kozlowskia8a11d32007-10-03 16:41:24 +00005099 cifs_buf_release(smb_buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005100 return rc;
5101}
5102
Al Viro2e32cf52013-10-03 12:53:37 -04005103static void delayed_free(struct rcu_head *p)
5104{
5105 struct cifs_sb_info *sbi = container_of(p, struct cifs_sb_info, rcu);
5106 unload_nls(sbi->local_nls);
5107 kfree(sbi);
5108}
5109
Al Viro2a9b9952011-06-17 09:27:16 -04005110void
5111cifs_umount(struct cifs_sb_info *cifs_sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005112{
Jeff Laytonb647c352010-10-28 11:16:44 -04005113 struct rb_root *root = &cifs_sb->tlink_tree;
5114 struct rb_node *node;
5115 struct tcon_link *tlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005116
Jeff Layton2de970f2010-10-06 19:51:12 -04005117 cancel_delayed_work_sync(&cifs_sb->prune_tlinks);
5118
Jeff Laytonb647c352010-10-28 11:16:44 -04005119 spin_lock(&cifs_sb->tlink_tree_lock);
5120 while ((node = rb_first(root))) {
5121 tlink = rb_entry(node, struct tcon_link, tl_rbnode);
5122 cifs_get_tlink(tlink);
5123 clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
5124 rb_erase(node, root);
Steve French50c2f752007-07-13 00:33:32 +00005125
Jeff Laytonb647c352010-10-28 11:16:44 -04005126 spin_unlock(&cifs_sb->tlink_tree_lock);
5127 cifs_put_tlink(tlink);
5128 spin_lock(&cifs_sb->tlink_tree_lock);
5129 }
5130 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04005131
Al Virod757d712011-06-17 09:42:43 -04005132 kfree(cifs_sb->mountdata);
Aurelien Aptela6b50582016-05-25 19:59:09 +02005133 kfree(cifs_sb->prepath);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -02005134#ifdef CONFIG_CIFS_DFS_UPCALL
Paulo Alcantarae511d312018-11-14 17:16:44 -02005135 dfs_cache_del_vol(cifs_sb->origin_fullpath);
Paulo Alcantara93d5cb52018-11-14 17:13:25 -02005136 kfree(cifs_sb->origin_fullpath);
5137#endif
Al Viro2e32cf52013-10-03 12:53:37 -04005138 call_rcu(&cifs_sb->rcu, delayed_free);
Steve French50c2f752007-07-13 00:33:32 +00005139}
Linus Torvalds1da177e2005-04-16 15:20:36 -07005140
Pavel Shilovsky286170a2012-05-25 10:43:58 +04005141int
5142cifs_negotiate_protocol(const unsigned int xid, struct cifs_ses *ses)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005143{
5144 int rc = 0;
Jeff Layton198b5682010-04-24 07:57:48 -04005145 struct TCP_Server_Info *server = ses->server;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005146
Pavel Shilovsky286170a2012-05-25 10:43:58 +04005147 if (!server->ops->need_neg || !server->ops->negotiate)
5148 return -ENOSYS;
5149
Jeff Layton198b5682010-04-24 07:57:48 -04005150 /* only send once per connect */
Pavel Shilovsky286170a2012-05-25 10:43:58 +04005151 if (!server->ops->need_neg(server))
Jeff Layton198b5682010-04-24 07:57:48 -04005152 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005153
Pavel Shilovsky286170a2012-05-25 10:43:58 +04005154 rc = server->ops->negotiate(xid, ses);
Jeff Layton198b5682010-04-24 07:57:48 -04005155 if (rc == 0) {
5156 spin_lock(&GlobalMid_Lock);
Jeff Layton7fdbaa12011-06-10 16:14:57 -04005157 if (server->tcpStatus == CifsNeedNegotiate)
Jeff Layton198b5682010-04-24 07:57:48 -04005158 server->tcpStatus = CifsGood;
5159 else
5160 rc = -EHOSTDOWN;
5161 spin_unlock(&GlobalMid_Lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005162 }
Steve French26b994f2008-08-06 05:11:33 +00005163
Jeff Layton198b5682010-04-24 07:57:48 -04005164 return rc;
5165}
Steve French26b994f2008-08-06 05:11:33 +00005166
Pavel Shilovsky58c45c52012-05-25 10:54:49 +04005167int
5168cifs_setup_session(const unsigned int xid, struct cifs_ses *ses,
5169 struct nls_table *nls_info)
Jeff Layton198b5682010-04-24 07:57:48 -04005170{
Pavel Shilovsky58c45c52012-05-25 10:54:49 +04005171 int rc = -ENOSYS;
Jeff Layton198b5682010-04-24 07:57:48 -04005172 struct TCP_Server_Info *server = ses->server;
5173
Jeff Layton198b5682010-04-24 07:57:48 -04005174 ses->capabilities = server->capabilities;
Steve French26b994f2008-08-06 05:11:33 +00005175 if (linuxExtEnabled == 0)
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04005176 ses->capabilities &= (~server->vals->cap_unix);
Steve French20418ac2009-04-30 16:13:32 +00005177
Joe Perchesf96637b2013-05-04 22:12:25 -05005178 cifs_dbg(FYI, "Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d\n",
Steve French96daf2b2011-05-27 04:34:02 +00005179 server->sec_mode, server->capabilities, server->timeAdj);
Jeff Laytoncb7691b2008-08-18 15:41:05 -04005180
Shu Wangf5c4ba82017-09-08 18:48:33 +08005181 if (ses->auth_key.response) {
Steve French2a182872018-03-29 12:16:34 -05005182 cifs_dbg(FYI, "Free previous auth_key.response = %p\n",
Shu Wangf5c4ba82017-09-08 18:48:33 +08005183 ses->auth_key.response);
5184 kfree(ses->auth_key.response);
5185 ses->auth_key.response = NULL;
5186 ses->auth_key.len = 0;
5187 }
5188
Pavel Shilovsky58c45c52012-05-25 10:54:49 +04005189 if (server->ops->sess_setup)
5190 rc = server->ops->sess_setup(xid, ses, nls_info);
5191
Shirish Pargaonkard4e63bd2013-08-29 08:35:09 -05005192 if (rc)
Ronnie Sahlbergafe6f652019-08-28 17:15:35 +10005193 cifs_server_dbg(VFS, "Send error in SessSetup = %d\n", rc);
Shirish Pargaonkar21e73392010-10-21 06:42:55 -05005194
Linus Torvalds1da177e2005-04-16 15:20:36 -07005195 return rc;
5196}
5197
Jeff Layton8a8798a2012-01-17 16:09:15 -05005198static int
5199cifs_set_vol_auth(struct smb_vol *vol, struct cifs_ses *ses)
5200{
Jeff Layton3f618222013-06-12 19:52:14 -05005201 vol->sectype = ses->sectype;
5202
5203 /* krb5 is special, since we don't need username or pw */
5204 if (vol->sectype == Kerberos)
Jeff Layton8a8798a2012-01-17 16:09:15 -05005205 return 0;
Jeff Layton8a8798a2012-01-17 16:09:15 -05005206
5207 return cifs_set_cifscreds(vol, ses);
5208}
5209
Steve French96daf2b2011-05-27 04:34:02 +00005210static struct cifs_tcon *
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08005211cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid)
Jeff Layton9d002df2010-10-06 19:51:11 -04005212{
Jeff Layton8a8798a2012-01-17 16:09:15 -05005213 int rc;
Steve French96daf2b2011-05-27 04:34:02 +00005214 struct cifs_tcon *master_tcon = cifs_sb_master_tcon(cifs_sb);
5215 struct cifs_ses *ses;
5216 struct cifs_tcon *tcon = NULL;
Jeff Layton9d002df2010-10-06 19:51:11 -04005217 struct smb_vol *vol_info;
Jeff Layton9d002df2010-10-06 19:51:11 -04005218
5219 vol_info = kzalloc(sizeof(*vol_info), GFP_KERNEL);
Dan Carpenter803ab972012-01-24 11:39:22 +03005220 if (vol_info == NULL)
5221 return ERR_PTR(-ENOMEM);
Jeff Layton9d002df2010-10-06 19:51:11 -04005222
Jeff Layton9d002df2010-10-06 19:51:11 -04005223 vol_info->local_nls = cifs_sb->local_nls;
5224 vol_info->linux_uid = fsuid;
5225 vol_info->cred_uid = fsuid;
5226 vol_info->UNC = master_tcon->treeName;
5227 vol_info->retry = master_tcon->retry;
5228 vol_info->nocase = master_tcon->nocase;
Steve French3d4ef9a2018-04-25 22:19:09 -05005229 vol_info->nohandlecache = master_tcon->nohandlecache;
Jeff Layton9d002df2010-10-06 19:51:11 -04005230 vol_info->local_lease = master_tcon->local_lease;
5231 vol_info->no_linux_ext = !master_tcon->unix_ext;
Jeff Layton28e11bd2013-05-26 07:01:00 -04005232 vol_info->sectype = master_tcon->ses->sectype;
5233 vol_info->sign = master_tcon->ses->sign;
Jeff Layton9d002df2010-10-06 19:51:11 -04005234
Jeff Layton8a8798a2012-01-17 16:09:15 -05005235 rc = cifs_set_vol_auth(vol_info, master_tcon->ses);
5236 if (rc) {
5237 tcon = ERR_PTR(rc);
5238 goto out;
5239 }
Jeff Layton9d002df2010-10-06 19:51:11 -04005240
5241 /* get a reference for the same TCP session */
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05305242 spin_lock(&cifs_tcp_ses_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04005243 ++master_tcon->ses->server->srv_count;
Suresh Jayaraman3f9bcca2010-10-18 23:29:37 +05305244 spin_unlock(&cifs_tcp_ses_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04005245
5246 ses = cifs_get_smb_ses(master_tcon->ses->server, vol_info);
5247 if (IS_ERR(ses)) {
Steve French96daf2b2011-05-27 04:34:02 +00005248 tcon = (struct cifs_tcon *)ses;
Pavel Shilovsky53e0e112016-11-04 11:50:31 -07005249 cifs_put_tcp_session(master_tcon->ses->server, 0);
Jeff Layton9d002df2010-10-06 19:51:11 -04005250 goto out;
5251 }
5252
5253 tcon = cifs_get_tcon(ses, vol_info);
5254 if (IS_ERR(tcon)) {
5255 cifs_put_smb_ses(ses);
5256 goto out;
5257 }
5258
Steve Frenchce558b02018-05-31 19:16:54 -05005259 /* if new SMB3.11 POSIX extensions are supported do not remap / and \ */
5260 if (tcon->posix_extensions)
5261 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS;
Steve French0fdfef92018-06-28 19:30:23 -05005262
Pavel Shilovsky29e20f92012-07-13 13:58:14 +04005263 if (cap_unix(ses))
Jeff Layton9d002df2010-10-06 19:51:11 -04005264 reset_cifs_unix_caps(0, tcon, NULL, vol_info);
Steve Frenchb3266142018-05-20 23:41:10 -05005265
Jeff Layton9d002df2010-10-06 19:51:11 -04005266out:
Jeff Layton8a8798a2012-01-17 16:09:15 -05005267 kfree(vol_info->username);
Aurelien Aptel97f4b722018-01-25 15:59:39 +01005268 kzfree(vol_info->password);
Jeff Layton9d002df2010-10-06 19:51:11 -04005269 kfree(vol_info);
5270
5271 return tcon;
5272}
5273
Steve French96daf2b2011-05-27 04:34:02 +00005274struct cifs_tcon *
Jeff Layton9d002df2010-10-06 19:51:11 -04005275cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb)
5276{
5277 return tlink_tcon(cifs_sb_master_tlink(cifs_sb));
5278}
5279
Jeff Laytonb647c352010-10-28 11:16:44 -04005280/* find and return a tlink with given uid */
5281static struct tcon_link *
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08005282tlink_rb_search(struct rb_root *root, kuid_t uid)
Jeff Laytonb647c352010-10-28 11:16:44 -04005283{
5284 struct rb_node *node = root->rb_node;
5285 struct tcon_link *tlink;
5286
5287 while (node) {
5288 tlink = rb_entry(node, struct tcon_link, tl_rbnode);
5289
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08005290 if (uid_gt(tlink->tl_uid, uid))
Jeff Laytonb647c352010-10-28 11:16:44 -04005291 node = node->rb_left;
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08005292 else if (uid_lt(tlink->tl_uid, uid))
Jeff Laytonb647c352010-10-28 11:16:44 -04005293 node = node->rb_right;
5294 else
5295 return tlink;
5296 }
5297 return NULL;
5298}
5299
5300/* insert a tcon_link into the tree */
5301static void
5302tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink)
5303{
5304 struct rb_node **new = &(root->rb_node), *parent = NULL;
5305 struct tcon_link *tlink;
5306
5307 while (*new) {
5308 tlink = rb_entry(*new, struct tcon_link, tl_rbnode);
5309 parent = *new;
5310
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08005311 if (uid_gt(tlink->tl_uid, new_tlink->tl_uid))
Jeff Laytonb647c352010-10-28 11:16:44 -04005312 new = &((*new)->rb_left);
5313 else
5314 new = &((*new)->rb_right);
5315 }
5316
5317 rb_link_node(&new_tlink->tl_rbnode, parent, new);
5318 rb_insert_color(&new_tlink->tl_rbnode, root);
5319}
5320
Jeff Layton9d002df2010-10-06 19:51:11 -04005321/*
5322 * Find or construct an appropriate tcon given a cifs_sb and the fsuid of the
5323 * current task.
5324 *
5325 * If the superblock doesn't refer to a multiuser mount, then just return
5326 * the master tcon for the mount.
5327 *
Suresh Jayaraman6ef933a2010-11-03 10:53:49 +05305328 * First, search the rbtree for an existing tcon for this fsuid. If one
Jeff Layton9d002df2010-10-06 19:51:11 -04005329 * exists, then check to see if it's pending construction. If it is then wait
5330 * for construction to complete. Once it's no longer pending, check to see if
5331 * it failed and either return an error or retry construction, depending on
5332 * the timeout.
5333 *
5334 * If one doesn't exist then insert a new tcon_link struct into the tree and
5335 * try to construct a new one.
5336 */
5337struct tcon_link *
5338cifs_sb_tlink(struct cifs_sb_info *cifs_sb)
5339{
5340 int ret;
Eric W. Biederman6d4a0832013-02-06 01:48:56 -08005341 kuid_t fsuid = current_fsuid();
Jeff Layton9d002df2010-10-06 19:51:11 -04005342 struct tcon_link *tlink, *newtlink;
5343
5344 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
5345 return cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
5346
5347 spin_lock(&cifs_sb->tlink_tree_lock);
Jeff Laytonb647c352010-10-28 11:16:44 -04005348 tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
Jeff Layton9d002df2010-10-06 19:51:11 -04005349 if (tlink)
5350 cifs_get_tlink(tlink);
5351 spin_unlock(&cifs_sb->tlink_tree_lock);
5352
5353 if (tlink == NULL) {
5354 newtlink = kzalloc(sizeof(*tlink), GFP_KERNEL);
5355 if (newtlink == NULL)
5356 return ERR_PTR(-ENOMEM);
Jeff Laytonb647c352010-10-28 11:16:44 -04005357 newtlink->tl_uid = fsuid;
Jeff Layton9d002df2010-10-06 19:51:11 -04005358 newtlink->tl_tcon = ERR_PTR(-EACCES);
5359 set_bit(TCON_LINK_PENDING, &newtlink->tl_flags);
5360 set_bit(TCON_LINK_IN_TREE, &newtlink->tl_flags);
5361 cifs_get_tlink(newtlink);
5362
Jeff Layton9d002df2010-10-06 19:51:11 -04005363 spin_lock(&cifs_sb->tlink_tree_lock);
5364 /* was one inserted after previous search? */
Jeff Laytonb647c352010-10-28 11:16:44 -04005365 tlink = tlink_rb_search(&cifs_sb->tlink_tree, fsuid);
Jeff Layton9d002df2010-10-06 19:51:11 -04005366 if (tlink) {
5367 cifs_get_tlink(tlink);
5368 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04005369 kfree(newtlink);
5370 goto wait_for_construction;
5371 }
Jeff Layton9d002df2010-10-06 19:51:11 -04005372 tlink = newtlink;
Jeff Laytonb647c352010-10-28 11:16:44 -04005373 tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
5374 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton9d002df2010-10-06 19:51:11 -04005375 } else {
5376wait_for_construction:
5377 ret = wait_on_bit(&tlink->tl_flags, TCON_LINK_PENDING,
Jeff Layton9d002df2010-10-06 19:51:11 -04005378 TASK_INTERRUPTIBLE);
5379 if (ret) {
5380 cifs_put_tlink(tlink);
NeilBrown74316202014-07-07 15:16:04 +10005381 return ERR_PTR(-ERESTARTSYS);
Jeff Layton9d002df2010-10-06 19:51:11 -04005382 }
5383
5384 /* if it's good, return it */
5385 if (!IS_ERR(tlink->tl_tcon))
5386 return tlink;
5387
5388 /* return error if we tried this already recently */
5389 if (time_before(jiffies, tlink->tl_time + TLINK_ERROR_EXPIRE)) {
5390 cifs_put_tlink(tlink);
5391 return ERR_PTR(-EACCES);
5392 }
5393
5394 if (test_and_set_bit(TCON_LINK_PENDING, &tlink->tl_flags))
5395 goto wait_for_construction;
5396 }
5397
5398 tlink->tl_tcon = cifs_construct_tcon(cifs_sb, fsuid);
5399 clear_bit(TCON_LINK_PENDING, &tlink->tl_flags);
5400 wake_up_bit(&tlink->tl_flags, TCON_LINK_PENDING);
5401
5402 if (IS_ERR(tlink->tl_tcon)) {
5403 cifs_put_tlink(tlink);
5404 return ERR_PTR(-EACCES);
5405 }
5406
5407 return tlink;
5408}
Jeff Layton2de970f2010-10-06 19:51:12 -04005409
5410/*
5411 * periodic workqueue job that scans tcon_tree for a superblock and closes
5412 * out tcons.
5413 */
5414static void
5415cifs_prune_tlinks(struct work_struct *work)
5416{
5417 struct cifs_sb_info *cifs_sb = container_of(work, struct cifs_sb_info,
5418 prune_tlinks.work);
Jeff Laytonb647c352010-10-28 11:16:44 -04005419 struct rb_root *root = &cifs_sb->tlink_tree;
Colin Ian King37e12f52018-01-17 09:52:39 +00005420 struct rb_node *node;
Jeff Laytonb647c352010-10-28 11:16:44 -04005421 struct rb_node *tmp;
5422 struct tcon_link *tlink;
Jeff Layton2de970f2010-10-06 19:51:12 -04005423
Jeff Laytonb647c352010-10-28 11:16:44 -04005424 /*
5425 * Because we drop the spinlock in the loop in order to put the tlink
5426 * it's not guarded against removal of links from the tree. The only
5427 * places that remove entries from the tree are this function and
5428 * umounts. Because this function is non-reentrant and is canceled
5429 * before umount can proceed, this is safe.
5430 */
5431 spin_lock(&cifs_sb->tlink_tree_lock);
5432 node = rb_first(root);
5433 while (node != NULL) {
5434 tmp = node;
5435 node = rb_next(tmp);
5436 tlink = rb_entry(tmp, struct tcon_link, tl_rbnode);
5437
5438 if (test_bit(TCON_LINK_MASTER, &tlink->tl_flags) ||
5439 atomic_read(&tlink->tl_count) != 0 ||
5440 time_after(tlink->tl_time + TLINK_IDLE_EXPIRE, jiffies))
5441 continue;
5442
5443 cifs_get_tlink(tlink);
5444 clear_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
5445 rb_erase(tmp, root);
5446
Jeff Layton2de970f2010-10-06 19:51:12 -04005447 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Laytonb647c352010-10-28 11:16:44 -04005448 cifs_put_tlink(tlink);
5449 spin_lock(&cifs_sb->tlink_tree_lock);
5450 }
5451 spin_unlock(&cifs_sb->tlink_tree_lock);
Jeff Layton2de970f2010-10-06 19:51:12 -04005452
Jeff Laytonda472fc2012-03-23 14:40:53 -04005453 queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
Jeff Layton2de970f2010-10-06 19:51:12 -04005454 TLINK_IDLE_EXPIRE);
5455}